5 min read0 views

My checklist for every VPS

Recently bought a server for my indie hacking projects. This is my brain dump for what I will do for any new VPS I have:

  • The essentials
    • System Updates
    • SSH Setup
    • Disable root password login
    • Firewall (UFW)
    • Fail2Ban
  • Good-to-haves
    • Self-hosted Vercel/Heroku: Dokploy/Coolify/Nixopus
    • Monitor w/ Uptime Kuma

System Updates

First thing I always do is make sure everything is up to date.

# 🌐 On your server:
sudo apt update && sudo apt upgrade -y

If you're not on Ubuntu, also do this to auto-install security patches (it's a set-and-forget):

# 🌐 On your server:
sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure --priority=low unattended-upgrades

SSH Setup

We use Ed25519 instead of RSA. It's the modern standard: more secure, faster, and the keys are much shorter.

# [1️⃣ Generate the key]
# 🖥️ Generate a private/public key pair
ssh-keygen -t ed25519 -C "my-server-key" # my-server-key is a human-readable label, you can also omit and will default to your device name
 
# [2️⃣ Add the public key to the server]
 
# 2.1: ⚡ The fast way
# 🖥️ Do this
ssh-copy-id -i ~/.ssh/id_ed25519.pub root@your-server-ip
# It should say: Number of key(s) added:        1
 
 
# 2.2: 🐌 The slow way
# 🖥️ Copy it
cat ~/.ssh/id_ed25519.pub | pbcopy # Copies on Mac; xclip on Linux; clip on Windows
 
# 🌐 Write to authorized_keys
mkdir -p ~/.ssh
vi ~/.ssh/authorized_keys
# Paste key, save, and exit.
 
# Important: Lock down permissions or SSH might ignore it! (ssh doesn't like it if it's readable by other users)
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
I'm new... How do SSH keys work?

Here is the easiest analogy to understand SSH keys. It is asymmetric encryption, which works like a specific Lock and Key pair:

  • id_ed25519 (The Private Key 🔑): This stays on your computer. You never share this. It is the only key in the world that can open the lock. Generally most devs have just 1 of this for all their servers (this is fine 🐶🔥).

  • id_ed25519.pub (The Public Key 🔒): This is the lock. You upload this to your server. Anyone is allowed to see the lock, but only your private key can open it.

Isn't it safer if the private key is on the server? Think of the Public Key as a Padlock you install on the server's door. The Private Key is the only key in the world that can open that padlock. When you connect, the server points to the padlock and says "Prove you have the key for this." Your laptop uses the private key to solve a math puzzle to prove it, without ever actually sending the secret key over the internet..

Typing ssh [email protected] is hard.
# 🖥️ Run this on your computer
vi ~/.ssh/config
 
# Add this block of code there
Host myserver
    HostName 123.123.123.123  # <-- 1️⃣ Replace with your server IP
    User root                 # <-- 2️⃣ The user you log in as
    IdentityFile ~/.ssh/id_ed25519  # <-- 3️⃣ Optional, but good if you have multiple keys
 
# 🖥️ Now you can do
ssh myserver

Remove password login

Once you have logged in using your SSH key, disable the password "door mat" so bots stop trying to guess it.

vi /etc/ssh/sshd_config
# Find: PasswordAuthentication yes
# 💡 You might find ones that start with `#`, those are comments, find the ones that don't.
# Change to: PasswordAuthentication no
sudo systemctl restart ssh
 
# Logout, then try to go back in with the password just to see if it's disabled.
exit
 
ssh -o PubkeyAuthentication=no -o PreferredAuthentications=password -o PasswordAuthentication=yes root@your-server-ip
# It should say: [email protected]: Permission denied (publickey).

Log out, then back in with your key to be 100% sure it still works.

How do I recover my server if I can't ssh root@your-server-ip anymore?”

Every serious host (Hetzner has “Rescue”, Netcup has “Recovery Console”) gives you a browser-console.
Boot into it, mount your disk, edit /etc/ssh/sshd_configPasswordAuthentication yes, reboot, log in with the root password you set at install, drop in a fresh pubkey, then lock it back down.

After that, add a second SSH key and bookmark the console URL + root password in your password manager so this never ruins a weekend.

Firewall (UFW)

Lock down the ports. Only allow what's necessary (SSH, HTTP, HTTPS). That means you can't access stuff like postgres://, etc.

sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
sudo ufw enable

Still need to hit your Postgres from your laptop? (SSH tunnel)

SSH-tunnel in your GUI (TablePlus, DBeaver, etc.).

  • Usually, GUI tools have an SSH section: server IP, user root, pick your id_ed25519 key.

The client rides the already-allowed SSH port (22) and hops to 5432 internally—no extra firewall rules needed.

Fail2Ban

Simple brute-force protection that bans IPs after too many failed login attempts.

sudo apt install fail2ban -y
 
# Make sure it's running
sudo systemctl status fail2ban

Good-to-haves

  • Self-hosted Vercel/Heroku:

  • Uptime Kuma

    • I personally find this essential, you never know when you have downtime. You want to monitor this.
    • If you haven't yet, add it to any server you own or as a new dokploy app: https://uptime.kuma.pet.
    • Make sure to set it to ping all the services you care about, you can also use it for cron heartbeat monitoring (you add it to the cron execution code), and wire up Telegram/Discord/Slack/Emails so the alerts actually reach you.

References

how levelsio secures a VPS (the guy literally runs a 1m business w/ a VPS) — @levelsio