Check a site
Check a website Service status Outages Blog
All tools
Check a websiteBrowse all tools
An sshd configuration file with hardening settings, each line marked with a green check

Guides

How to harden SSH on a Linux server: a 15-minute checklist

Posted Jimel S.4 min read

Switch to keys, turn off passwords and root logins, limit who and where people can connect from, and test every change without locking yourself out. A practical SSH hardening checklist for Debian, Ubuntu, RHEL and Alpine.

Illustration: UtiBox

Every server with SSH open to the internet is being tried, constantly, by bots guessing usernames and passwords. Bugs like the recent “sshole” password bypass show why password logins are worth switching off even when your passwords are strong.

This checklist takes about 15 minutes. It works on Debian, Ubuntu, Red Hat-family distributions and Alpine; where commands differ, both are shown.

1. Log in with a key instead of a password

On your own computer, create an Ed25519 key pair if you don’t already have one. Protect it with a passphrase; our Password Generator can make a long random one, and your password manager can remember it.

ssh-keygen -t ed25519 -C "you@laptop"

Copy the public key to the server, then check that you can log in with it:

ssh-copy-id -i ~/.ssh/id_ed25519.pub deploy@your-server
ssh deploy@your-server

If you have a hardware security key (YubiKey, SoloKey and similar), use -t ed25519-sk instead. The private key then can’t be copied off the device, and every login needs a physical touch.

2. Put your settings in a drop-in file

Most current distributions (Debian, Ubuntu, Fedora, RHEL 9 and later, Alpine) load extra files from /etc/ssh/sshd_config.d/. Using one keeps your changes separate from the distribution’s defaults and safe from package upgrades. Check that your main config includes the folder (if this prints nothing, put the settings at the top of /etc/ssh/sshd_config instead):

grep -i '^Include' /etc/ssh/sshd_config
# /etc/ssh/sshd_config.d/10-hardening.conf
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin no
AllowUsers deploy
MaxAuthTries 3
LoginGraceTime 30
X11Forwarding no

What each line does:

  • PasswordAuthentication no / KbdInteractiveAuthentication no: keys only. This alone stops almost all brute-force attempts.
  • PermitRootLogin no: log in as a normal user and use sudo. Use prohibit-password instead if automation genuinely needs root with a key.
  • AllowUsers deploy: only the listed accounts may log in over SSH at all. You can also use AllowGroups.
  • MaxAuthTries 3 / LoginGraceTime 30: fewer guesses per connection, and less time to make them.
  • X11Forwarding no: turn off what you don’t use.

3. Test the configuration before restarting

Check for typos, then confirm the settings sshd will actually use:

sudo sshd -t
sudo sshd -T | grep -Ei 'passwordauth|kbdinteractive|permitrootlogin|allowusers|maxauthtries'

If sshd -t prints nothing, the syntax is fine. Then restart the service:

sudo systemctl restart ssh      # Debian / Ubuntu
sudo systemctl restart sshd     # RHEL, Fedora, Rocky, Alma
sudo rc-service sshd restart    # Alpine

Now open a new terminal and log in again. Also try a password login, which should be refused:

ssh -o PubkeyAuthentication=no deploy@your-server

4. Limit where people can connect from

If you always connect from a fixed address, such as an office, a VPN or a jump host, only allow SSH from there. Find your public address with What Is My IP, then on Ubuntu or Debian with UFW:

sudo ufw allow from 203.0.113.10 to any port 22 proto tcp
sudo ufw enable
sudo ufw status numbered

Add the allow rule before enabling the firewall. If your address changes often, a VPN such as WireGuard or Tailscale, or your cloud provider’s security groups, does the same job without hard-coding your home IP.

5. Slow down the bots with fail2ban

fail2ban watches your logs and temporarily blocks addresses that keep failing to log in. On Debian and Ubuntu the SSH jail is enabled by default once it’s installed:

sudo apt install fail2ban
sudo fail2ban-client status sshd

If the status command reports an error on a system that logs only to the systemd journal (no /var/log/auth.log, as on a minimal Debian 12), add backend = systemd under [sshd] in /etc/fail2ban/jail.local and restart fail2ban.

With password logins off, fail2ban mostly keeps your logs quiet, but quiet logs make the real problems easier to spot.

6. Keep OpenSSH updated, and restart it

Most SSH compromises don’t come from clever settings being missing. They come from old software. Turn on automatic security updates (unattended-upgrades on Debian and Ubuntu, dnf-automatic on RHEL-family systems) and remember that a running sshd keeps the old code until it’s restarted. Check your version with ssh -V.

7. Check who is getting in

Get used to reading your SSH logs, so unusual entries stand out:

sudo journalctl -u ssh --since "24 hours ago" | grep -E "Accepted|Failed"   # Debian / Ubuntu
sudo journalctl -u sshd --since "24 hours ago" | grep -E "Accepted|Failed"  # RHEL family
grep -E "Accepted|Failed" /var/log/messages                                 # Alpine

Look at ~/.ssh/authorized_keys for every user from time to time, too. A key you don’t recognise is a key someone else added.

What about changing the port?

Moving SSH from port 22 to something else cuts down log noise from the laziest bots, but it isn’t real security: scanners find other ports quickly. It’s fine to do, but it doesn’t replace any of the steps above. On Ubuntu, which starts SSH through systemd socket activation, follow Ubuntu’s documentation if you change the port.

The checklist

  • Ed25519 (or hardware-backed) key with a passphrase
  • PasswordAuthentication no and KbdInteractiveAuthentication no
  • PermitRootLogin no
  • AllowUsers or AllowGroups set
  • sshd -t passes and sshd -T shows the values you expect
  • Firewall limits port 22 to known addresses, or a VPN
  • fail2ban (or similar) installed
  • Automatic security updates on, and sshd restarted after updates
  • Logs and authorized_keys reviewed regularly

Related

More from Guides

Most read

Latest

Most read

  1. 01November Patch Tuesday lands on the 10th: what October’s record release tells us19
  2. 02Introducing UtiBox: the Web’s Utility Box2
  3. 03Ivanti Connect Secure zero-days gave attackers root on VPN gateways1
  4. 04“Black October”: attackers raid secrets at cloud and AI developer platforms1

Embed this post

Paste this code into your page. It shows the post as a card that links back here. In WordPress you can also paste the post’s address on a line of its own.

Cookies on UtiBox

UtiBox is free because of ads. Google and its partners use cookies to show, limit and measure ads, Google Analytics, Ahrefs Web Analytics and Microsoft Clarity show us how the site is used, and we use a few essential cookies to run the site.