A freshly provisioned VPS is not a neutral, waiting server — it is a target. Internet-wide scanners catalogue new IP ranges continuously, and automated botnets begin SSH brute-force attempts within the first hour a default-configured server comes online. The window between your first login and a successful compromise is often measured in days, sometimes hours. Everything in this article is designed to be completed during that first SSH session, in under 30 minutes, using only commands you can paste into a terminal.
Step 1: Generate an SSH Key Pair and Disable Password Login
Password authentication is the single most attacked authentication method on the public internet. An Ed25519 key with a high key-derivation round count is computationally infeasible to brute-force with current hardware, while a weak password can fall in seconds to dictionary attacks. Generate the key on your local machine, never on the server:
ssh-keygen -t ed25519 -a 100 -f ~/.ssh/vps_key
ssh-copy-id -i ~/.ssh/vps_key.pub root@YOUR_VPS_IP
Now harden the SSH daemon on the server by editing /etc/ssh/sshd_config:
Port 2222— move SSH off the default port to cut 99% of automated scansPermitRootLogin prohibit-password— root may only log in with a keyPasswordAuthentication no— disable password auth entirelyMaxAuthTries 3— limit authentication attempts per connectionAllowUsers deploy— whitelist the only user allowed to log in
Restart with systemctl restart ssh, then before closing your current session, open a second terminal and verify key login works on the new port. Locking yourself out is the only real risk in this step.
Step 2: Create a Non-Root User With sudo
Operating as root full-time turns every typo into a potential disaster — one misplaced rm -rf or a compromised web application running as root wipes or owns the entire server. Create a regular administrative user and copy your key over:
adduser deploy
usermod -aG sudo deploy
mkdir -p /home/deploy/.ssh
cp ~/.ssh/authorized_keys /home/deploy/.ssh/
chown -R deploy:deploy /home/deploy/.ssh
chmod 700 /home/deploy/.ssh && chmod 600 /home/deploy/.ssh/authorized_keys
Once sudo works from the new user, set PermitRootLogin no in sshd_config so root cannot log in at all.
Step 3: Enable a Default-Deny Firewall
A default-deny policy blocks every incoming connection except the handful of ports you explicitly open. UFW is the fastest way to get there on Ubuntu and Debian:
ufw default deny incoming
ufw default allow outgoing
ufw allow 2222/tcp comment 'SSH'
ufw allow 80/tcp comment 'HTTP'
ufw allow 443/tcp comment 'HTTPS'
ufw --force enable
ufw status verbose
| Port | Service | Rule |
|---|---|---|
| 2222/tcp | SSH (moved from 22) | Allow from your IP only, if possible |
| 80/tcp | HTTP | Allow |
| 443/tcp | HTTPS | Allow |
| 3306 / 5432 | MySQL / PostgreSQL | Never open — bind to 127.0.0.1 |
Databases belong on localhost. If you need remote access, use an SSH tunnel or WireGuard instead of exposing the port to the internet.
Step 4: Install Fail2ban for Brute-Force Protection
Fail2ban watches authentication logs and bans IP addresses that fail repeatedly. It is a second line of defence behind key-only auth, and it also protects web login pages:
apt install fail2ban
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
In jail.local, configure the SSH jail for your non-default port:
[sshd]
enabled = true
port = 2222
maxretry = 5
findtime = 10m
bantime = 1h
Verify it is actually watching: fail2ban-client status sshd should show a log path and a ban count.
Step 5: Enable Automatic Security Updates
Verizon’s Data Breach Investigations Report has repeatedly found that the majority of breaches exploit known vulnerabilities with patches that were never applied. On Ubuntu and Debian, unattended-upgrades closes that gap:
apt install unattended-upgrades
dpkg-reconfigure --priority=low unattended-upgrades
Confirm /etc/apt/apt.conf.d/20auto-upgrades contains:
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
Step 6: Audit Listening Services
Most VPS images ship with services you do not need. ss -tulpn lists everything listening on a network port; anything you do not recognise should be stopped and disabled with systemctl disable --now <service>. Fewer open ports means fewer attack surfaces, period.
The 10-Minute Verification Checklist
- SSH into the new non-default port using your key — password prompt must not appear
sudo -vworks for the deploy user, andPermitRootLogin nois activeufw status verboseshows default deny + only your allowed portsfail2ban-client status sshdreports an active jailunattended-upgrades --dry-runcompletes without errors
Beyond the First Session: File Integrity and Log Review
Once the six core steps are in place, two additions give you early warning when something does slip through. AIDE (Advanced Intrusion Detection Environment) builds a cryptographic database of system binaries and configuration files; a nightly aide --check run flags any unauthorized modification, which is how you detect a backdoored binary before it does damage. Logwatch, meanwhile, emails you a daily digest of authentication failures, service restarts, and disk warnings, so a sudden spike in failed logins is visible the next morning instead of months later.
apt install aide logwatch
aideinit && mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db
logwatch --output mail --mailto [email protected] --detail high
Schedule both with cron: aide --check nightly at 03:00 and Logwatch at 06:00. On a small VPS each run costs a few megabytes of I/O and under a minute of CPU, which is a small price for knowing that your binaries and logs are being watched.
These six steps take roughly 25 minutes on a fresh server and reduce the realistic attack surface by orders of magnitude. The same discipline applies no matter which provider you deploy on — if you are still choosing one, compare providers side by side in our VPS comparison table, and for plan-level differences such as DDoS protection and backup offerings, see the full feature breakdown on our VPS page before you commit. A provider that offers snapshots and automated backups makes the recovery questions in our FAQ much easier to answer later.



Leave a Reply
You must be logged in to post a comment.