- Created README.md in docs folder outlining project structure and documentation links. - Added SECURITY.md detailing the security model, threat model, authentication, transport security, network isolation, and incident response procedures. - Introduced SETUP.md providing a detailed setup guide for local and production environments, including prerequisites, environment setup, and Gitea integration. - Added STREAMING.md outlining the streaming pipeline, including production flow, source-media contract, playout and HLS packaging, cache contract, player behavior, and monitoring. - Updated architecture documentation to include links to new SETUP.md and STREAMING.md files for better navigation.
4.0 KiB
4.0 KiB
Security Guide
Layered security model for Linear Void.
Threat Model
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ Client │───▶│Cloudflare│───▶│ nginx │───▶│ Backend │
│ (public) │ │ WAF+CDN │ │ proxy │ │ chat │
└──────────┘ └──────────┘ └────┬─────┘ └────┬─────┘
│ │
┌──────┴──────┐ ┌─────┴──────┐
│ /health │ │ /api/admin │
│ /metrics │ │ /ws (chat) │
│ /hls/* │ │ /api/chat/* │
│ (public) │ │ (auth req) │
└─────────────┘ └────────────┘
Authentication & Sessions
- Login:
POST /api/admin/login→ cookielinearvoid_admin_session - Cookie flags:
HttpOnly,SameSite=Strict,Secure(over HTTPS) - Server-side expiry via
ADMIN_SESSION_TTL_HOURS - Rate limit: 5 attempts/IP/5min via Redis
Transport Security (TLS/HSTS)
- Cloudflare TLS mode: Full (strict) — valid origin cert required
- nginx listens on 80 internally; Cloudflare handles TLS termination
- HSTS header set by Cloudflare:
max-age=31536000; includeSubDomains; preload - WSS upgrade path:
/wsthrough nginx → chat:3000
Network Isolation
- All backend services on internal Docker network (
linearvoid-net) - Only nginx port exposed to host (443/80)
- Database, Redis, exporters inaccessible from outside
docker-compose.prod.ymlkeeps ports internal viaexpose:notports:
Reverse Proxy Controls
auth_request /api/admin/authgate on all/adminand/api/adminpaths- Explicit
client_max_body_size 64mfor resumable upload chunks - WebSocket upgrade headers:
Upgrade,Connectionpreserved - CORS headers on HLS:
Access-Control-Allow-Origin * - XSS protection: CSP headers served by Cloudflare
Rate Limiting
| Resource | Limit | Window |
|---|---|---|
| WebSocket connect | 5/IP | 60s |
| Chat messages | 10/IP | 10s |
| Admin login | 5/IP | 5min |
Implemented via Redis INCR + EXPIRE.
Secrets Management
.env— local dev only, gitignored- Gitea Actions secrets (
CI_*prefix) for CI/CD - Never commit: passwords, tokens, API keys, R2 credentials
- Production
.envprovisioned manually on host, never checked in - Rotate admin password quarterly
Data Protection
- PostgreSQL: chat history, moderation logs, media metadata
- Redis: append-only persistence for presence, rate limits, sessions
- HLS segments: ephemeral, regenerated by playout
- Backups:
scripts/backup-db.sh(daily),scripts/backup-weekly.sh,scripts/verify-backups.sh
Hardening Checklist
- HTTPS/WSS enforced end-to-end (Cloudflare Full strict)
- Strong admin credentials configured
- Secrets only in env/secrets stores (never committed)
- Proxy auth and websocket headers validated
- Upload limits and MIME validation active
- Rate limiting active (WS, messages, login)
- Cloudflare WAF/rate-limit rules active
- Backup/restore drills completed
- Security alerts routed (Prometheus alertmanager)
Incident Response
- Detect — alerts (ChatDown, RedisDown, HighChatLatency) or user reports
- Triage — edge (Cloudflare), proxy (nginx), app (chat/playout), data (Redis/Postgres)
- Contain — rate limit, credential rotate, service restart, slate mode activation
- Recover — verify health endpoints, check Prometheus targets, validate HLS output
- Record — timeline + corrective actions in
docs/incident-runbook.md