Securing SSH Access
SSH (Secure Shell — the encrypted protocol you use to log in to a remote server and run commands) is the front door to almost every Linux server you will ever manage. If an attacker gets through it, they own your machine. The good news is that SSH is also one of the easiest things to lock down hard. This page consolidates the most important hardening steps: switching to key-only authentication, turning off root and password login, optionally moving the port, limiting who can log in, adding idle timeouts, and finally putting fail2ban in front of it all to block brute-force attacks automatically.
Every command below works on a fresh Ubuntu 22.04 or 24.04 LTS server. The SSH server software on Ubuntu is called OpenSSH, and its main configuration file lives at /etc/ssh/sshd_config.
Before you change anything: keep a second SSH session open in another terminal while you edit the config and restart the service. If you lock yourself out, that open session lets you fix the mistake. Never test a change by closing your only connection.
Step 1: Use SSH keys instead of passwords
An SSH key is a pair of cryptographic files: a private key that stays secret on your laptop, and a public key you copy to the server. The server lets you in only if your private key matches the public key it has on file. This is far stronger than a password, which can be guessed or brute-forced.
When to use this
Always. Key authentication should be your default for every server. The only time you fall back to passwords is for a brand-new server during initial setup, and you remove that fallback immediately afterwards.
On your local machine, generate a key if you do not already have one:
ssh-keygen -t ed25519 -C "[email protected]"
ed25519 is a modern, fast, and very secure key type — prefer it over the older RSA. Press Enter to accept the default path (~/.ssh/id_ed25519) and set a passphrase when prompted (this encrypts the private key on disk).
Now copy the public key to your server:
ssh-copy-id [email protected]
Output:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh '[email protected]'"
and check to make sure that only the key(s) you wanted were added.
Test it — you should log in without being asked for a password:
ssh [email protected]
Step 2: Disable password and root login
Once key login works, turn off password authentication so brute-force attacks become useless, and block direct root login so attackers cannot target the all-powerful root account.
Open the config file:
sudo nano /etc/ssh/sshd_config
Set (or add) these lines:
PasswordAuthentication no
PubkeyAuthentication yes
PermitRootLogin no
KbdInteractiveAuthentication no
PermitRootLogin no means you log in as a normal user (e.g. deploy) and use sudo for admin tasks — this gives you an audit trail of who did what. Apply the changes by reloading the SSH service:
sudo systemctl reload ssh
On Ubuntu 24.04 the service is socket-activated. If
reload sshreports the unit is not found, usesudo systemctl restart ssh.socketfollowed bysudo systemctl restart ssh.
Step 3: Limit who can log in with AllowUsers
By default any valid user account can attempt an SSH login. You can whitelist only the accounts that are supposed to use SSH. Anyone not on the list is rejected before authentication even starts.
Add this line to /etc/ssh/sshd_config:
AllowUsers deploy admin
When to use this
Use AllowUsers whenever your server has service accounts (like www-data or postgres) that should never be logged into interactively. It is a simple, powerful way to shrink your attack surface. If you manage users by group instead, use AllowGroups sshusers and add people to that group.
Step 4: Optionally change the SSH port
SSH listens on port 22 by default. Moving it to a high, non-standard port (e.g. 2222) does not make SSH more secure on its own — a determined attacker scans all ports. What it does is dramatically reduce noise: automated bots that hammer port 22 all day simply never find you, so your logs stay clean.
When to use this — and when not
| Situation | Change the port? |
|---|---|
| Public-facing server drowning in port-22 brute-force logs | Yes, reduces noise |
| You rely on a strict corporate firewall that only allows port 22 outbound | No, you may lock out admins |
| You think it replaces key auth or fail2ban | No — it is cosmetic, not a real control |
To change it, edit the config:
Port 2222
If you use the ufw firewall (Ubuntu’s Uncomplicated Firewall), open the new port and close the old one before restarting SSH:
sudo ufw allow 2222/tcp
sudo systemctl restart ssh
sudo ufw delete allow OpenSSH
From now on you connect with ssh -p 2222 [email protected].
Step 5: Add idle session timeouts
A logged-in SSH session left open on an unlocked laptop is a real risk. You can have the server automatically disconnect idle sessions.
Add to /etc/ssh/sshd_config:
ClientAliveInterval 300
ClientAliveCountMax 2
This sends a keep-alive check every 300 seconds (5 minutes). After 2 missed checks (10 minutes of silence) the server drops the connection. Reload SSH to apply.
Step 6: Block brute-force attacks with fail2ban
fail2ban is a small daemon (background program) that watches your log files for repeated failed login attempts and automatically bans the offending IP address in the firewall for a while. Even with password login disabled, bots will still pound your server — fail2ban makes them go away.
Install it:
sudo apt update
sudo apt install -y fail2ban
Create a local config (never edit the package’s jail.conf directly — it gets overwritten on updates):
sudo nano /etc/fail2ban/jail.local
[sshd]
enabled = true
port = 2222
maxretry = 4
findtime = 10m
bantime = 1h
This bans any IP that fails 4 times within 10 minutes, for 1 hour. (Set port = 22 if you did not change it.) Start the service:
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd
Output:
Status for the jail: sshd
|- Filter
| |- Currently failed: 1
| |- Total failed: 27
| `- File list: /var/log/auth.log
`- Actions
|- Currently banned: 2
|- Total banned: 6
`- Banned IP list: 45.227.255.x 193.32.162.x
Best Practices
- Always confirm key login works in a second terminal before disabling password authentication.
- Protect your private key with a passphrase and never copy it onto a server — only the public key belongs there.
- Keep
PermitRootLogin noand log in as a normal user withsudofor a clean audit trail. - Combine layers: keys,
AllowUsers, a firewall, and fail2ban together — no single control is enough. - Treat a custom SSH port as noise reduction only, never as a real security control.
- Rotate or revoke keys promptly when a laptop is lost or someone leaves the team.
- Review
/var/log/auth.logandfail2ban-client status sshdperiodically to see what is hitting your door.