How to Secure SSH on a Linux Server: The Settings That Matter
SSH is the front door to your server and a constant target for bots. These sshd settings, tested safely, cut the risk without locking you out.
Within minutes of going online, a public server starts receiving SSH login attempts from automated scanners. Most of them guess common usernames and passwords. You cannot stop the attempts, but you can make sure none of them succeed. This guide covers the settings that provide real protection and the testing routine that stops you locking yourself out.
Before you change anything
Always keep one working SSH session open while you edit the configuration. Test every change from a second terminal. If you break the configuration, the first session is your way back in. Also make sure key-based login already works for your user; the knowledge base and our other server guides explain how to set that up.
The server configuration lives in /etc/ssh/sshd_config. On modern Debian and Ubuntu you can also put overrides in a separate file such as /etc/ssh/sshd_config.d/10-hardening.conf, which survives package upgrades more cleanly. Note that for most directives the first value SSH reads wins, so check for conflicting lines in other included files.
The settings that matter most
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
KbdInteractiveAuthentication no
MaxAuthTries 3
LoginGraceTime 30
AllowUsers deploy
X11Forwarding no
ClientAliveInterval 300
ClientAliveCountMax 2
What each one does:
- PermitRootLogin no stops anyone logging in directly as root. Attackers always try the root account first, so this removes the most obvious target. Use a normal user and
sudo. - PasswordAuthentication no disables password logins entirely, so guessing is pointless. This is the single most effective change, but only apply it after keys work.
- KbdInteractiveAuthentication no closes a related route that can still allow password-style prompts on some setups. On older OpenSSH versions this option is called
ChallengeResponseAuthentication. - MaxAuthTries and LoginGraceTime limit how many attempts and how much time a connection gets.
- X11Forwarding no turns off graphical forwarding, which a typical server never needs.
- ClientAliveInterval and ClientAliveCountMax make the server drop sessions whose client has disappeared, after roughly ten minutes with these values.
- AllowUsers is an allow-list. Only the named accounts may log in over SSH, which is useful on servers with many system accounts.
Test, then reload
Check the syntax before applying:
sudo sshd -t
No output means no errors. Then reload the service. On Debian and Ubuntu the unit is named ssh, on Red Hat style systems sshd:
sudo systemctl reload ssh
Open a new terminal and log in. Only when that works should you close the old session. You can also confirm the effective values with sudo sshd -T | grep -i passwordauth.
Should you change the port?
Moving SSH from port 22 to another number reduces noise in your logs because simple bots only probe the default port. It is not real security: a determined attacker can scan all ports. If you do it, open the new port in your firewall before restarting SSH, and keep the old session open. Treat it as a tidy-up, not a defence, and never rely on it instead of key-only login.
Add layers around SSH
- Firewall: allow SSH only from addresses you use if you have a fixed IP. Otherwise keep it open but rate-limited. With ufw,
sudo ufw limit OpenSSHthrottles repeated connection attempts. - fail2ban: bans addresses that repeatedly fail to authenticate. With password logins disabled it mostly reduces log clutter and load, but it remains a useful extra layer.
- Two-factor authentication: it is possible to require a second factor on top of the key. It adds complexity, so decide whether the extra protection is worth it for your situation.
- Keep OpenSSH updated: security fixes arrive through normal package updates, so enable automatic security upgrades.
Read your logs
Authentication events are recorded in /var/log/auth.log on Debian and Ubuntu, and in /var/log/secure on Red Hat style systems. On systems that use journald you can also run sudo journalctl -u ssh. Look for repeated failures from the same address and for successful logins you do not recognise. The command last lists recent logins.
Make this review a habit rather than a one-off. Once in a while, open ~/.ssh/authorized_keys for each account and confirm that every key still belongs to someone who should have access. Remove accounts that are no longer needed with sudo deluser, and check that no user has a password set that you did not expect. Small checks like these catch the quiet problems that no setting can prevent.
Recovering from a mistake
If you do lock yourself out, you are not stuck forever. Most providers offer some kind of emergency console or rescue mode that does not depend on SSH. Find out how yours works before you need it, not afterwards. On a Zebra Hosting server you can also ask the support team for help.
A quick audit you can run today
Run sudo sshd -T and read the effective values for permitrootlogin, passwordauthentication and allowusers. Then check sudo grep -c "Failed password" /var/log/auth.log on Debian and Ubuntu: a large number is normal on an exposed server and is not a sign of compromise by itself. What matters is the lack of successful logins from addresses you do not recognise. For wider protection beyond SSH, see our security page.
Security help at Zebra Hosting
Hardening SSH is one step in running a safe server. If you want full control over those settings, start from a Zebra Hosting VPS and apply them on day one.