Security basics · Lesson 2 · 30 min

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-add so 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 -t and sshd -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.

SettingSafe valueWhat it means
PasswordAuthenticationnoOnly keys can log in. Guessed or leaked passwords stop working over SSH.
PermitRootLoginnoNobody logs in as root directly. You log in as yourself, then use sudo, so every admin action has a name on it.
PubkeyAuthenticationyesKeys 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.

Same on both (on your laptop)
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:

Rocky / RHEL
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.

Ubuntu / Debian
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:

Same on both
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:

  1. Make sure your key works first. Log in with it and check there was no password prompt.
  2. Write your settings in /etc/ssh/sshd_config.d/00-hardening.conf.
  3. Test the config: sudo sshd -t. A typo here would stop sshd from starting at all.
  4. Apply it: reload the service. sshd only reads its files when it starts or reloads, so editing alone changes nothing.
  5. 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.
Rocky / RHEL
printf 'PasswordAuthentication no\nPermitRootLogin no\n' | sudo tee /etc/ssh/sshd_config.d/00-hardening.conf
sudo sshd -t
sudo systemctl reload sshd
Ubuntu / Debian
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:

Same on both (from the laptop)
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
What a lockout looks like

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

Security through obscurity isn't security

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?

2. What's the safest order?

3. Someone copies your private key file ~/.ssh/id_ed25519. When is that copy useless to them?

4. Why is PermitRootLogin no a good idea even with keys?

Finished the missions and the quiz? Mark it done to track your progress.