adze.uk — The Digital Toolshed

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

  1. Generate an SSH key pair on your local machine:
ssh-keygen -t ed25519 -C "your-identifier"
  1. Copy the public key to your server:
ssh-copy-id user@server-ip
  1. Disable password authentication in /etc/ssh/sshd_config:
PasswordAuthentication no
PubkeyAuthentication yes
PermitRootLogin no
MaxAuthTries 3
  1. Restart SSH:
sudo systemctl restart sshd

Change the Default Port

Moving SSH from port 22 reduces automated scanning noise by 90%+:

# /etc/ssh/sshd_config
Port 2222

This 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 fail2ban

Create /etc/fail2ban/jail.local:

[sshd]
enabled = true
port = 2222
maxretry = 3
findtime = 600
bantime = 3600

This 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.com

Certificates auto-renew. Check with:

sudo certbot renew --dry-run

Internal 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 enable

Principle 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.env files 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.

SolutionProtocolDifficultySelf-Hosted
AutheliaOIDC, LDAPMediumYes
AuthentikOIDC, SAML, LDAPMediumYes
KeycloakOIDC, SAMLHardYes

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:1000 in Compose
  • Read-only filesystemsread_only: true where possible
  • Drop capabilitiescap_drop: [ALL] then add back only what's needed
  • No privileged mode — Never use privileged: true unless 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.