Nick James

Eliminate the need for passwords with SSH Keys and ssh-agent

A bit of background

Assuming you are unfamiliar, SSH keys provide an alternative method to identify yourself when requesting access to an SSH server. It uses public-key cryptography and challenge-response authentication to do this. So that means keys are generated as a pair. One private, and the second public. Always, always, always be sure to keep your private key private. If someone were to get a hold of it, THEY BECOME YOU, Highlander style!! Well, not really, but they can impersonate you, and you wouldn't want that!

Now that I have totally freaked you out, you might be wondering why you would even want to use SSH keys. One benefit is added security, assuming you listened to my warning above, and have kept your private key secure. Secondly, they can offer a more convenient way authenticate when using ssh. For example, pushing code to a remote repository or access a VPS.

Install SSH and generate your very first key

On a Linux based machine, you will want to install the openssh package. This should be pretty easy to do using the package manager for your distro. On Arch, it's as easy as running the following command in a terminal

sudo pacman -S openssh

Next, you will want to create your SSH key.

ssh-keygen -t rsa -b 4096  -C "$(whoami)@$(hostname)-$(date -I)"

It is OK to save the file in the default location of /home/your_user_name/.ssh/id_rsa. Just hit enter to accept.

From here, enter a passphrase you will remember to secure the SSH key if you like. Personally, I would advise it. You have now generated you first SSH key!

Access a remote server

OK, now that you have an SSH key, lets put it to good use. Lets assume you have a VPS you ssh into every now and then. In order to stop providing your username and password, you will need to copy the public key you just created onto the remote server. Copying the key is as easy as running the command below, but be sure to replace user and host with your own information.

ssh-copy-id -i ~/.ssh/ user@host

After you enter the password of the specified user, the key should now exist in the `/hom/user/.ssh/authorized_keys` file on the remote machine. Now, lets ssh into the server to confirm it worked.

ssh -i ~/.ssh/ user@host

Enter the passphrase you supplied when you created the SSH key and just like that, you should now be free to move about the remote machine!

Use SSH key with GitHub

Another great use case for using an SSH key is securely pushing and pulling code from a remote git repository. Here I will describe how to do it with Github.

Just in case Github decides to change their process for adding a key, I will link to their guide instead of writing my own instructions. I found it to be easy to follow.

Cool, now that you have added your key to Github, you can test it out by cloning one of your repos using the ssh option. Click on the clone or download button and then select the Use SSH option.

Copy the provided URL and run git clone as usual. Now you will be prompted for your SSH key passphrase instead of your username and password.

Should you want to the SSH key with a repo that has already been cloned, you will need to update the remote url value. Again, Github provides an easy to follow guide.

ssh-agent to the rescue

So far we have eliminated the need to supply a username and password when we want to ssh into a remote machine or pull/push code to Github. However, in terms of typing, all we have really eliminated is the need to supply a username. The passphrase for the SSH key still needs to be typed every time we want to perform an action that needs interact with a remote machine. I don't know about you, but for me, the less typing the better. Luckily, openssh ships with a handy dandy tool called ssh-agent that can save us from unnecessary typing, and maybe even carpal tunnel!

Starting ssh-agent can be done with the command below.

eval $(ssh-agent)

Now that the agent is running, you will want to add your private key to the ssh-agent cache.

ssh-add ~/.ssh/id_rsa

If you try to ssh to a remote machine, or do a git push or pull once more, you should no longer be asked to provide a passphrase!

Automate all the things with a systemd unit file

So far, so good. We have eliminated the need to type a username and password, as well as cached the passphrase for the SSH key. However, there still exist one little issue. If you open a new terminal, and try cloning a repo using SSH, you will have to type your passphrase again. The reason for this is ssh-agent is not running in this new terminal. It was only active in the terminal you started it from. We can fix this by creating a service that systemd will start automatically.

Instead of creating a system level service, I created on for only my user. But first, you will need to know where to save such a file. That can be done like so

systemd-analyze --user unit-paths

Example output from my machine

>>systemd-analyze --user unit-paths

I used the first directory printed, and you can probably do the same. If it does not already exist, you will need to create it. Now, inside of ~/.config/systemd/user.control/, create a file named ssh-agent.service and paste the content below

Description=SSH key agent

ExecStart=/usr/bin/ssh-agent -D -a $SSH_AUTH_SOCK


Save this file and then run the next command

echo 'SSH_AUTH_SOCK DEFAULT="${XDG_RUNTIME_DIR}/ssh-agent.socket"' >> .pam_environment

In order to make all ssh clients, including git store keys in the agent on first use, run

echo 'AddKeysToAgent yes' >> ~/.ssh/config

Lastly, start new service file

systemctl --user start ssh-agent.service

and enable it so it starts on system boot

systemctl --user enable ssh-agent.service

Go ahead and try cloning that repo again or sshing into that remote server. You will be asked for the passphrase the first time, but from that point on, it should be cached! Hurray for no more typing!

Further reading

Author image
About Nick James