trails/docs/server-hardening.md
Ullrich Schäfer be3e69c10b
Security hardening: headers, scanning, Docker, firewall
- Caddy: HSTS, CSP, X-Frame-Options, nosniff, Referrer-Policy,
  Permissions-Policy on all responses
- Caddy: Block scanner paths (.env, .git, wp-config, etc.) with 403
- CI: Gitleaks secret scanning + pnpm audit for vulnerabilities
- Dependabot: Weekly npm + GitHub Actions + monthly Docker updates
- Docker: Non-root user in journal, planner, and brouter containers
- Server: UFW firewall (22/80/443 only) + fail2ban (8 IPs already banned)
- SECURITY.md: Vulnerability disclosure policy
- Privacy page: Security practices section added

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 09:58:12 +01:00

53 lines
968 B
Markdown

# Server Hardening
Steps to harden the Hetzner CX21 production server.
## UFW Firewall
```bash
# Install and enable
apt install -y ufw
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp # SSH
ufw allow 80/tcp # HTTP (Caddy redirect)
ufw allow 443/tcp # HTTPS
ufw enable
ufw status
```
## Fail2ban (SSH protection)
```bash
# Install
apt install -y fail2ban
# Create config
cat > /etc/fail2ban/jail.local << 'EOF'
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 5
bantime = 3600
findtime = 600
EOF
# Start
systemctl enable fail2ban
systemctl start fail2ban
# Check status
fail2ban-client status sshd
```
## SSH Hardening
Already in place:
- Key-based auth only (password auth disabled by Hetzner cloud-init)
- Root login via SSH key only
Optional improvements:
- Change SSH port (security through obscurity, mild benefit)
- Add `AllowUsers root` to `/etc/ssh/sshd_config` to restrict SSH users