Hardening a fresh VPS: SSH keys, firewall and Fail2ban
Kort antwoord
Do four things before putting a fresh VPS to real use: switch to SSH key authentication and turn off password logins, install and configure Fail2ban, and set up the portal-level firewall in front of it. Each step is covered in full elsewhere in this knowledge base, this article is the checklist that ties them together.
A freshly deployed VPS is reachable on the internet the moment it's created, and automated scanners will find it within minutes. None of the steps below are difficult on their own, doing them in order, before you start using the server, is what matters.
1. Switch to SSH key authentication
Generate and install a key pair
Generate an SSH key pair on your own machine and copy the public key to the server. See Creating an SSH key pair for the full walkthrough, including ssh-keygen and ssh-copy-id.
For a new Flexible VPS, it's simpler to add the key before the server exists: go to Flexible VPS → Settings in Portal and add your public key there, manually or imported from GitHub or GitLab, then select it during creation so it's already in place on first boot.
Test the key before touching passwords
Log in with the key from a new terminal window while your existing session stays open. Don't move on to the next step until this works.
2. Disable password authentication
Once key login is confirmed working, turn off password logins. Do not just append the settings to /etc/ssh/sshd_config. On most current cloud images that file starts with an Include /etc/ssh/sshd_config.d/*.conf line, the image ships a drop-in file there that sets PasswordAuthentication yes, and sshd keeps the first value it reads for a setting. An edit added at the bottom of the main file is silently ignored, and password login stays on while you think you switched it off.
Start by looking at what is already set:
grep -rnE '^[[:space:]]*(Include|PasswordAuthentication|PermitRootLogin)' /etc/ssh/sshd_config /etc/ssh/sshd_config.d/ 2>/dev/nullIf there is an Include line and a drop-in already sets these options, either edit that drop-in, or add your own file with a name that sorts before it. Files in /etc/ssh/sshd_config.d/ are read in name order, so 00-hardening.conf is read before a shipped 50-cloud-init.conf and its values win. Create /etc/ssh/sshd_config.d/00-hardening.conf with:
PasswordAuthentication no
PermitRootLogin noIf your image has no Include line and no sshd_config.d directory, put the same two lines in /etc/ssh/sshd_config itself.
Now check the syntax and, more importantly, the values sshd will actually use:
sudo sshd -t
sudo sshd -T | grep -iE 'passwordauthentication|permitrootlogin'Both lines must come back as no. If either still says yes, another file is winning, so go back to the grep above and deal with it before you restart anything.
Restart the SSH service to apply it:
# Debian / Ubuntu
sudo systemctl restart ssh
# Rocky Linux / RHEL-based
sudo systemctl restart sshdKeep your existing session open until you've confirmed a fresh login with the key still succeeds. If you get locked out, Portal's console access can get you back in without SSH; see How to improve your SSH security for the reasoning behind this step and further hardening options, such as changing the default SSH port.
3. Install and configure Fail2ban
Fail2ban watches your authentication logs and temporarily blocks IP addresses after repeated failed login attempts. It's a standard second layer, useful even with password authentication already disabled, since it also covers other services you might run.
Install it
# Debian / Ubuntu
sudo apt update && sudo apt install fail2ban
Rocky Linux / RHEL-based
sudo dnf install fail2banCreate a local override
Don't edit jail.conf directly, it gets overwritten on updates. Copy it to a local override file instead:
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.localIn jail.local, enable the SSH jail and set reasonable thresholds, for example:
[sshd]
enabled = true
maxretry = 5
bantime = 1h
findtime = 10mStart and enable the service
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshdThe status command shows current bans and confirms the jail is active.
4. Set up the portal-level firewall
The steps above all run on the VPS itself. The portal firewall sits in front of it as a separate layer, a managed gateway per region, and is worth setting up even once the server-side hardening is done.
Anything your server needs to reach outbound beyond the firewall's default policy has to be added explicitly as a rule under Firewall Rules. Inbound access to the VPS is controlled the same way, through NAT rules rather than exposing the server directly. See Firewall basics in Portal for how to create one, attach your VPS's network, and set up port forwarding.
Checklist summary
- SSH key pair generated and tested, see Creating an SSH key pair
- Password authentication and root login disabled in
sshd_config - Fail2ban installed, configured with a local override, and running
- Portal-level firewall created for the region and attached to the VPS, see Firewall basics in Portal
- Operating system and OpenSSH kept up to date on an ongoing basis