Every new VPS gets the same first hour: create a user, lock down SSH, set up a firewall, install fail2ban, turn on automatic updates… and then forget one of them on the next server.

So we turned our checklist into a small open-source script: veloxahost/server-hardening. One command, readable configs, safe to re-run.

What it does

  • Creates a sudo user and installs your SSH key
  • SSH: keys only, no root login, no passwords — via a drop-in file, validated with sshd -t before restart
  • UFW: deny inbound, rate-limit SSH, allow 80/443
  • fail2ban with the systemd backend (the reliable choice on Ubuntu 24.04) and escalating bans
  • Unattended security upgrades + needrestart
  • auditd rules for identity files, sudoers, sshd config and root commands
  • Kernel sysctl hardening that doesn't break Docker
  • A Lynis audit at the end so you get a score

Usage

On a fresh Ubuntu 24.04 server (22.04 and Debian 12 work too), keep your current session open and run:

git clone https://github.com/veloxahost/server-hardening.git cd server-hardening sudo NEW_USER=deploy SSH_KEY="ssh-ed25519 AAAA... you@example.com" ./harden.sh 

Then open a new terminal and check ssh deploy@your-server works before logging out.

Options are plain environment variables:

Var Default Meaning
NEW_USER deploy sudo user to create
SSH_KEY required public key for that user
SSH_PORT 22 SSH port to allow
ALLOW_PORTS 80,443 extra TCP ports to open
ENABLE_IP_FORWARD 0 set 1 on Docker hosts
RUN_LYNIS 1 run the audit at the end

Three things people get wrong on Ubuntu 24.04

1. Editing sshd_config directly. 24.04 reads /etc/ssh/sshd_config.d/*.conf first. Put your settings in a drop-in so package upgrades never overwrite them.

2. fail2ban watching a log file that's empty. SSH logs go to the journal now. Use backend = systemd or your sshd jail will show zero failures forever.

3. Trusting UFW with Docker. Ports published with -p 8080:8080 bypass UFW completely. Bind internal services to 127.0.0.1 and put a reverse proxy in front.

Why not Ansible?

If you already run Ansible, use it. This is for the "one server, five minutes" case: a single bash script you can read top to bottom before you run it as root.

More

PRs and issues welcome — especially for other distros.

Disclosure: I work on VeloxaHost, a hosting platform. The script is MIT-licensed and works on any Linux server.