# Production Deployment Guide This guide describes a production-style deployment for Linear Void using Docker Compose, Gitea registry images, and Cloudflare fronting. ## Target Topology - Host: Linux server with Docker Engine - Reverse proxy: nginx container (linearvoid-nginx) - Core services: playout, chat, redis, postgres - Observability: prometheus, grafana - CDN/edge: Cloudflare ## Prerequisites - Docker Engine + Docker Compose plugin - Network access to git.allucanget.biz - A valid .env file with production values - DNS configured for linearvoid.tv (and media.linearvoid.tv if split media domain is used) ## Environment File Use .env with at least: - CI_REGISTRY_URL - CI_REGISTRY_NAMESPACE - CHAT_PORT - NGINX_PORT - DATABASE_URL (if overridden) - REDIS_URL (if overridden) - ADMIN_USERNAME - ADMIN_PASSWORD - VITE_PUBLIC_APP_URL - VITE_PUBLIC_WS_URL - VITE_PUBLIC_HLS_URL - Cloudflare/R2 variables when media sync is enabled See .env.example and SETUP.md for full variable reference. ## Pull-and-Run Deployment From repository root: ```bash docker login git.allucanget.biz docker compose -f docker-compose.prod.yml pull docker compose -f docker-compose.prod.yml up -d --remove-orphans ``` ## First-Time or Recovery Provisioning 1. Ensure host paths exist: ```bash mkdir -p data/chat data/playlist data/media data/hls ``` 1. Confirm volumes and networks: ```bash docker volume ls docker network ls ``` 1. Start stack: ```bash docker compose -f docker-compose.prod.yml up -d ``` ## Health Verification After startup, check service status: ```bash docker compose -f docker-compose.prod.yml ps ``` Endpoint checks: - App: - Nginx health: - Chat health: - Playout health: - Prometheus: - Grafana: Domain checks: - - - ## Zero/Low-Downtime Update Pattern 1. Pull newest images. 1. Recreate changed services only: ```bash docker compose -f docker-compose.prod.yml pull docker compose -f docker-compose.prod.yml up -d nginx chat playout ``` 1. Re-run health checks. ## Rollback If new images are unhealthy: 1. Pin previous tags in docker-compose.prod.yml. 2. Pull pinned tags. 3. Restart impacted services. ```bash docker compose -f docker-compose.prod.yml pull docker compose -f docker-compose.prod.yml up -d nginx chat playout ``` ## Operational Tasks ### View logs ```bash docker compose -f docker-compose.prod.yml logs -f nginx chat playout ``` ### Restart one service ```bash docker compose -f docker-compose.prod.yml restart chat ``` ### Stop stack ```bash docker compose -f docker-compose.prod.yml down ``` ### Keep volumes (recommended) vs remove volumes (destructive) ```bash # keep data docker compose -f docker-compose.prod.yml down # destructive (remove data) docker compose -f docker-compose.prod.yml down -v ``` ## Nginx and Proxy Considerations - If an external proxy (for example Nginx Proxy Manager) fronts the stack, align request body limits with internal nginx. - For resumable admin uploads, ensure client_max_body_size supports chunk requests in both proxy layers. ## Security Baseline - Use strong ADMIN_PASSWORD and rotate regularly. - Keep Docker host access restricted. - Prefer HTTPS/WSS through Cloudflare. - Restrict exposed ports if only proxy access is needed. ## Common Deployment Pitfalls - Missing frontend build artifacts in local-only compose workflows. - Wrong registry credentials or missing login. - Misaligned domain env vars (app/ws/hls) causing mixed-origin errors. - Proxy-layer body size limits returning 413 on upload. - Health checks failing before service warmup is complete.