Steps taken to harden an Ubuntu Noble (24.04) VPS on Hetzner (arm64).
SSH hardening
Move SSH to a non-standard port and lock down authentication.
Config is split across /etc/ssh/sshd_config and /etc/ssh/sshd_config.d/*.conf.
# Key settings to ensure:
Port 2222
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
KbdInteractiveAuthentication no
PermitEmptyPasswords no
MaxAuthTries 2
X11Forwarding no
AllowAgentForwarding no
Reload after changes:
sudo systemctl reload ssh
SSH keypair
Generate an Ed25519 keypair on your local machine:
ssh-keygen -t ed25519
Copy the public key to the server’s ~/.ssh/authorized_keys.
Firewall (UFW)
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw enable
Initially allow SSH on the public interface:
sudo ufw allow 2222
After Tailscale is set up, restrict SSH to the Tailscale interface only:
sudo ufw allow in on tailscale0 to any port 2222
sudo ufw delete allow 2222
Fail2Ban
Install and enable fail2ban to block brute-force attempts:
sudo apt install fail2ban -y
sudo systemctl enable --now fail2ban
Unattended upgrades
Ensure automatic security updates are enabled:
sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure -plow unattended-upgrades
Tailscale (zero-trust network)
Install Tailscale:
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
Tailscale starts on boot automatically (tailscaled.service is enabled by default).
Once connected, lock down the firewall to Tailscale-only SSH. This makes SSH invisible on the public internet.
Disable unused services
Disable and mask serial consoles that are not needed:
sudo systemctl disable --now serial-getty@ttyAMA0.service serial-getty@ttyS0.service
sudo systemctl mask serial-getty@ttyAMA0.service serial-getty@ttyS0.service
Final state
- SSH only accessible via Tailscale on port 2222
- Key-only authentication, no root login
- Brute-force protection via fail2ban
- Automatic security updates
- No unnecessary services running