I've recently set up a GPG key for PGP mail encryption and for signing commits in Git.
It's quite a minefield with various guides available on the web. I thought I'd give my take—this is my guide for how I created a GPG key and set up the required configs to be able to sign commits in Git.
🛠️ Prerequisites
I used GnuPG running on macOS 15.5. However, this process should be very similar on Linux and Windows (WSL).
Make sure you have GnuPG set up already. On macOS, I installed this with Homebrew:brew install gnupg
🚀 Install & Setup
1️⃣ List All Keys Stored in GPG
This is how you list keys already set up on your system. If this is a fresh install, there should be no existing keys.
- Public:
gpg --list-keys
- Private:
gpg --list-secret-keys
2️⃣ Create a GPG Public-Private Key Pair
Run: gpg --full-generate-key
Select:
- 'RSA and RSA' – You could select 'ECC (sign and encrypt)', but RSA is more widely supported and has been around much longer.
- Key size: '4096'
- Key expiry: '0' – It's probably best to set an expiry for the key, but I don't want to keep updating my key often, so I prefer no expiry.
- Then enter your name and email address.
3️⃣ Find Your Key Identifier
Now your key has been generated, we need to find the key identifier as this will be used to perform actions on the key such as exporting and backup.
Run this command to list all of your keys: gpg --list-secret-keys --keyid-format=long
It will return something like this:
sec rsa4096/171UN2R685ITSJFW 2025-10-01 [SC]
J8YO9LZFUXXVH2AO6I6K5W1O171UN2R685ITSJFW
uid [ultimate] Your Name <yourname@gmail.com>
ssb rsa4096/RVKVAHYFAWPYOT2J 2025-10-01 [E]
Notice in this example where you see 171UN2R685ITSJFW
—this will be your key identifier.
🚨 Note: Throughout the next steps, this key identifier will be used in the examples. If you're running these commands for yourself, replace
171UN2R685ITSJFW
with your key.
4️⃣ Export Keys
That's it! You can now export your public and private keys.
🚨 Remember: Ensure you are the only one who has access to the private key. For someone to send you an encrypted message, provide them with your public key. This public key is used to encrypt the message for you to decrypt with your private key. The same applies if you're sending a message to a recipient; you must have the recipient's public key to encrypt the message for them.
- Export a public key:
gpg --armor --export 171UN2R685ITSJFW
- Export a private key:
gpg --armor --export-secret-key 171UN2R685ITSJFW
For public keys, I usually save these with a .asc
file extension, e.g., your-name.asc
. For the private key, save this as a .key
file extension.
5️⃣ Further Steps
🌍 Pushing Key to a Public Key Server
It's recommended you push your public key to a trusted public key server so it can be verified by others.
For example, this will push the key to the 'OpenPGP Key' server:gpg --keyserver hkps://keys.openpgp.org --send-keys 171UN2R685ITSJFW
🔏 Configure Git to Sign Commits with Key
- Upload your public key to GitHub. This will be in your settings page: github.com/settings/keys.
- If you have previously configured Git to use a different key format when signing with
--gpg-sign
, unset this configuration so the default format of OpenPGP will be used:git config --global --unset gpg.format
- Tell Git to use your key identifier:
git config --global user.signingkey 171UN2R685ITSJFW
- Optionally, to configure Git to sign all commits and tags by default, enter the following commands:
git config --global commit.gpgsign true
git config --global tag.gpgSign true
📚 Further Reading
💾 Backup/Restore Keys
Usually, just storing your public and private keys will be good enough. However, GnuPG allows you to easily backup/restore your keys.
Running the below will backup/restore keys from the backupkeys.pgp
file. This file is generated in the same folder where you're running this command in your terminal.
- Backup keys:
gpg --output backupkeys.pgp --armor --export-secret-keys 171UN2R685ITSJFW
- Restore keys:
gpg --import-options restore --import backupkeys.pgp
🗑️ Deleting Keys from GnuPG
If you need to delete keys, you can do so with the commands below:
- Delete a private key:
gpg --delete-secret-keys 171UN2R685ITSJFW
- Delete a public key:
gpg --delete-keys 171UN2R685ITSJFW
🍏 macOS Troubleshooting
I encountered some issues specifically when entering my key's passphrase in Visual Studio Code.
To fix these issues, I had to install 'Pinentry' and make some changes to my ZShell config. See the notes below:
⚙️ Configure ZShell GPG_TTY Variable
You need to export the GPG_TTY variable into the ZShell. I found this when looking here for the Bash shell.
For more debugging on errors, see: https://www.betterbugs.io/blog/fix-error-gpg-failed-to-sign-the-data-git.
- Open the ZShell config:
sudo nano ~/.zshrc
- Add this line to the bottom of the file, then save:
export GPG_TTY=$(tty)
- Source the config to pick up the changes:
source ~/.zshrc
- Run this command to view any errors. It should display your public key if successful:
echo "hello" | gpg -bsau 171UN2R685ITSJFW
🔑 Configure pinentry-mac for Interactive Passphrase
To allow the passphrase prompt to appear in apps such as Visual Studio Code, install pinentry: brew install pinentry-mac
These are based on the notes from: https://stackoverflow.com/questions/63440623/no-gpg-passphrase-prompt-in-visual-studio-code-on-windows-10-for-signed-git-comm
- Edit
sudo nano ~/.gnupg/gpg.conf
to have this content:
use-agent
default-key 171UN2R685ITSJFW
- Edit
sudo nano ~/.gnupg/gpg-agent.conf
to have this content:
default-cache-ttl 34560000
max-cache-ttl 34560000
pinentry-program /opt/homebrew/bin/pinentry-mac
- Edit the shell config to ensure these lines exist:
sudo nano ~/.zshrc
export GPG_TTY=$(tty)
export GPG_AGENT_INFO=${HOME}/.gnupg/S.gpg-agent:0:1
- Source the config to pick up the changes:
source ~/.zshrc
- Reload gpg-agent: To apply the changes, run:
sudo pkill -TERM gpg-agent
followed bygpg-connect-agent reloadagent /bye
✨ Good luck you're now able to send/receive encrypted messages and sign your Git commits!
You can find my Public key here - I use Keybase to host my key, it also allows you to prove your identity via various methods.
Also, once you upload your public to GitHub, you can access a hosted copy at: https://github.com/your-username.gpg
, example mine is hosted at https://github.com/ryanfitton.gpg.