GitHub finally introduced granular access tokens that let you limit access to select repositories. Personal access tokens can authorize Git with HTTPS.
Like many, I use Git with SSH on my desktop. SSH keys grant access to all repositories, whereas access tokens can be much more limited. This is great for servers and automation use-cases, but should you also prefer access tokens, and therefore HTTPS for your personal machines?
Connecting to a Git server over SSH for the first time presents you with this message:
$ git clone firstname.lastname@example.org:example/example The authenticity of host 'github.com (IP ADDRESS)' can't be established. RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8. Are you sure you want to continue connecting (yes/no)?
When you see this, do you:
If your answer is 2, you are vulnerable to a man-in-the-middle attack. This is not a problem with HTTPS because certificate authorities like Let's Encrypt verify the ownership of a domain.
You authenticate with HTTPS by sending a plain-text to the server, whereas SSH uses public-key crypto. Sending a token to a trusted server over a encrypted connection is fine, but the best way to never expose a secret is to never send it over the wire. You can also embed SSH tokens in a hardware device like the YubiKey for extra-secure storage.
If used right, SSH is more secure. But for the 99% (?) of us who don't verify fingerprints, HTTPS wins. HTTPS also enables the use of granular tokens.
Your SSH keys are stored in the
~/.ssh directory and automatically used by Git to authenticate. Git provides
credential helpers for use with HTTPS. The
cache helper stores credentials
in memory temporarily. The
store helper stores them in plain text on disk, which you may not want to do. You could use
.netrc file in your home directory:
machine github.com login example password github_token
This will work out of the box, and with git-credential-netrc you could encrypt this file using gpg.
Alternatively, you could use the credential store built into your operating system, which will typically encrypt your secrets using your login password.
# On Fedora, for others see below sudo dnf install git-credential-libsecret git config --global credential.helper libsecret
git config --global credential.helper osxkeychain
git config --global credential.helper wincred
Once configured, Git will automatically store your credentials in the OS secret store.
See this StackOverflow question for more information.
This approach does have one problem: Containerized environments will not be able to access your local secret store unless they specifically support it. As a heavy user of VSCode Remote Containers, it's not for me.
SSH authentication just works, whereas HTTPS requires some time to set up if you want to store your credentials in encrypted form. I'd say SSH has the edge in terms of convenience.
SSH is a protocol for remotely controlling machines. It is installed on nearly every Linux server on the internet. When
you set up a Git server with SSH, you need to either rebind the default port 22 to our Git server, or you need to move
the Git server to another port. It's harder to remember an address like
example.com:7392/user/repo, but there is only
one port 22.
When hosting multiple Git servers, you have two choices: Use alternative ports or use dedicated IP addresses for each. IPv4 addresses are in short supply, so neither are great options.
HTTPS uses Server Name Indication to tell which server a client is connecting to. You almost never need to use non-default ports when accessing websites. At Cloudplane, we provide managed Gitea instances, and we've chosen to ship with HTTPS support only. Providing SSH ports would be challenging for us.
SSH remains the most convenient solution for users, but it is vulnerable to attacks unless used correctly. HTTPS is secure and easy to host, but setting up credentials is a little more involved.
Should you switch from SSH to HTTPS? I think SSH is perfectly fine and there is no immediate need to switch. But there are good reasons to prefer HTTPS in some situations, especially now that GitHub supports granular access tokens.