14 KiB
14 KiB
🔐 Security Guide
Overview
This guide covers security best practices for the homelab, including authentication, network security, secrets management, and incident response.
🏰 Security Architecture
┌─────────────────────────────────────────────────────────────────────────────┐
│ SECURITY LAYERS │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ EXTERNAL │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Cloudflare WAF + DDoS Protection + Bot Management │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ GATEWAY ▼ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Nginx Proxy Manager (SSL Termination + Rate Limiting) │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ AUTHENTICATION ▼ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Authentik SSO (OAuth2/OIDC + MFA + User Management) │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ NETWORK ▼ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Tailscale (Zero-Trust Mesh VPN) + Wireguard (Site-to-Site) │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ APPLICATION ▼ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Vaultwarden (Secrets) + Container Isolation + Least Privilege │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
🔑 Authentication & Access Control
Authentik SSO
All services use centralized authentication through Authentik:
# Services integrated with Authentik SSO:
- Grafana (OAuth2)
- Portainer (OAuth2)
- Proxmox (LDAP)
- Mattermost (OAuth2)
- Seafile (OAuth2)
- Paperless-NGX (OAuth2)
- Various internal apps (Forward Auth)
Multi-Factor Authentication (MFA)
| Service | MFA Type | Status |
|---|---|---|
| Authentik | TOTP + WebAuthn | ✅ Required |
| Vaultwarden | TOTP + FIDO2 | ✅ Required |
| Synology DSM | TOTP | ✅ Required |
| Proxmox | TOTP | ✅ Required |
| Tailscale | Google SSO | ✅ Required |
Access Levels
# Role-Based Access Control
roles:
admin:
description: Full access to all systems
access:
- All Portainer environments
- Authentik admin
- DSM admin
- Proxmox root
operator:
description: Day-to-day operations
access:
- Container management
- Service restarts
- Log viewing
viewer:
description: Read-only monitoring
access:
- Grafana dashboards
- Uptime Kuma status
- Read-only Portainer
family:
description: Consumer access only
access:
- Plex/Jellyfin streaming
- Photo viewing
- Limited file access
🌐 Network Security
Firewall Rules
# Synology Firewall - Recommended rules
# Control Panel > Security > Firewall
# Allow Tailscale
Allow: 100.64.0.0/10 (Tailscale CGNAT)
# Allow local network
Allow: 192.168.0.0/16 (RFC1918)
Allow: 10.0.0.0/8 (RFC1918)
# Block everything else by default
Deny: All
# Specific port rules
Allow: TCP 443 from Cloudflare IPs only
Allow: TCP 80 from Cloudflare IPs only (redirect to 443)
Cloudflare Configuration
# Cloudflare Security Settings
ssl_mode: full_strict # End-to-end encryption
min_tls_version: "1.2"
always_use_https: true
# WAF Rules
waf_enabled: true
bot_management: enabled
ddos_protection: automatic
# Rate Limiting
rate_limit:
requests_per_minute: 100
action: challenge
# Access Rules
ip_access_rules:
- action: block
filter: known_bots
- action: challenge
filter: threat_score > 10
Port Exposure
# Only these ports exposed to internet (via Cloudflare)
exposed_ports:
- 443/tcp # HTTPS (Nginx Proxy Manager)
# Everything else via Tailscale/VPN only
internal_only:
- 22/tcp # SSH
- 8080/tcp # Portainer
- 9090/tcp # Prometheus
- 3000/tcp # Grafana
- All Docker services
🔒 Secrets Management
Vaultwarden
Central password manager for all credentials:
# Vaultwarden Security Settings
vaultwarden:
admin_token: # Argon2 hashed
signups_allowed: false
invitations_allowed: true
# Password policy
password_hints_allowed: false
password_iterations: 600000 # PBKDF2 iterations
# 2FA enforcement
require_device_email: true
# Session security
login_ratelimit_seconds: 60
login_ratelimit_max_burst: 10
Environment Variables
# Never store secrets in docker-compose.yml
# Use Docker secrets or environment files
# Bad ❌
environment:
- DB_PASSWORD="REDACTED_PASSWORD"
# Good ✅ - Using .env file
environment:
- DB_PASSWORD="REDACTED_PASSWORD"
# Better ✅ - Using Docker secrets
secrets:
- db_password
Secret Rotation
# Secret rotation schedule
rotation_schedule:
api_tokens: 90 days
oauth_secrets: 180 days
database_passwords: 365 days
ssl_certificates: auto (Let's Encrypt)
ssh_keys: on compromise only
🐳 Container Security
Docker Security Practices
# docker-compose.yml security settings
services:
myservice:
# Run as non-root
user: "1000:1000"
# Read-only root filesystem
read_only: true
# Disable privilege escalation
security_opt:
- no-new-privileges:true
# Limit capabilities
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE # Only if needed
# Resource limits
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
Container Scanning
# Scan images for vulnerabilities
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy image myimage:latest
# Scan all running containers
for img in $(docker ps --format '{{.Image}}' | sort -u); do
echo "Scanning: $img"
docker run --rm aquasec/trivy image "$img" --severity HIGH,CRITICAL
done
Image Security
# Only use trusted image sources
trusted_registries:
- docker.io/library/ # Official images
- ghcr.io/ # GitHub Container Registry
- lscr.io/linuxserver/ # LinuxServer.io
# Always pin versions
# Bad ❌
image: nginx:latest
# Good ✅
image: nginx:1.25.3-alpine
🛡️ Backup Security
Encrypted Backups
# Hyper Backup encryption settings
encryption:
enabled: true
type: client-side # Encrypt before transfer
algorithm: AES-256-CBC
key_storage: local # Never store key on backup destination
# Verify encryption
# Check that backup files are not readable without key
file backup.hbk
# Should show: "data" not "text" or recognizable format
Backup Access Control
# Separate credentials for backup systems
backup_credentials:
hyper_backup:
read_only: true # Cannot delete backups
separate_user: backup_user
syncthing:
ignore_delete: true # Prevent sync of deletions
offsite:
encryption_key: stored_offline
access: write_only # Cannot read existing backups
📊 Security Monitoring
Log Aggregation
# Critical logs to monitor
security_logs:
- /var/log/auth.log # Authentication attempts
- /var/log/nginx/access.log # Web access
- Authentik audit logs # SSO events
- Docker container logs # Application events
Alerting Rules
# prometheus/rules/security.yml
groups:
- name: security
rules:
- alert: REDACTED_APP_PASSWORD
expr: increase(authentik_login_failures_total[1h]) > 10
labels:
severity: warning
annotations:
summary: "High number of failed login attempts"
- alert: SSHBruteForce
expr: increase(sshd_auth_failures_total[5m]) > 5
labels:
severity: critical
annotations:
summary: "Possible SSH brute force attack"
- alert: UnauthorizedContainerStart
expr: changes(container_start_time_seconds[1h]) > 0
labels:
severity: info
annotations:
summary: "New container started"
Security Dashboard
Key metrics to display in Grafana:
- Failed authentication attempts
- Active user sessions
- SSL certificate expiry
- Firewall blocked connections
- Container privilege changes
- Unusual network traffic patterns
🚨 Incident Response
Response Procedure
1. DETECT
└─► Alerts from monitoring
└─► User reports
└─► Anomaly detection
2. CONTAIN
└─► Isolate affected systems
└─► Block malicious IPs
└─► Disable compromised accounts
3. INVESTIGATE
└─► Review logs
└─► Identify attack vector
└─► Assess data exposure
4. REMEDIATE
└─► Patch vulnerabilities
└─► Rotate credentials
└─► Restore from backup if needed
5. RECOVER
└─► Restore services
└─► Verify integrity
└─► Monitor for recurrence
6. DOCUMENT
└─► Incident report
└─► Update procedures
└─► Implement improvements
Emergency Contacts
# Store securely in Vaultwarden
emergency_contacts:
- ISP support
- Domain registrar
- Cloudflare support
- Family members with access
Quick Lockdown Commands
# Block all external access immediately
# On Synology:
sudo iptables -I INPUT -j DROP
sudo iptables -I INPUT -s 100.64.0.0/10 -j ACCEPT # Keep Tailscale
# Stop all non-essential containers
docker stop $(docker ps -q --filter "name!=essential-service")
# Force logout all Authentik sessions
docker exec authentik-server ak invalidate_sessions --all
📋 Security Checklist
Weekly
- Review failed login attempts
- Check for container updates
- Verify backup integrity
- Review Cloudflare analytics
Monthly
- Rotate API tokens
- Review user access
- Run vulnerability scans
- Test backup restoration
- Update SSL certificates (if manual)
Quarterly
- Full security audit
- Review firewall rules
- Update incident response plan
- Test disaster recovery
- Review third-party integrations