Backup & Restore GPG Key

First, identify which key you want to back up:

$ gpg --list-secret-keys --keyid-format=long

Find your key ID — it appears after rsa4096/ (or ed25519/) on the sec line:

sec   rsa4096/ABCDEF1234567890 2026-03-13 [SC] [expires: 2027-03-13]
      C1CB417F5F2F9E4D147F01C4ABCDEF1234567890
uid                 [ultimate] John Doe <john.doe@datawords.asia>
ssb   rsa4096/1234567890ABCDEF 2026-03-13 [E] [expires: 2027-03-13]

Export your private key (this is the critical part — without it you cannot sign commits):

$ gpg --armor --export-secret-keys ABCDEF1234567890 > gpg-private-key.asc

Also export your public key:

$ gpg --armor --export ABCDEF1234567890 > gpg-public-key.asc

Export the trust database so your key trust level is preserved:

$ gpg --export-ownertrust > gpg-ownertrust.txt
Important: The private key file (gpg-private-key.asc) gives full access to your GPG identity. Treat it like a password — never send it over email or messaging apps in plain text.
Tip: You can verify the exported files are valid before transferring:
$ gpg --show-keys gpg-private-key.asc
$ gpg --show-keys gpg-public-key.asc

Move the exported files to your new machine securely. Here are recommended methods:

Option 1: USB drive (recommended)

# Copy to USB
$ cp gpg-private-key.asc gpg-public-key.asc gpg-ownertrust.txt /media/usb/

# After copying to new machine, securely delete from USB
$ shred -u /media/usb/gpg-private-key.asc

Option 2: SCP (over SSH)

$ scp gpg-private-key.asc gpg-public-key.asc gpg-ownertrust.txt user@newmachine:~/
Important: After the transfer is complete, delete the exported files from the source machine and any transfer media:
$ shred -u gpg-private-key.asc gpg-public-key.asc gpg-ownertrust.txt
Tip: shred -u overwrites the file content before deleting. On macOS, use rm -P instead. On Windows, simply delete the files — shred is not available.

On the new machine, import the keys and trust database:

Import the private key (this also imports the public key):

$ gpg --import gpg-private-key.asc
[pinentry dialog will appear — enter your passphrase]
gpg: key ABCDEF1234567890: secret key imported
gpg: Total number processed: 1
gpg:              imported: 1
gpg:       secret keys read: 1
gpg:   secret keys imported: 1

Import the public key (in case it was not included with the private key export):

$ gpg --import gpg-public-key.asc

Restore the trust database:

$ gpg --import-ownertrust gpg-ownertrust.txt

If you did not back up the trust database, set the trust level manually:

$ gpg --edit-key ABCDEF1234567890
gpg> trust
  1 = I don't know or won't say
  2 = I do NOT trust
  3 = I trust marginally
  4 = I trust fully
  5 = I trust ultimately
  m = back to the main menu

Your decision? 5
gpg> quit

Re-configure Git to use the key for commit signing:

$ gpg --list-secret-keys --keyid-format=long
# Find your key ID from the output
$ git config --global user.signingkey ABCDEF1234567890
$ git config --global commit.gpgsign true
Tip: After verifying the import was successful (next step), delete the exported files from the new machine too:
$ shred -u gpg-private-key.asc gpg-public-key.asc gpg-ownertrust.txt

Confirm the key was imported correctly:

$ gpg --list-secret-keys --keyid-format=long
sec   rsa4096/ABCDEF1234567890 2026-03-13 [SC] [expires: 2027-03-13]
      C1CB417F5F2F9E4D147F01C4ABCDEF1234567890
uid                 [ultimate] John Doe <john.doe@datawords.asia>
ssb   rsa4096/1234567890ABCDEF 2026-03-13 [E] [expires: 2027-03-13]

Make sure the trust level shows [ultimate]. If it shows [unknown], go back and set the trust level.

Create a test commit to verify signing works:

$ cd /path/to/any/repo
$ git commit --allow-empty -m "test: verify GPG signing on new machine"

Check that the commit is signed:

$ git log --show-signature -1
commit abc123...
gpg: Signature made ...
gpg: Good signature from "John Doe <john.doe@datawords.asia>"
...

Push to Gitea and check that the commit shows the green "Verified" badge.

Done! Your GPG key has been successfully migrated. All commits from this machine will be signed and verified on Gitea.
ProblemSolution
gpg: decryption failed: No secret key The private key was not imported. Run gpg --import gpg-private-key.asc again and make sure no errors appear.
Trust level shows [unknown] instead of [ultimate] Run gpg --edit-key KEY_ID, then trust, select 5 (ultimate), and quit.
gpg: signing failed: No secret key when committing Check that git config user.signingkey matches your key ID. Run gpg --list-secret-keys --keyid-format=long to confirm.
error: gpg failed to sign the data Run export GPG_TTY=$(tty) and retry. Add this to your shell profile (~/.bashrc or ~/.zshrc).
Key shows as expired after import Extend the expiration: gpg --edit-key KEY_IDexpire → set new date → save. Then re-export the public key and update it on Gitea.
Passphrase dialog does not appear Install pinentry for your platform: brew install pinentry-mac (macOS), sudo apt install pinentry-curses (Linux). Then restart gpg-agent: gpgconf --kill gpg-agent.