Auth logs on a fresh VPS: 200 root / admin123 attempts in four hours — bots, not personal targeting. The server falls not to an SSH zero-day, but because PasswordAuthentication yes lingered after install. Four habits would have closed 95% of that surface.
SSH is your VPS admin door. On small projects, it is often the only one. Securing it needs no dedicated security team — just basic discipline applied before the first automated scan succeeds.
Automatic scans target port 22 worldwide around the clock. The good news: they hunt default configurations — root password, weak keys, outdated services. Four well-applied habits drastically reduce surface without exotic tools. Pair them with a VPS firewall and regular updates.
Habit 1: key authentication only
Generate Ed25519 key locally, deploy public key in ~/.ssh/authorized_keys for a dedicated user. In /etc/ssh/sshd_config, set PasswordAuthentication no, PubkeyAuthentication yes, PermitRootLogin no. Test new session before closing old one, then reload sshd.
Key without passphrase on stolen laptop = master key. Passphrase or hardware token for production.
Habit 2: non-root user plus sudo
Create deploy or admin in sudo group. Direct root forbidden; ops via logged sudo. Disable demo accounts from cloud image.
Habit 3: fail2ban (or equivalent)
sshd jail — ban IP after N failures. Pair with restrictive firewall. Whitelist fixed office IP. Do not rely on port 22 change alone — scans cover the range.
Habit 4: updates and minimal surface
Automatic security patches (unattended-upgrades). Remove unnecessary listening services. MaxAuthTries 3, AllowUsers deploy for small team.
Bastion and team access
Multiple servers: one SSH bastion (restricted IP) or WireGuard VPN; prod not public SSH if possible. Different keys staging/production. Revoke keys on employee departure — deployment secrets includes CI SSH keys.
| Bad | Better |
|---|---|
| root + password | user + key + sudo |
| same key everywhere | keys per environment |
| SSH world 0.0.0.0/0 | admin IP firewall |
The climax: hardened SSH does not protect the app
Decide and move forward without blind spots
Generate Ed25519 key with passphrase. Create sudo user and test key login. Disable password authentication and root SSH. Enable fail2ban and firewall restricting port 22. Document rescue console access. Compare hosts with rescue console via the directory.
Frequently asked questions
RSA or Ed25519 key?
Ed25519 is recommended for a fresh VPS: short, modern and quick to deploy. RSA 4096 remains acceptable if you must support a legacy environment. On a laptop, protect the private key with a passphrase — or an SSH agent locked on session close.
Disable root SSH completely?
Yes, once a sudo user is created and tested from a new parallel session. Keep host console (KVM or serial) accessible: an error in sshd_config can lock you out before the next deploy. Test key login before closing the root session.
Is fail2ban enough?
Not alone. fail2ban complements keys and disabled passwords by banning IPs after repeated failures. Tune ban duration and whitelist fixed office IP if you have one — otherwise you may lock yourself out after your own attempts.
SSH on several servers — how to organise?
Use distinct keys per environment (staging, production), a Host block in ~/.ssh/config per server, and a bastion or WireGuard VPN for production. Restrict port 22 via VPS firewall to authorised admin addresses; revoke keys when a team member leaves.
Secure SSH: four obvious habits — keys, no root password, sudo, fail2ban — that too many VPSes apply only after the first successful scan.