How to Configure Git SSH Keys and GPG Signing on Fedora

Generate SSH and GPG keys on Fedora and configure Git to use them for authentication and commit signing.

You pushed a commit and GitHub flagged it as unsigned

You push a commit to a remote repository and the platform marks it as Unverified. Your terminal works fine, but the web interface shows a yellow warning next to every commit. You want green checkmarks and cryptographic proof that you actually wrote the code. Fedora makes this straightforward, but the pieces live in three different tools: ssh-keygen, gpg, and git. You need to generate the keys, load them into the credential agent, and tell Git to attach the signature to every commit.

Why Git and GPG need to talk to each other

Git tracks changes. It does not track identity by default. When you commit, Git records the name and email you configured in your local settings. Anyone can type git config user.name "Someone Else" and claim authorship. The name and email are just metadata. They offer zero cryptographic guarantee.

SSH keys solve authentication. They prove you are who you say you are when you push or pull from a remote host. The remote server checks your public key against the private key on your machine. If they match, the server grants you write access.

GPG keys solve attribution. They cryptographically sign the commit object itself. The signature travels with the repository. Anyone with your public GPG key can verify the commit came from your machine and was not altered in transit. Think of SSH as the key to your office door. Think of GPG as the wax seal on a letter. You need both for a complete workflow.

Run the key generation commands first. The agent will handle the rest.

Generate the keys

Start with the SSH key. Modern Fedora ships with openssh preinstalled. Ed25519 is the standard algorithm. It is fast, secure, and widely supported across Git hosting platforms. Run the generation command. You will be prompted for a file path and a passphrase. Use the default path. Set a strong passphrase. The passphrase protects the key if your laptop is stolen.

ssh-keygen -t ed25519 -C "your_email@example.com"
# -t ed25519 selects the modern elliptic curve algorithm
# -C adds a comment string for identification, not authentication
# Press Enter to accept the default path ~/.ssh/id_ed25519
# Enter a passphrase twice. Leave it blank only for throwaway machines

Add the key to the agent. Fedora uses gpg-agent as the default SSH agent since version 38. The ssh-add command loads the private key into memory so you do not type the passphrase on every push. The agent caches the credential until you reboot or lock your screen.

ssh-add ~/.ssh/id_ed25519
# Loads the private key into the running gpg-agent process
# You will be prompted for the passphrase once per session
# The agent caches the key until you reboot or lock your screen

Now generate the GPG key. GPG handles symmetric encryption, digital signatures, and key management. You need a primary key and a subkey for signing. The interactive wizard handles this. Choose the default RSA algorithm and 4096 bits. Set an expiration date. One year is standard practice. It forces you to rotate keys before they become obsolete.

gpg --full-generate-key
# Launches the interactive key generation wizard
# Select option 4 for RSA (sign only) to keep the primary key safe
# Choose 4096 bits for maximum compatibility with older servers
# Set expiration to 1y. You can extend it later without regenerating
# Enter your real name and email. The comment field is optional
# Confirm the details and enter the passphrase

Generate the keys once. Rotate them annually. Do not skip the expiration date.

Wire Git to your keys

Git needs to know which GPG key to use and whether to sign commits automatically. The --global flag applies the setting to every repository on your machine. Use --local if you want different keys for work and personal projects. Fedora stores user config in ~/.config/git/config rather than the legacy ~/.gitconfig. The git config command handles the path automatically. Never edit /usr/lib/git-core/ files. Those ship with the package and get overwritten on upgrade.

gpg --list-secret-keys --keyid-format LONG
# Prints your secret keys with full 16-character identifiers
# Copy the ID under sec. It looks like A1B2C3D4E5F6G7H8
# Do not copy the fingerprint. Git expects the key ID
git config --global user.signingkey A1B2C3D4E5F6G7H8
# Tells Git which GPG key to use for cryptographic signatures
# Replace the ID with the one from the previous command
# This setting lives in ~/.config/git/config
git config --global commit.gpgsign true
# Automatically signs every commit you make
# You can override this per-commit with git commit --no-gpg-sign
# The agent will prompt for your passphrase on the first sign

Set the global config. Test it in a sandbox before touching production repositories.

Verify the setup

Test the signature before pushing. Create a test commit in a temporary directory. Check the log with the --show-signature flag. Git will call GPG to verify the cryptographic hash. The output will show whether the signature is valid and which key produced it.

mkdir /tmp/git-test && cd /tmp/git-test
git init
echo "test" > file.txt
git add file.txt
git commit -m "Signed test commit"
# Creates a commit and triggers the GPG signing process
# The agent will ask for your passphrase if it is not cached
git log --show-signature -1
# Displays the commit details and GPG verification result
# Look for "Good signature" and your key ID
# If it says "BAD signature", your key ID or agent is misconfigured

Clean up the test directory. The signature is embedded in the commit object. It will travel to GitHub, GitLab, or your self-hosted Gitea instance. Push the test commit to a private repository. Check the web interface. The warning should be gone.

Run the verification command. Do not skip the sandbox test.

Common pitfalls and what the error looks like

The most common failure is a missing GPG agent socket. Fedora's desktop session starts gpg-agent automatically. Headless servers do not. If you see the following error, the agent cannot prompt for a passphrase:

gpg: signing failed: Inappropriate ioctl for device

Run gpgconf --launch gpg-agent to start it manually. Add pinentry-mode loopback to ~/.gnupg/gpg-agent.conf if you run Git inside a script or CI pipeline. The loopback mode reads the passphrase from the terminal instead of spawning a GUI dialog. Restart the agent with gpgconf --kill gpg-agent after editing the config file.

Another frequent issue is the wrong key format. Git expects the 16-character key ID, not the 40-character fingerprint. If you paste the fingerprint, Git will complain with gpg: no default secret key: Bad passphrase. Run gpg --list-secret-keys --keyid-format LONG again. Copy only the short ID.

SSH key permissions also cause silent failures. The ~/.ssh directory must be 700. The private key file must be 600. If the permissions are too open, ssh-add will refuse to load the key and print:

Permissions 0644 for '~/.ssh/id_ed25519' are too open.

Fix it with chmod 700 ~/.ssh && chmod 600 ~/.ssh/id_ed25519. OpenSSH enforces this strictly. It will not negotiate with you.

Check the agent socket first. Fix permissions before blaming the key.

When to use SSH keys versus GPG signing

Use SSH keys when you need to authenticate to a remote Git host. Use GPG signing when you need to prove authorship of a specific commit. Use both when you want a complete security chain from local commit to remote push. Stay on the default commit.gpgsign false if you only sign tags and release commits. Use git commit -S for manual signing when you work across multiple machines with different keys.

Pick the tool that matches your threat model. Do not sign blindly.

Where to go next