Persistent access with SSH keys
Picture this: you got your new machine set up with your development tools. You fire up a Terminal, SSH into your work’s server, and… it asks for your password. Panic sets in as you realize that you decommissioned away the old machine, along with the old SSH keys. You must now remember that password to that server - a password you seldom typed in thanks to your SSH keys - or if the SSH daemon installed on that particular server disallows password-based authentication, be forced to do the call-of-shame to your colleague or the administrator of the server to let you back in.
Humiliating! Embarrassing. And most importantly, annoying.
So what if there was a way to enable persistent access to a given server or machine? What if you didn’t have to go around updating every single machine with your new SSH key?
In this blog post we’ll go over how we can do just that!
1. GitHub
The first thing you have to do is make sure that your GitHub security is top-notch. Because anybody who gets access to your GitHub account will have access to all of your servers.
Once you’ve done that, go over to Settings > SSH and GPG keys, and add your SSH keys here. This is where you will add all of your SSH keys and the new SSH keys you generate whenever you get a new machine or environment to work in. You only need to update GitHub, and the other machines will follow.
Done? Now let’s move over to the server or machine you want persistent access to.
2. Script
Remote into the target server, and start!
Make a script, update-ssh.sh
, wherever you like in your home directory. Paste in the following:
Make sure you replace “ericswpark” with your GitHub username.
So what does this script do? Well, it fetches your public keys from your GitHub profile, and saves them to the authorized_keys
file in your .ssh
directory. Then it sets the relevant permissions to make sure that the SSH daemon will not reject the file, since the daemon will ignore authorized_keys
files that have too open permissions.
Set the script as executable and try running the script. Afterwards, you will be able to log into the server without actually manually adding your new SSH key.
But we want to automate this, so that whenever you add a new key on GitHub, it syncs to all of your servers.
3. Automate
To make this script run periodically, we’ll use crontab
.
Don’t know how to use crontab
? Me too! Let’s just go over the basics.
The basic syntax of crontab
is as follows:
20 * * * * ls
The first column is minutes, which has a range of 0 to 59, and the second column is hours, which has a range from 0 to 23. The third column is the day of month (1 - 31), the fourth column is the month (1 - 12), and the final column is the day of week (Sunday 0 to Saturday 6). A wildcard value matches to all possible values in that range.
Therefore, the crontab
entry above will run every hour at 20 minutes (so, 2:20 PM, 3:20 PM, and so on).
There’s also patterns to make crontab
entries repeat (/2 means every 2 units, and so on), but it’s not supported by all Linux distros, so be careful when using them!
Some enthusiasts will preach about systemd
tasks, but I think cron
is more prevalent (not so sure, don’t quote me). I haven’t seen a system yet that doesn’t have cron
. But of course this is an option if you prefer systemd
.
So still in that same target server, run crontab -e
. A editor should pop up. In the last line, create the following entry:
42 * * * * ~/update-ssh.sh >> ~/update-ssh.sh.log
Change 42 to a random number between 0 and 59, to help lessen load on the server.
Wait, why don’t we just refresh every minute?
The reason I set the crontab
here to refresh every hour is because I don’t want to put unnecessary strain on the server or GitHub’s servers. We don’t usually update SSH keys all that often, but we want to strike a balance, because if the interval is too long then we might as well just remote in with our password and change the keys ourselves. An hour is a reasonable interval that won’t put too much strain on the servers involved. You can set it to a shorter interval, say 5 minutes, if you change SSH keys frequently, but do keep in mind that you may be rate-limited.
The log pipe is not strictly necessary, but it’s good to have in case things go wrong.
The crontab
entry means that your SSH keys will be updated each hour at the random minute you specified.
Conclusion
The next time you update your SSH keys, update them on GitHub, wait until an hour has elapsed, then remote in to your usual server!
Thanks for reading! I hope this blog post helped you out.