Security & Hardening — Protect Your Infrastructure
SSH hardening, TLS certificates, fail2ban, access control, and security best practices for self-hosted services and home servers.
Security Is Not Optional
When you self-host, you are the security team. There is no IT department, no SOC, no managed firewall. The good news: the attack surface of a well-configured home server is small. The bad news: one misconfiguration can expose everything.
This guide covers the essentials. None of it is difficult — it just needs doing.
SSH Hardening
SSH is likely the primary way you manage your servers. Lock it down.
Key-Based Authentication Only
- Generate an SSH key pair on your local machine:
ssh-keygen -t ed25519 -C "your-identifier"- Copy the public key to your server:
ssh-copy-id user@server-ip- Disable password authentication in
/etc/ssh/sshd_config:
PasswordAuthentication no
PubkeyAuthentication yes
PermitRootLogin no
MaxAuthTries 3- Restart SSH:
sudo systemctl restart sshdChange the Default Port
Moving SSH from port 22 reduces automated scanning noise by 90%+:
# /etc/ssh/sshd_config
Port 2222This isn't security through obscurity — it's noise reduction. Use it alongside key-based auth, not instead of it.
Fail2ban — Automatic Ban on Failed Logins
Fail2ban monitors log files and bans IPs that show malicious behaviour.
sudo apt install fail2banCreate /etc/fail2ban/jail.local:
[sshd]
enabled = true
port = 2222
maxretry = 3
findtime = 600
bantime = 3600This bans any IP that fails 3 SSH logins within 10 minutes, for 1 hour.
TLS Certificates
Every service exposed to the internet (or even your local network) should use HTTPS. There is no excuse not to — certificates are free.
Let's Encrypt via Caddy (Automatic)
If you use Caddy as your reverse proxy, TLS is automatic. Caddy obtains and renews certificates without any configuration.
Let's Encrypt via Certbot (Manual)
sudo apt install certbot
sudo certbot certonly --standalone -d yourdomain.comCertificates auto-renew. Check with:
sudo certbot renew --dry-runInternal TLS
For services that never face the internet, use a private Certificate Authority. Step-CA or mkcert create trusted certificates for internal domains.
Firewall Configuration
UFW (Uncomplicated Firewall)
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 2222/tcp # SSH
sudo ufw allow 80/tcp # HTTP
sudo ufw allow 443/tcp # HTTPS
sudo ufw enablePrinciple of Least Privilege
Only open ports you need. If a service doesn't need to be reachable from the internet, don't expose it. Use your VPN (WireGuard/Tailscale) for remote access to internal services.
Secrets Management
Never put passwords, API keys, or tokens in plain text files or Docker Compose files.
Options:
- Docker secrets — Built-in for Swarm mode
- Environment files —
.envfiles with restricted permissions (chmod 600) - Vault (HashiCorp) — Enterprise-grade, overkill for most home setups
- Infisical — Self-hostable secrets manager with a clean UI
Minimum viable approach: a .env file with 600 permissions, referenced in your Compose file.
Two-Factor Authentication (2FA)
Enable 2FA on every service that supports it:
- Nextcloud — TOTP app in the app store
- Vaultwarden — Built-in TOTP support
- Gitea/Forgejo — TOTP and WebAuthn
- SSH — Via
pam_google_authenticator
Use an authenticator app (Aegis on Android, Raivo on iOS) — not SMS.
Single Sign-On (SSO)
When you're running 10+ services, logging into each one separately becomes tedious. SSO solutions provide one login for everything.
| Solution | Protocol | Difficulty | Self-Hosted |
|---|---|---|---|
| Authelia | OIDC, LDAP | Medium | Yes |
| Authentik | OIDC, SAML, LDAP | Medium | Yes |
| Keycloak | OIDC, SAML | Hard | Yes |
Authelia is the most popular choice for self-hosters: lightweight, Docker-friendly, and works with most reverse proxies.
Container Security
- Don't run containers as root — Use
user: 1000:1000in Compose - Read-only filesystems —
read_only: truewhere possible - Drop capabilities —
cap_drop: [ALL]then add back only what's needed - No privileged mode — Never use
privileged: trueunless absolutely necessary - Scan images — Trivy scans Docker images for known vulnerabilities
Monitoring and Alerting
You can't secure what you can't see.
- Uptime Kuma — Monitor that services are responding
- Grafana + Prometheus — System metrics (CPU, RAM, disk, network)
- Crowdsec — Community-driven intrusion detection (like fail2ban but collaborative)
- Ntfy — Self-hosted push notifications for alerts
Regular Maintenance Checklist
- Weekly: Check for container updates, review fail2ban logs
- Monthly: Review firewall rules, check disk space, verify backups
- Quarterly: Rotate secrets/passwords, review access permissions, test disaster recovery
- Annually: Full security audit, replace SSH keys, review network architecture
Product links may include affiliate partnerships — see our affiliate disclosure for details.