https://www.linkedin.com/feed/update/urn:li:groupPost:25827-7499516013978214400/
Minimum security setup for a solo dev server — from a real deployment
I just shipped a side project to a VPS and had to lock it down before accepting real payments. Here's my non-negotiable checklist — everything took ~30 minutes and cost $0: 1. SSH: keys only, passwords off
bash
ssh-keygen -t ed25519 ssh-copy-id root@your-server
Then disable password auth:
bash
sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
systemctl restart sshd
Plus fail2ban for the noise:
bash
apt install fail2ban && systemctl enable --now fail2ban
Firewall: deny by default Only 22, 80 and 443 open. Everything else — FTP, Telnet, RDP, databases — blocked. If it's not in production, it shouldn't be reachable.
Secrets never touch git
bash
echo ".env" >> .gitignore chmod 600 .env
Tokens, API keys and webhook secrets live only on the server. I verified the repo contains no secrets before pushing.
- Automatic security updates
bash
apt install unattended-upgrades
Patches apply while I sleep.
- Webhooks: verify signatures, always If your payment provider calls your server, verify the HMAC signature of every request — it's 5 lines:
python
digest = hmac.new(secret, body, hashlib.sha256).hexdigest() if not hmac.compare_digest(digest, signature): return 403 # not from the provider
Without this, anyone who knows your webhook URL can forge events — activate users for free, or cancel paying ones.
TLS everywhere, services nowhere Automatic HTTPS via Caddy + Let's Encrypt (free). Internal services bind to localhost and sit behind a reverse proxy — never exposed directly.
Least privilege mindset Every port you open, every secret you share, every service you expose is attack surface. Ask: "does this need to be public?" — usually the answer is no.
The best part: none of this requires being a security expert. It's a checklist. Run it before you take your first real payment, not after.
