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!
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.
So make sure your GitHub account has a strong password, preferably set with a password manager, and make absolutely sure to enable 2FA.
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.
Remote into the target server, and start!
Make a script,
update-ssh.sh, wherever you like in your home directory. Paste in the following:
#!/bin/bash echo -e "Script started at $(date)" curl "https://github.com/your-username-here.keys" > ~/.ssh/authorized_keys echo "The following keys were added:" cat ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys
Make sure you replace “your-username-here” with your GitHub username. For example, my public keys can be found at https://github.com/ericswpark.keys.
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.
To make this script run periodically, we’ll use
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.
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
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.
crontab entry means that your SSH keys will be updated each hour at the random minute you specified.
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.