
How to Secure a Linux VPS in 30 Minutes Without Locking Yourself Out
Mahmud Hasan
October 16, 2026
Denmark's national ID register exposed 8.8 million people this month, and the reported cause was a 123456 password at the company holding legitimate access to the database. That is the real threat model for your server: not a hooded genius, but boring defaults meeting automated scripts. A brand-new VPS with a fresh public IP starts collecting SSH brute-force attempts within minutes of coming online — before it hosts anything.
Here is the fix, and it takes about thirty minutes. Seven steps, in an order that matters — the order is what stops you from locking yourself out.
Know what you're actually defending against
Forget the movie version. The realistic attackers for a small server are bots brute-forcing SSH passwords around the clock, scanners hunting for services left open on default ports, and exploit scripts probing for software that was patched months ago. None of them are patient or clever. They are scripts playing a numbers game across millions of IPs.
So the strategy is simple: shrink the attack surface, make the remaining entry points expensive, keep software patched, and set yourself up to notice when something looks wrong. The steps below follow exactly that order.
Steps 1–2: The front door — users and SSH
Working as root every day is the original sin of server administration: every command carries full destructive power, a compromised session hands over the entire machine, and every log line just says "root" instead of telling you who did what. The fix takes a minute:
adduser deploy
usermod -aG sudo deploy
su - deploy
sudo whoami
If that last command prints root, your sudo access works. Pick an unusual username — attackers' wordlists are full of "admin" and "ubuntu." And do not skip the test: disabling root login before confirming the replacement account is the classic self-inflicted lockout, and the only cure is your provider's rescue console.
SSH is the single most attacked service on the internet, so it comes next. Generate the keypair on your local machine, not the server:
ssh-keygen -t ed25519 -C "deploy@yourserver"
ssh-copy-id deploy@your-server-ip
Open a new terminal and SSH in as the deploy user. If you land in a shell without a password, the key works — only now touch /etc/ssh/sshd_config:
PasswordAuthentication no
PermitRootLogin no
PubkeyAuthentication yes
The first line makes every password-guessing bot on Earth permanently irrelevant to you. Reload the daemon, test from the second terminal, and only then close your original session.
One myth to kill: moving SSH off port 22 does not add real security. Scanners find nonstandard ports in seconds. It only quiets your logs, which has value when you start reading them — but treat it as housekeeping, not protection. A nonstandard port without keys and a firewall is security theater.
Steps 3–4: The perimeter — firewall and fail2ban
A firewall flips your posture from "everything open unless closed" to "everything closed unless opened." On Ubuntu and Debian, UFW does this in five commands — but the order matters, because enabling a firewall that doesn't allow SSH disconnects you on the spot:
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
Allow SSH before enabling — that line is your lifeline. The web ports apply only if this machine serves websites. The rule of thumb: every open port is a promise that something safe answers there. Three open ports means three promises to keep. Thirty means you've lost track.
Even with passwords disabled, hostile connections still arrive, fill your logs, and eat resources. fail2ban watches the auth log and temporarily bans IPs that fail repeatedly. Install it — then don't edit the shipped config, because package updates overwrite jail.conf. Create a local override:
sudo apt install fail2ban
# in /etc/fail2ban/jail.local:
[sshd]
enabled = true
maxretry = 4
findtime = 10m
bantime = 1h
Four failures within ten minutes earns a one-hour ban. Confirm the jail is live with fail2ban-client status sshd — a fresh server typically collects its first bans within hours. But IP blocking is the alarm system, not the locks; keys and the firewall do the real work.
Step 5: Automatic security updates
Most successful server compromises don't involve clever zero-days. They exploit vulnerabilities patched months earlier on machines nobody updated. Automating security patches removes forgetfulness from the equation:
sudo apt install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades
Answer yes, and Ubuntu installs security patches daily without your involvement. The default applies security updates only — not feature upgrades — the conservative behavior a production server wants. "Automatic updates will break my app" is a fair fear; the answer is that security patches don't need to wait for human judgment the way application updates do.
One permanent habit: kernel patches only take effect after a restart, and a server with a pending reboot is patched on disk but not in memory. Check every time you log in:
cat /var/run/reboot-required 2>/dev/null
If the flag is there, schedule the reboot. It should never survive the week.
Step 6: Close the doors you forgot — including the Docker trap
Every service listening on a public port is a doorway, and you can't defend doorways you forgot exist. Audit what your server actually exposes:
sudo ss -tulpn
Read the output ruthlessly. SSH, your web server, and little else should listen on public interfaces. Anything bound to 0.0.0.0 that doesn't need internet exposure — databases, Redis, app ports, admin panels — should be disabled or rebound to 127.0.0.1. Dashboards and APIs you expose yourself should sit behind a reverse proxy on 443, so TLS, access control, and your firewall story all live in one place.
Now the trap that catches almost everyone who hardens a server and then installs containers: Docker publishes ports by manipulating iptables directly, walking straight past your UFW rules. A container started with -p 5678:5678 is internet-reachable even though ufw status shows nothing allowed. Publish to localhost only:
docker run -p 127.0.0.1:5678:5678 ...
Step 7: Notice when something's wrong — and keep backups
Hardening without visibility is locking the doors and never checking the windows. You don't need an enterprise SIEM; you need two habits. Habit one: read the auth log occasionally — one command shows who got in and who was refused:
sudo journalctl -u ssh --since today
Habit two: watch for change. Failed sudo attempts, logins at strange hours, unfamiliar IPs succeeding — these are the signals worth a closer look.
Backups are the final layer, because hardening prevents but never guarantees. Follow the 3-2-1 rule: three copies of your data, on two different media, one offsite. Then actually test a restore — a backup you've never restored is a rumor, not a backup. The honest summary: hardening protects the server you have; backups protect the business it runs.
The 30-minute checklist
- Sudo user:
adduser+usermod -aG sudo, test it, then touch root - SSH keys: ed25519 keys,
PasswordAuthentication no,PermitRootLogin no, test in a second terminal - Firewall: UFW deny-incoming, allow SSH first, then 80/443
- fail2ban: override in
jail.local, sshd jail, confirm withfail2ban-client status sshd - Auto updates: unattended-upgrades, security-only default, check
/var/run/reboot-required - Surface audit:
ss -tulpn, bind internals to127.0.0.1, remember the Docker-UFW trap - Visibility + backups: auth-log habit, alerts, tested 3-2-1 backups
None of these steps requires deep expertise, and all of them together take half an hour. The result is a server where the constant background scanning of the internet simply stops mattering.
Related reading
Once the box is locked down, two things usually follow: putting an app on it, and debugging it when Nginx complains. Deploying a Next.js app on a VPS the production way covers the full setup, and when a deploy ends in a gateway error, the 502 Bad Gateway walkthrough shows the diagnostic order that finds the real cause.
References
- How to Secure a Linux VPS: Complete Hardening Guide — WebHost365
- VPS Security Checklist: 15 Linux Hardening Steps — CyberPanel
- How to Secure Your Linux VPS: The First 10 Essential Steps — dev.to
- Denmark data breach: hacker reportedly used '123456' password to access national registry — Economic Times
Comments
More in Cybersecurity

Is the AI Bubble About to Burst? The Honest 2026 Answer
The IMF just put a number on the AI-bubble debate: an investment bust could shave roughly a point off global GDP by 2028. This week gave both sides fresh ammunition — here is the honest middle.
Read more
