I find myself needing to set up SSH and GPG keys for use with GitHub, Bitbucket, GitLab and other similar services rather frequently. Here are the steps I use to set this up.
Use the below command to create SSH keys. It might be wise to "silo" your keys such that you dedicate a separate key for each computer you use and per repository, service or some other logical way. For instance, have one key for GitHub and another for Bitbucket.
$ ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_$(whoami)_$(date -f %Y-%m-%d) -C "Macbook Pro SSH Key for GitHub"
Make sure to set a passphrase! If you don't, and your key is compromised, it's a free pass for the attacker.
Copy the public key from the .pub
file created in the last command to your clipboard. From our previous example, it would be something like this:
$ clip < ~/.ssh/id_ed25519_jdoe_2020-12-29.pub
You can also open the file in your favorite editor (*cough vim) and simply copy it that way (assuming you can quit out of vim :p ).
In GitHub, or whichever service you happen to be using, go to your settings and then to SSH Keys. Many services combine SSH key and GPG key management into the same page, so don't leave the page once you find it.
Select "Add new key", and paste the key in. If you copied the whole key, it should automagically populate the key name. I personally only copy the type and the base64 encoded key leaving out the username, hostname and comment, if any, e.g. ssh-ed25519 aAbBcCdD...
(see https://coolaj86.com/articles/the-ssh-public-key-format/ for a breakdown of the key format).
You will receive an email stating that a new key has been added. Likewise, if you delete a key you will also receive an email alerting you to the activity.
This step isn't entirely necessary, however, it does help if you plan to use multiple keys.
Open ~/.ssh/config
in your favorite vim, I mean editor. Add the following, making changes where you see text surrounded by '<>'.
Host <slug>
Hostname <github.com or your services FQDN>
Username git
IdentityFile <path to private key>
IdentitiesOnly yes
Here's a breakdown:
github.com
, but if you are going to silo, you might choose something more descriptive, like mycoolwidget. Then when you set up your git remote in your local repository, you should use that slug instead of github.com.
This configuration will essentially alias the FQDN for the slug. The main benefit here is that you can use multiple keys with the same service. Just make different slugs that point to each key, add the keys to your service and then make sure to use the slug when you set up the git remote locally. See the example below for context.git@github.com:jdoe/mycoolwidget.git
you would simply use github.com
here.ssh-keygen
in step 1 above that has no extension. Keep it secret, keep it safe. But refer to it here. In our above example, it would be ~/.ssh/id_ed25519_jdoe_2020-12-29
. You can use the ~
here, thats fine.You need to make sure that the config file has chmod 600, meaning that the owner of the file has read and write permissions (6), and then group and everyone have no permissions (0). You can always hit it with a quick chmod 600 ~/.ssh/config
to make sure.
As an example of "siloing" your keys, assuming your project mycoolwidget is hosted on github:
# ~/.ssh/config
Host mycoolwidget
Hostname github.com
Username git
IdentityFile ~/.ssh/id_ed25519_jdoe_2020-12-29_mycoolwidget
IdentitiesOnly yes
Host mycoolapp
Hostname github.com
Username git
IdentityFile ~/.ssh/id_ed25519_jdoe_2020-12-29_mycoolapp
IdentitiesOnly yes
# set up local git repositories
# the alias would be the equivalent to 'git@github.com:jdoe/mycoolwidget.git',
# but since we are using the slug we defined in the SSH config,
# our identity file will automatically be used
$ git remote add origin mycoolwidget:jdoe/mycoolwidget.git
$ cd ../mycoolapp
$ git remote add origin mycoolapp:jdoe/mycoolapp.git
Lastly, verify that your config works.
ssh -T <slug>
You should get a message back saying something along the lines of you've connected successfully, but shells aren't allowed.
Thats it for the SSH key peice. Now for the hard part…GPG keys.
You will need the GPG command line tool for this. Make sure you install the correct version for your OS. Most linux and Mac (including Windows Subsystem for Linux) will already have gpg ready for you.
If you don't already have keys set up for your e-mail, or if like me, you've failed to store your passphrase in your password vault and have now forgotten it, then you need to generate a new key.
gpg --full-generate-key
You will be prompted for several things:
y
, else bail out and start over.12345678+jdoe@users.no-reply.github.com
which can be found in your email settings, but just make sure that it matches your local git config as well.Congratulations, you have a gpg key. Now we need to get the keyid and the ASCII armored key so we can tell our provider du jour about it.
You need to copy the key ID from the output of the following, which in this example would be 3XE290DWFIXQ8L1J
.
$ gpg --list-secret-keys --keyid-format LONG
/Users/jdoe/.gnupg/secring.gpg
----------------------------------------------
sec 4096R/3XE290DWFIXQ8L1J 2020-12-29 [expires: 2021-12-29]
uid jdoe
ssb 4096R/CTRNZTHH95IG5CSB 2020-12-29
Using the key ID that we just got, we need to export the key in ASCII armor format:
$ gpg --armor --export 3XE290DWFIXQ8L1J
-----BEGIN PGP PUBLIC KEY BLOCK-----
gibberish
-----END PGP PUBLIC KEY BLOCK-----
Copy the key output, including the -----BEGIN PGP PUBLIC KEY BLOCK-----
and -----END PGP PUBLIC KEY BLOCK-----
Add GPG Key
interfaceHold your horses, we aren't done yet. Now, let's tell our local git repository to use the key
You can do this globally for all repositories if you will use only one GPG key (i.e. only one email/git account/persona), or by repository. If you are doing this globally, you can skip step 1.
Get your Key ID again, just like before. Again the Key ID in the example below would be 3XE290DWFIXQ8L1J
$ gpg --list-secret-keys --keyid-format LONG
/Users/jdoe/.gnupg/secring.gpg
----------------------------------------------
sec 4096R/3XE290DWFIXQ8L1J 2020-12-29 [expires: 2021-12-29]
uid jdoe
ssb 4096R/CTRNZTHH95IG5CSB 2020-12-29
Set your GPG signing key.
# For only the repository in the current directory
$ git config user.signingkey 3XE290DWFIXQ8L1J
# OR globally for all repositories. Can be overriden by repository specific config
$ git config --global user.signingkey 3XE290DWFIXQ8L1J
(OPTIONAL) If you want to sign all commits by default, you can configure it by repository or globally as well:
# Repository specific
$ git config commit.gpgsign true
# Global
$ git config --global commit.gpgsign true
Sometimes on windows, you may get a "gpg failed to sign data" message. Add the following to the end of your ~/.bashrc
file:
$ export GPG_TTY=$(tty)
Now run your commit again, and it should prompt you for your GPG passphrase.
This should be it. Your workflow should look something like this:
git add
git commit -m 'message'
git push origin <branch>
Once pushed, you should see that your commit is now reflected in the remote via the git web interface. You should also note that your commit features a verified committer a la pretty green checkmark or similar icon.
Hope you found this useful. Please let me know in the comments if you have any questions, or if this doesn't yield promised results. I wrote it from memory, not doing an actual walkthrough so cut me a bit of slack.
0 comments