Lock down SSH
SSH is your server's front door. In Linux Sysadmin, lesson 4 you saw what happens to any server on the internet: within minutes, bots start guessing passwords. You can't stop them knocking, but you can make sure a guessed password is useless. By the end of this lesson, only your key opens the door, and root can't log in at all.
You will learn
- Why keys beat passwords, and the three settings that matter most
- Protecting the key itself with a passphrase, and
ssh-addso you type it once - Where the SSH server's settings live, and the drop-in files that quietly override them on both families
- Checking what the server really uses with
sshd -tandsshd -T - The safe routine that makes sure you never lock yourself out
Why passwords are the weak spot
A password can be guessed, reused from another site that leaked, or typed into a fake login page. An SSH key can't be guessed: it's a pair of files, and the private half never leaves your computer (you made one in Linux Basics, lesson 3). So the plan is simple: make sure your key works, then tell the server to stop accepting passwords.
| Setting | Safe value | What it means |
|---|---|---|
PasswordAuthentication | no | Only keys can log in. Guessed or leaked passwords stop working over SSH. |
PermitRootLogin | no | Nobody logs in as root directly. You log in as yourself, then use sudo, so every admin action has a name on it. |
PubkeyAuthentication | yes | Keys are allowed. It's already the default; just don't turn it off! |
Protect the key itself: a passphrase
Once passwords are off, your private key is your login. So think about what happens if someone gets a copy of the file ~/.ssh/id_ed25519: a stolen or lost laptop, a backup that ends up somewhere public, or malware that grabs files. Without protection, the copy works just as well as the original.
A passphrase encrypts the key file. A stolen copy is then just scrambled bytes until someone knows the passphrase. It never leaves your computer and is never sent to the server: it only unlocks the key on your side.
ssh-keygen -t ed25519 # type a passphrase when it asks (twice) ssh-keygen -p -f ~/.ssh/id_ed25519 # add or change the passphrase of a key you already have ssh-add # unlock it once for this session ssh-add -l # which keys are unlocked right now?
Typing a passphrase for every login gets old fast. That's what ssh-add is for: it hands the unlocked key to the ssh-agent, a small helper that most desktops and Macs start for you. You type the passphrase once, and ssh stops asking until you log out. The file on disk stays encrypted the whole time.
A good passphrase is long rather than clever: four or five random words (quartz-otter-maple-river) are both easier to remember and harder to guess than P@ssw0rd!.
Where the settings live (and the trap)
The SSH server is a program called sshd (the d is for daemon). Its settings are in /etc/ssh/sshd_config. But look at the very first line that isn't a comment:
Include /etc/ssh/sshd_config.d/*.conf
Every .conf file in that folder is read first, in alphabetical order. And sshd has one golden rule: for each setting, the first value it reads wins. So a line in a drop-in file beats the same setting written further down in the main file. Both families ship a drop-in that catches people out:
ls /etc/ssh/sshd_config.d/ # 01-permitrootlogin.conf 50-redhat.conf sudo cat /etc/ssh/sshd_config.d/01-permitrootlogin.conf # PermitRootLogin yes
If the installer's "allow root SSH login with password" box was ticked, this file turns root logins on, whatever the main file says.
ls /etc/ssh/sshd_config.d/ # 50-cloud-init.conf cat /etc/ssh/sshd_config.d/50-cloud-init.conf # PasswordAuthentication yes
Cloud and VPS images of Ubuntu add this file, so writing PasswordAuthentication no in the main file does nothing.
The fix is the same on both: put your settings in your own drop-in whose name sorts first, like 00-hardening.conf. Then your values are the first ones sshd reads.
Ask sshd what it really thinks
Never trust your reading of the files. Ask sshd itself:
sudo sshd -t # test the config: silence means OK sudo sshd -T | grep -iE 'passwordauth|permitroot' # the settings it would really use
-t (small t) finds typos before they cause damage. -T (capital T) prints the final result of all the files, after the first-value-wins rule. Both need sudo, because sshd has to read its private host keys.
The safe routine: never lock yourself out
Changing SSH over SSH is sawing off the branch you're sitting on. Professionals always follow the same steps:
- Make sure your key works first. Log in with it and check there was no password prompt.
- Write your settings in
/etc/ssh/sshd_config.d/00-hardening.conf. - Test the config:
sudo sshd -t. A typo here would stop sshd from starting at all. - Apply it: reload the service. sshd only reads its files when it starts or reloads, so editing alone changes nothing.
- Test from a second window, while the first one stays logged in. If something is wrong, you still have a way in to fix it.
printf 'PasswordAuthentication no\nPermitRootLogin no\n' | sudo tee /etc/ssh/sshd_config.d/00-hardening.conf sudo sshd -t sudo systemctl reload sshd
printf 'PasswordAuthentication no\nPermitRootLogin no\n' | sudo tee /etc/ssh/sshd_config.d/00-hardening.conf sudo sshd -t sudo systemctl reload ssh
Then, from your laptop, prove both halves:
ssh -o PubkeyAuthentication=no student@192.168.1.50 # must be REFUSED: passwords are off ssh student@192.168.1.50 # must still work: your key
Turn passwords off before your key is installed, and the next login says Permission denied (publickey). On a real server you'd need the provider's web console or a trip to the machine. In the practice terminal you can try it on purpose and press Reset afterwards.
A few more good habits
- Only let the right people in:
AllowUsers student mariain your drop-in means nobody else can log in over SSH, even with a valid password or key. - Read the evidence: after the change, the log shows
Accepted publickeyfor you, and bots now getConnection closed … [preauth]instead ofFailed password. Look withjournalctl -u sshd(Rocky) orjournalctl -u ssh(Ubuntu).
A popular tip is to move SSH from port 22 to something like 2222. It does make the log quieter, because the laziest bots only try port 22. But it doesn't protect anything: a scanner finds the new port in seconds, and a real attacker checks every port anyway. Hiding the door is not the same as locking it. Keys, a passphrase and no root login are what actually keep people out. If you do move the port for a quieter log, treat it as a nice extra, never as the defence. (On Rocky, a new port also needs semanage port for SELinux; on Ubuntu, systemctl daemon-reload and a restart of ssh.socket.)
Try it: lock the front door 🔐
This terminal starts on your laptop. The server is at 192.168.1.50 (user student, password linux). Follow the safe routine, and prove it worked.
Quick check
1. You added PasswordAuthentication no to the end of /etc/ssh/sshd_config on an Ubuntu cloud server and reloaded, but passwords still work. Why?
✓ 50-cloud-init.conf sets it first. Put your settings in 00-hardening.conf, and check with sudo sshd -T.
2. What's the safest order?
✓ Key first, test the config, keep one session open while you test with another.
3. Someone copies your private key file ~/.ssh/id_ed25519. When is that copy useless to them?
✓ The passphrase encrypts the file. (And if a key ever does leak, remove its line from ~/.ssh/authorized_keys on every server.)
4. Why is PermitRootLogin no a good idea even with keys?
✓ Bots always try "root". With direct root login off, that guess is worthless, and sudo leaves a record of who did what.