Basic Server Protection: ssh, Firewall, fail2ban
Before you install the panel and nodes, the server needs to be locked down. This is the base I run on every fresh VPS in five minutes: firewall, ssh by key, fail2ban. Without it, any clean server collects thousands of brute-force attempts from the internet within a day.
This material is about engineering your own infrastructure and is educational in nature. You comply with the laws of your own jurisdiction yourself.
A fresh VPS with a public IP isn't a "blank slate" but a server that will start being scanned and brute-forced within an hour. Basic protection is three fronts: the firewall (what's exposed to the outside at all), ssh (how you log in), and fail2ban (what to do with those who hammer at it). Let's run through them in order.
Firewall: close everything unnecessary
The rule is simple — by default deny incoming, open only what's actually needed. On Ubuntu/Debian that's ufw:
ufw default deny incoming # all incoming — closed
ufw default allow outgoing # outgoing — free
ufw allow 22/tcp # SSH
ufw allow 443/tcp # inbound working port
ufw --force enableOn a node, add a rule for the daemon port, open only for the panel IP:
# node daemon port — accept only from the panel server
ufw allow from PANEL_IP to any port 2222 proto tcpThe point is for the minimum to be exposed outward. Everything internal — panel, DB, subscription page — listens on 127.0.0.1 and isn't visible from the internet. Fewer open ports — smaller attack surface.
SSH: key only
An ssh password gets brute-forced around the clock. We switch login to a key and disable the password entirely.
First, on your own machine, create a key (if you don't have one) and copy it to the server:
# on YOUR OWN computer
ssh-keygen -t ed25519 -C "server-admin"
ssh-copy-id root@SERVER_IPNow on the server we disable password login and root password login:
sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config
systemctl restart sshCritical: verify key login in a new terminal window without closing the current session. If something went wrong with the key and you've already disabled the password, you'll lock yourself out and have to go into the host's console.
fail2ban: ban brute-force automatically
Even with the password disabled, the log fills up with login attempts. fail2ban reads the log and temporarily bans those who hammer at it:
apt -y install fail2ban
cat >/etc/fail2ban/jail.d/local.conf <<'EOF'
[sshd]
enabled = true
maxretry = 4
bantime = 1h
findtime = 10m
EOF
systemctl enable --now fail2banThe rule logic: four failed attempts in ten minutes — a one-hour ban. The values can be tightened, but don't overdo it: too aggressive a ban risks cutting you off yourself on a typo.
Check that fail2ban is alive and already catching someone:
# jail status and the list of banned IPs
fail2ban-client status sshdKeep the system fresh
Half of all breaches aren't clever attacks but unpatched holes in old software. Regular updates close them for free:
apt update && apt -y upgradeOn prod it makes sense to enable automatic security updates (unattended-upgrades) so critical patches arrive without your involvement. Update the node and panel separately, reading their changelogs.
Checklist
- [ ] ufw is on, default deny incoming.
- [ ] Only necessary ports are exposed outward, internal stuff is on
127.0.0.1. - [ ] Node daemon port open only for the panel IP.
- [ ] SSH by key, password and root password login disabled.
- [ ] fail2ban is up and catching brute-force.
- [ ] System is updated, auto-patches enabled.
This is the foundation under any service server. Next, once the panel is on it, it's locked down with a separate layer — reverse proxy, allowlist, hidden subdomain — that's in the article "Panel Hardening: Locking Down Access."
Next guide Detecting Key Sharing: How Distribution Gets Caught → ↗ Article unclear or something off? Message me and I will help or fix it. @notrealvpn →