Contents

How to use a GPG Smartcard for Git and SSH

   Sep 14, 2025     12 min read

YubiKey Stock Photo

A guide on using a GPG compatible SmartCard such as the NitroKey or YubiKey for Git and SSH.

This guide assumes that you are using a YubiKey and NixOS, but should largely be reusable for other SmartCards and Linux Operating Systems.

NOTE: Due to current limitations, you cannot have multiple SmartCards that all work simultaneously using the same keys. You can however copy the backed up keys to a new SmartCard, and only need to change the configuration on your client device(s), not any servers. This is because GPG will look for the serial number of the SmartCard when completing operations, which will only ever point to one card at a time. Also, the stubs created will be unique for each SmartCard despite using the same underlying keys. At time of writing, there are no reasonable workarounds for this issue.

References

Requirements

  • A computer to perform the key generation and SmartCard setup
  • A SmartCard that is GPG compatible
  • A USB Storage Device to be used for backing up the GPG secret keys

Steps

Configure computer for setup process

Select a computer that you would like to use for generating the secret keys and uploading them to your SmartCard(s). This should be a secure computer that you trust and personally control.

NOTE: Using a live boot operating system during this process may reduce the risk of your secret keys being cached on disk and later retrieved by an attacker, but is not necessary to follow this guide. Likewise, having a computer with hardware kill switches for networking, or removing the networking equipment during key generation and upload may also reduce the chances of the keys being stolen by an attacker. However, this is almost certainly overkill for the vast majority of people, and simply using a personal device and turning off the network connection via software should be sufficient in most cases.

On that computer, you will need to install GnuPG and enable SmartCard support.

Debian-based

Install the GPG smartcard daemon and enable SSH support for GPG.

sudo apt install scdaemon -y
echo "enable-ssh-support" | tee -a ~/.gnupg/gpg-agent.conf

Then in your ~/.bashrc (or equivalent file if using another shell, e.g. ~/.zshrc for zsh) add the following to the end of the file:

export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
gpgconf --launch gpg-agent

You may need to log out and back in to refresh your gpg-agent session.

NixOS

Within your Nix Configuration, add the following:

{
  # Install GnuPG with SSH Support
  programs.gnupg.agent = {
    enable = true;
    enableSSHSupport = true;
  };

  # Enable SmartCard udev rules
  hardware.gpgSmartcards.enable = true;
}

Using home manager and Nix Flakes (trust me, you want both if you aren’t using them yet), create a .bashrc file with the following in addition to your other bashrc config:

export SSH_AUTH_SOCK="/run/user/$UID/gnupg/S.gpg-agent.ssh"
gpgconf --launch gpg-agent

Use home manager to source the .bashrc file (once you’re done following the rest of the setup, you’ll also want to add/uncomment .gitconfig and sshcontrol):

{

  home.file = {
    ".bashrc".source = ./.bashrc;
    # ".gitconfig".source = ./.gitconfig;
    # ".gnupg/sshcontrol".source = ./sshcontrol;
  };
}

The first half is where the file will be symlinked to within your home folder, while the second half is the relative path where the config lives from the perspective of the home manager nix file. I will go more in-depth on how to configure this in a follow up guide on getting started with NixOS.

Rebuild your system to use the new config.

Generating the GPG keys

Create a temp folder to work from and cd into it:

mkdir -p ~/temp
cd ~/temp

Generate a passphrase using your Password Manager, and copy it to the clipboard. You’ll need it when generating the main key. You will need this beyond initial setup, so ensure it is saved in your password manager. You may also want to save some time and create a User PIN, Admin PIN, and Unlock PIN. Despite being called PINs, these can contain any characters not just numbers. The User PIN is what you’ll use on a daily basis when making SSH connections or signing git commits. The other three passwords will be used infrequently.

In other words, create a single “SmartCard” entry in your password manager with four passwords:

  • GPG Passphrase - Used when importing stubs on new machines
  • User PIN - Used on a daily basis for SSH and Git Commits
  • Admin PIN - Used when changing SmartCard settings
  • Unlock PIN - Used if you accidentally use the incorrect user pin too many times and lock the device

NOTE: There are some concerns around ECC cryptography potentially having NSA backdoors and being susceptible to future quantum computer attacks. This guide recommends the use of RSA 4096 keys, but check for the currently recommended best practices on GPG keys as they may have changed since time of writing.

Generate the main key (used for signing the subkeys):

gpg --full-generate-key

Use the following settings:

  • 4 - RSA (sign only)
  • Keysize - 4096
  • Expires - 0 (never)
  • Y (confirm key expiration)
  • Name - Your Name
  • Email - gpg@example.com
  • Comment (leave blank)
  • Ensure you have your desired gpg passphrase copied to your keyboard
  • O - Okay, continue
  • Paste gpg passphrase when prompted

This will output the results, and give you a long string after “pub” that is the ID of your gpg key. Copy that gpg id for use in the following command. If you cleared the terminal before seeing it, you can also find the gpg key id at any time by running gpg -k.

Now edit the key you just generated, and add information for ssh and git commits:

gpg --edit-key <gpg-id>

Optionally, use the following commands if you have emails specific to SSH and Git Commits that differ from your gpg email:

  • adduid - SSH Identity
    • Your Name
    • Email - ssh@example.com
  • adduid - Git Commit Identity
    • Your Name
    • Email - git-commit@example.com
  • uid 1 - Select first UID (GPG identity when you created the main key)
  • primary - Set the selected UID (1) as primary
  • save

Now generate the subkeys:

gpg --expert --edit-key <gpg-id>
  • Copy your gpg passphrase again, it’ll prompt you for it when adding subkeys
  • addkey - Sign Only (e.g. sending and receiving encrypted email)
    • 4 - RSA (sign only)
    • Keysize - 4096
    • Expires - 0 (never)
    • Y (confirm key expiration)
    • Y (really create)
    • Paste gpg passphrase when prompted
  • addkey - Encrypt Only (e.g. gpg git commit signing)
    • 6 - RSA (encrypt only)
    • Keysize - 4096
    • Expires - 0 (never)
    • Y (confirm key expiration)
    • Y (really create)
    • Paste gpg passphrase when prompted
  • addkey - Authenticate Only (e.g. SSH)
    • 8 - RSA (custom)
    • S - Disable Signing
    • E - Disable Encrypt
    • A - Enable Authenticate
    • Q - Save
    • Keysize - 4096
    • Expires - 0 (never)
    • y (confirm key expiration)
    • y (really create)
    • Paste gpg passphrase when prompted
  • save

Generate a revocation certificate in case you lose the smartcard and need to mark your keys as compromised:

gpg --gen-revoke <gpg-id> >> ./revoke.asc
  • Copy your gpg passphrase again
  • y - Yes create a revocation certificate
  • 1 - Reason: Key has been compromised
  • Optional description - leave blank (just hit enter again)
  • y - Yes this is okay, generate
  • Paste gpg passphrase when prompted

Also, create a backup of the original secret keys:

gpg -a --export-secret-key <gpg-id> >> ./main.key
gpg -a --export-secret-subkeys <gpg-id> >> ./subkeys.key

NOTE: The secret keys will be deleted from your machine when porting them over to the SmartCard. If you want to keep a backup to allow switching to a new SmartCard in the future, it is critical to do this backup before proceeding.

Configuring the SmartCard

Plug in your SmartCard now.

Edit the SmartCard configuration using:

gpg --card-edit

NOTE: Because you don’t have the opportunity to copy the new unlock pin after it asks you for the admin pin, I recommend changing the unlock pin before changing the admin pin to avoid needing another device to look at the passwords you generated and typing it manually.

Use the following commands:

  • admin
  • passwd
  • 1 - change PIN (user pin)
    • Enter current user pin (usually defaults to 123456)
    • Enter new user pin
    • Repeat new user pin
  • 4 - change Unlock PIN
    • Enter current admin pin (usually defaults to 12345678)
    • Enter new unlock pin
    • Repeat new unlock pin
  • 3 - change Admin PIN
    • Enter current admin pin (usually defaults to 12345678)
    • Enter new admin pin
    • Repeat new admin pin
  • q - Quit passwd / Return to main menu
  • name - Your Name
  • login - Your Username
  • lang - en
  • quit

Now copy the gpg keys from your computer to the SmartCard (this will delete the secret keys from your computer, see above note on backups):

gpg --edit-key <gpg-id>
  • toggle - Enable selecting of subkeys
  • key 1 - Enable sign key
  • keytocard
  • 1 (signature key)
  • key 1 - Disable sign key
  • key 2 - Enable encrypt key
  • keytocard
  • 2 (encrypt key)
  • key 2 - Disable encrypt key
  • key 3 - Enable authenticate key
  • keytocard
  • 3 (authenticate key)
  • save

The gpg keys have now been automatically deleted and replaced with stubs pointing at your SmartCard. You’ll want to save these stubs for importing on other computers using the following command:

gpg -a --output stubs.asc --export-secret-keys <gpg-id>

Configure SSH to use your SmartCard

Grab the keygrip for your authenticate subkey using:

gpg --with-keygrip -K

Save it as ~/.gnupg/sshcontrol (or within your NixOS config as sshcontrol and uncomment the relevant home manager line)

Grab your ssh public key via:

ssh-add -L

It should look like:

ssh-rsa <long string here> (none)

Save this in your password manager, it will be used when adding your public key to ssh servers.

Configure Git to use your SmartCard

Grab the long format ID for your sign only subkey:

gpg -K --keyid-format LONG

Add it to your .gitconfig, removing the rsa4096/ first:

[user]
  name = "Your Name"
  email = git-commit@example.com
  signingKey = <sign only subkey id in long format>

If using NixOS, uncomment the .gitconfig line in home manager.

Grab your gpg public key for uploading to GitHub or other Git servers:

gpg -a --export <gpg-id> > smartcard.pub

Backup GPG files

Plug in your backup USB drive, then open a terminal within your backup USB drive and run:

mkdir -p ./smartcard-backup
cd ./smartcard-backup
cp ~/temp/* ./

NOTE: Do NOT use mv to move the files. It is more secure to copy, then shred the original in the following step.

Cleanup

cd ~/temp
shred -u -z ./*
cd ..
rm -r ~/temp

If you used a live boot USB for following this guide, it would now be wise to securely erase the drive to remove the possibility of recovering the secret keys from a cache that may have been missed.

Adding to GitHub

Use the SSH public key and GPG public key, and add them to your GitHub account.

Now test your SSH keys with:

ssh -T git@github.com

If working correctly, it should ask you to plug in your SmartCard if unplugged, then request your User PIN to unlock the SmartCard until unplugged.

If successful, it should output:

Hi github-username! You've successfully authenticated, but GitHub does not provide shell access.

You can now test creating a new git commit, and pushing to GitHub. It should show as verified using your GPG key. You can also check this locally via:

git log --show-signature

Which should show some lines mentioning gpg and a good signature from your gpg key.

If so, congratulations, you should be good to go!

Setting up a new computer

Follow the same install process at the beginning of the guide on the new computer, and then import the SmartCard stubs with:

gpg --import stubs.asc

You will need to edit the stubs to have ultimate trust (defaults to unknown):

gpg --edit-key gpg@example.com

Use the following commands:

  • trust - Set trust level
  • 5 - Ultimate trust
  • y - Yes, I’m sure
  • save

Log out and back in to refresh gpg-agent session, then insert your SmartCard and use:

gpg --card-status

It should tell you about the SmartCard and have your four keys (main, and three subkeys).

Test that things are working by using:

ssh-add -L

It should return your SSH public key. If it doesn’t, something went wrong.

Your new computer should now be ready to use!