Git, SSH, and GPG¶
These instructions should work for Linux, macOS, and Windows.
Prerequisites
Install Git, SSH, GPG, and the GitHub CLI before proceeding. Follow the Linux setup guide, macOS setup guide, or Windows setup guide.
Configure Git¶
Configure your username and email:
git config --global user.name "your-username"
git config --global user.email "email-associated-with-github@address.tld"
To clone with https, you may need to add the git https helper. Run sudo apt install libcurl4-openssl-dev
in Ubuntu or dnf install curl-devel
in Fedora. I haven’t seen this problem on macOS or Windows.
Configure SSH and set up keys¶
Background
SSH keys provide asymmetric cryptography for securing your connections. In asymmetric cryptography, there are two keys: a public one and a private one. The public key encrypt messages, while the private one is needed to decrypt them. This means that you could send your public key out to everyone. But your private key must remain on your computer and be secure. For historical reasons, SSH, OpenSSL, and GPG provide independent mechanisms, but they’re similar.
These steps cover hardening SSH, generating keys, adding a key to GitHub.
(If needed) Fix SSH permissions¶
Permissions in ~/.ssh/
need to be set precisely. If they got messed up, use this to fix them:
chmod 600 "~/.ssh/*"
chmod 700 "~/.ssh/"
[[ -e "~/.ssh/config" ]] && chmod 700 "~/.ssh/config"
[[ -e "~/.ssh/known_hosts" ]] && chmod 700 "~/.ssh/known_hosts"
chmod 644 "~/.ssh/*.pub"
[[ -e "~/.ssh/authorized_keys" ]] && chmod 644 "~/.ssh/authorized_keys"
Configuring the SSH client¶
The following instructions will
- Disable SSH agent forwarding, which is very insecure (disabled by default on most systems).
- Disable X forwarding, which also has security concerns (disabled by default on most systems).
- Tell the SSH agent to automatically add keys found in
~/.ssh/
. - Tell macOS to use your keychain (ignored on other platforms). Note: This only applies to the OpenSSH variant that ships with macOS. I recommend replacing that software by running
brew install openssh
. - Tell the client to try to keep connections alive.
Important: How SSH reads .ssh/config
The ssh config docs neglect to state this explicitly: Options declared at the top of the file – specifically, before any Host
specification – are global and non-overridable. This is distinct from putting them under Host *
.
SSH merges config option–value pairs from all Host specifications that match. If two matching specifications set an option, the first takes precendent. So, follow this order:
ForwardAgent no
, etc. (noHost
)Host github.com
,Host server1.puppy-rescue.org
, etc.Host *.puppy-rescue.org
and other globsHost *
for defaults
Global, non-overridable options¶
First, create ~/.ssh/config
doesn’t exist. Add these lines at the top of the file:
ForwardAgent no # Disable SSH agent forwarding, which is insecure
ForwardX11 no # Disable X11 forwarding, which is insecure
ForwardX11Trusted no # Restrict X11 access (this line is probably redundant)
AddKeysToAgent yes # Automatically add discovered keys to the agent
IgnoreUnknown UseKeychain # Let Linux ignore this macOS/BSD-specific key
UseKeychain # Tell macOS SSH to use the system keychain
Defaults for connection timeouts¶
Next, you can set defaults to keep connections alive for longer, subject to server policy. You can instruct the client to send TCP KeepAlive
packets periodically by adding this section to the end of the file:
Host *
ServerAliveInterval 60 # If no data was received for 1 minute, send a KeepAlive.
ServerAliveCountMax 360 # If no KeepAlive response was received, retry up to 360 times.
Generate keys for GitHub¶
Using SSH to access a GitHub repository is preferable to using HTTPS where authenticating via the GitHub API or installing the GitHub CLI would be difficult. You’ll need to generate an SSH key pair and tell GitHub about it.
See also
For extended instructions with explanations, see GitHub’s SSH instructions.
- Generate a new SSH key pair, named
github
, by running this command. I recommend skipping the passphrase; instead, keep your private key safe, and revoke it if it is compromised.
- Add it to the SSH agent immediately. (This might not be necessary if
AddKeysToAgent
is enabled.)
- Add a section to your config file. If your name is Kerri Johnson and you use
kerri.johnson@gmail.com
on GitHub, add this to the middle of~/.ssh/config
:
Host github github.com
HostName github.com
User kerri.johnson@gmail.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/github
- Send the key to GitHub.
Using the GitHub CLI, run (choosing a better title
):
Alternatively, go to https://github.com/settings/ssh/new
(as of 2025-01) and paste the contents of ~/.ssh/github.pub
.
(If needed) Connect to another remote host¶
Bug: Servers lacking EdDSA support
Some servers might not support EdDSA yet. If this is the case, generate another pair of keys:
Replaceid_ed25519
with id_rsa
in these instructions. Follow these steps if you need to add a host other than GitHub.
When you first connect, you’ll see something like this:
The authenticity of host '122.152.98.56' can't be established.
ED25519 key fingerprint is SHA256:RiB+VjEoRmclYEhNfn0iZ3E4X1xUM2N0OSV6azdsTDw.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])?
Verify it by running this on the remote machine and comparing the strings:
Then, add a section to the middle of your ~/.ssh/config
:
Finally, use ssh-copy-id
to transfer your key to the server’s authorized_keys. Using the example above, run ssh-copy-id -i ~/.ssh/id_ed25519 lab
. (If you’re not a sysadmin, ask before doing this.)
(If needed) sshd server to allow remote access¶
You will need to install and configure the SSH server.
firewalld
should accept communications over port 22 without additional configuration. If not, look for firewalld guides (and shoot me a message).
Toggle Settings ➤ General ➤ Sharing ➤ Remote Login.
Navigate to Settings ➤ Optional Features ➤ OpenSSH server.
Enabling commit signatures¶
Sign with SSH – NOT recommended¶
Warning
Doing this has no significant advantages, is more limited, and may be less secure. Unless you’re sure, proceed to the GPG instructions below.
As of August 2022, GitHub supports signing with SSH keys. This is an alternative to signing with GPG keys.
If you really want to do this, run
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/github
git config --global commit.gpgsign true
Note: Although the config keys are gpg.format
and gpg.format
, it will actually use SSH.
Generate GPG keys¶
Also see GitHub’s guide to generating GPG keys. You may consider using an @users.noreply
email address per their suggestion.
-
Install GPG:
sudo apt install gnupg
sudo dnf install gnupg
brew install gnupg
choco install gnupg
(as an administrator) -
Launch gpg-agent by running
-
Then, generate a key pair by running
Use your full name and the email address you used on GitHub. As with SSH keys, you may choose to use a passphrase. Choose a reasonable expiration date.
Tell Git to use your GPG key¶
You can use the GitHub CLI for this. To see your generated key pair, run
sec ed25519 2023-11-04 [SC] [expires: 2025-11-03]
983C8320158FBB03818D3910C01A28311C1501SH
uid [ultimate] Kerri Johnson <kerri-johnson@hotmail.com>
ssb cv25519 2023-11-04 [E] [expires: 2025-08-03]
Check the type: pub
is public; sec
is your private key. Here, we want sec
. If you have multiple keys, make sure to select the one you want.
983C8320158FBB03818D3910C01A28311C1501SH
is your private key ID. (Note: There may be a prefix, using /
as a seperator. If so, ignore it.) Using it, run:
git config --global --unset gpg.format
git config --global commit.gpgsign true
git config --global user.signingkey 983C8320158FBB03818D3910C01A28311C1501SH
Send the GPG key to GitHub¶
Using your secret key ID, run this to write a temporary file called github.key.private.gpg
:
Then upload to GitHub by running the following (choosing a better title
):
Delete the github.key.private.gpg
file when done.
Optionally, publicize your public key¶
Important
This assumes that you used a real email address, not a @users.noreply.github.com
address.
You can put your public key on your website, include it in email signatures, etc.
First, list your public keys by running
You’ll see this:
pub ed25519 2023-11-04 [SC] [expires: 2025-11-03]
AC03281HD01A83C8DD50A9BEAA130FA03599207C
uid [ultimate] Kerri Johnson <kerri.johnson@hotmail.com>
sub cv25519 2023-11-04 [E] [expires: 2025-11-03]
Danger
Make sure you are using your public (pub
) key, not your private key (sec
).
Check the type: pub
is public; sec
is your private key. Here, we want pub
. Using your public key ID, run the following to get a key file called kerri-johnson.pub.asc
, which you can put wherever you want:
Credits: Cole Helsell drafted the original version of this guide with me.