Hardening a Fresh VPS: The 30-Minute Production Checklist
Every new VPS ships wide open. Here is the exact sequence we run at Paj Digital Solutions before a single site goes live — SSH keys, fail2ban, kernel tuning and firewall rules.
Why the first 30 minutes matter
A freshly provisioned VPS is scanned within minutes of getting a public IP. Bots hammer port 22 with credential lists long before you have deployed anything. The window between provisioning and hardening is the single riskiest period in a server's life.
Step 1 — Keys only, never passwords
Generate a key locally, push it, then disable password auth entirely.
ssh-keygen -t ed25519 -C class="text-code-string">"ops@pajdigital"
ssh-copy-id -i ~/.ssh/id_ed25519.pub root@your.server.ip
sed -i class="text-code-string">'s/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
systemctl reload sshdStep 2 — A non-root deploy user
Running your stack as root is how a single template injection becomes a full box takeover.
adduser deploy
usermod -aG sudo deploy
rsync --archive --chown=deploy:deploy ~/.ssh /home/deployStep 3 — Firewall defaults
Deny everything inbound, then open only what you serve.
ufw default deny incoming
ufw default allow outgoing
ufw allow 22,80,443/tcp
ufw enableStep 4 — Automatic security updates
Unattended upgrades are not optional on an internet-facing box.
apt install -y unattended-upgrades
dpkg-reconfigure --priority=low unattended-upgradesStep 5 — Watch the logs
Install fail2ban, point it at sshd and your web server, then actually read the jail status weekly. Most breaches are loud for days before they are damaging.
Wrapping up
None of this is exotic. It is a checklist, and checklists are how infrastructure teams stay boring. Boring is the goal.
Paj Digital Labs
The engineering journal of Paj Digital Solutions — hosting, server infrastructure and web engineering, written by the people who run the servers.
Related reading
DNS Records Explained for People Who Ship Websites
A, AAAA, CNAME, MX, TXT and the TTL decisions that decide whether your migration is invisible or a two-hour outage.