SSH Hardening: Lock Down SSH on Your Server
A practical SSH hardening checklist: key-only authentication, no root login, AllowUsers, modern key types, sshd_config drop-ins, testing safely without locking yourself out, fail2ban, firewall rules or a private network like Tailscale, 2FA, and auditing who has access.
SSH is the front door to your server. It's also the most attacked service on the internet — automated bots try passwords on port 22 constantly. These steps make those attempts pointless. (How to SSH into a server)
Before you change anything: don't lock yourself out
- Keep your current session open while you make changes.
- Test from a second terminal before closing the first.
- Know where your provider's web console is — it works even if SSH doesn't.
1. Use SSH keys
On your own computer:
ssh-keygen -t ed25519 -C "you@laptop"
ssh-copy-id deploy@your-server
Confirm you can log in without a password. (SSH keys explained)
2. Create a normal user with sudo
adduser deploy
usermod -aG sudo deploy
Copy your key to that user and log in as them. Do day-to-day work as deploy, not root.
3. Edit the SSH server config
Modern Ubuntu and Debian read drop-in files, which survive package upgrades. Create /etc/ssh/sshd_config.d/99-hardening.conf:
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin no
PubkeyAuthentication yes
AuthenticationMethods publickey
AllowUsers deploy
MaxAuthTries 3
LoginGraceTime 30
X11Forwarding no
AllowAgentForwarding no
ClientAliveInterval 300
ClientAliveCountMax 2
What matters most:
PasswordAuthentication no— the single biggest improvement. Brute-forcing passwords becomes impossible.PermitRootLogin no— attackers always tryroot.AllowUsers— only listed accounts can log in at all.- Turning off agent and X11 forwarding reduces what a compromised session can reach.
Check for conflicting settings in the main file and other drop-ins (the first value read wins for most options), then validate and reload:
sudo sshd -t
sudo systemctl reload ssh
Test a new login from a second terminal before closing the first.
4. Firewall
Only allow SSH from where you need it:
sudo ufw allow from 203.0.113.50 to any port 22 proto tcp # your office/home IP
# or, if your IP changes, allow from anywhere but rate-limit:
sudo ufw limit 22/tcp
5. Better: don't expose SSH publicly
Put SSH on a private network and close port 22 to the internet entirely:
- Tailscale or WireGuard — SSH only over your private network. (What is Tailscale?)
- Your cloud provider's firewall limited to a bastion host or VPN.
Nothing to brute-force if bots can't reach it.
6. Ban repeat offenders
fail2ban bans IPs with repeated failures — mostly log hygiene once passwords are off, but cheap to add. (fail2ban)
7. What about changing the port?
Moving SSH from 22 to, say, 2222 cuts log noise from dumb bots but isn't real security — scanners find it. Fine as a bonus; don't count on it.
8. Extra hardening for sensitive servers
- Hardware-backed keys (
ed25519-skwith a security key like a YubiKey) — the private key can't be copied off the device. - SSH certificates — short-lived, signed credentials instead of long-lived keys in
authorized_keys; worth it with a team. - Two-factor via a PAM module (TOTP) for password-less-but-two-factor setups. (Two-factor authentication)
9. Audit access regularly
cat ~/.ssh/authorized_keys # for each user
last -a | head # recent logins
journalctl -u ssh --since today # attempts
Remove keys for people and laptops that no longer need access. Give each person (and each automated deploy) its own key, so you can revoke one without changing everything. (Principle of least privilege)
10. Keep it updated
OpenSSH vulnerabilities are rare but serious. Enable automatic security updates. (How to secure a new VPS)
EasySpawn servers are reachable over SSH as well as the web and your phone, with the firewall and OS patching handled for you — and your personal private keys never need to be copied onto the server. See how it works or join the waitlist.
Related: SSH Keys Explained · How to Secure a New VPS · fail2ban · The SSH Config File Explained
Keep reading
What Is Tailscale? A Private Network for Your Devices and Servers
Tailscale builds a private, encrypted network (a tailnet) between your laptops, phones and servers using WireGuard, with no ports to open. How it works, common uses — private SSH, reaching databases and admin tools, home labs — MagicDNS, ACLs, Funnel and Serve, and alternatives like Headscale and plain WireGuard.
Writing a systemd Service File for Your App (With Hardening)
A production-ready systemd unit for a Node.js or Python app, explained: Type, User, WorkingDirectory, EnvironmentFile, Restart and backoff, graceful stop, resource limits, logging, and the sandboxing options (ProtectSystem, NoNewPrivileges, PrivateTmp) that limit damage if the app is compromised.