486 lines
14 KiB
Markdown
486 lines
14 KiB
Markdown
# 🔐 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:
|
|
|
|
```yaml
|
|
# 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
|
|
|
|
```yaml
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```yaml
|
|
# 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
|
|
|
|
```yaml
|
|
# 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:
|
|
|
|
```yaml
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```yaml
|
|
# 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
|
|
|
|
```yaml
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```yaml
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```yaml
|
|
# 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
|
|
|
|
```yaml
|
|
# 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
|
|
|
|
```yaml
|
|
# 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
|
|
|
|
```yaml
|
|
# Store securely in Vaultwarden
|
|
emergency_contacts:
|
|
- ISP support
|
|
- Domain registrar
|
|
- Cloudflare support
|
|
- Family members with access
|
|
```
|
|
|
|
### Quick Lockdown Commands
|
|
|
|
```bash
|
|
# 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
|
|
|
|
---
|
|
|
|
## 🔗 Related Documentation
|
|
|
|
- [Authentik SSO Setup](../infrastructure/authentik-sso.md)
|
|
- [Cloudflare Configuration](../infrastructure/cloudflare-dns.md)
|
|
- [Backup Strategies](backup-strategies.md)
|
|
- [Disaster Recovery](../troubleshooting/disaster-recovery.md)
|
|
- [Tailscale Setup](../infrastructure/tailscale-setup-guide.md)
|