From 3dad6204e61bac2f512f97ecc9111f666f720598 Mon Sep 17 00:00:00 2001 From: Cal Corum Date: Thu, 15 Jan 2026 09:51:41 -0600 Subject: [PATCH] CLAUDE: Add production deployment documentation for Linode VPS Documents deployment strategy using Docker Compose on existing Linode infrastructure. Includes architecture diagram, step-by-step deployment guide, NPM configuration, maintenance commands, and rollback procedures. Co-Authored-By: Claude Opus 4.5 --- DEPLOYMENT.md | 294 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 294 insertions(+) create mode 100644 DEPLOYMENT.md diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md new file mode 100644 index 0000000..f52cc9b --- /dev/null +++ b/DEPLOYMENT.md @@ -0,0 +1,294 @@ +# Production Deployment Guide + +## Target Environment + +**Server**: Linode VPS (ssh akamai) +- Ubuntu 24.04 LTS +- 8GB RAM / 160GB disk +- Docker + Nginx Proxy Manager pre-configured + +**Domain**: `gameplay.sba.manticorum.com` (or similar) + +## Architecture + +``` +┌─────────────────────────────────────────────────────┐ +│ Linode VPS │ +├─────────────────────────────────────────────────────┤ +│ Nginx Proxy Manager (:80/:443) │ +│ └─ gameplay.sba.manticorum.com │ +│ ├─ /api/* → backend:8000 │ +│ ├─ /socket.io/* → backend:8000 (WebSocket) │ +│ └─ /* → frontend:3000 │ +├─────────────────────────────────────────────────────┤ +│ strat-gameplay-webapp │ +│ ├─ backend (FastAPI + Socket.io) :8000 │ +│ └─ frontend-sba (Nuxt 3 SSR) :3000 │ +├─────────────────────────────────────────────────────┤ +│ Shared Services (existing) │ +│ ├─ sba_postgres :5432 (database: sba_gameplay) │ +│ └─ sba_redis :6379 │ +└─────────────────────────────────────────────────────┘ +``` + +## Why Docker Compose? + +Evaluated options for this deployment: + +| Option | Verdict | Reason | +|--------|---------|--------| +| **Docker Compose** | ✅ Selected | Existing infra, compose files ready, NPM network integration | +| Bare metal (systemd) | ❌ | No isolation, manual dependency management, harder rollbacks | +| Docker Swarm | ❌ | Overkill for single node | +| Kubernetes/K3s | ❌ | Significant complexity for minimal benefit at this scale | + +## Pre-Deployment Checklist + +### 1. Discord OAuth Setup +- [ ] Add redirect URI in [Discord Developer Portal](https://discord.com/developers/applications): + - `https://gameplay.sba.manticorum.com/api/auth/discord/callback/server` + +### 2. Database Setup +```bash +# SSH to server +ssh akamai + +# Create database +docker exec -it sba_postgres psql -U sba -c "CREATE DATABASE sba_gameplay;" +``` + +### 3. DNS Configuration +- [ ] Add A record: `gameplay.sba.manticorum.com` → Linode IP + +## Deployment Steps + +### Step 1: Prepare Server Directory + +```bash +ssh akamai +mkdir -p ~/container-data/strat-gameplay-webapp +cd ~/container-data/strat-gameplay-webapp +``` + +### Step 2: Clone Repository + +```bash +git clone https://github.com/calcorum/strat-gameplay-webapp.git . +# Or use deploy key for private repo +``` + +### Step 3: Create Production Environment Files + +**Backend** (`backend/.env`): +```bash +# Database - use existing SBA postgres +DATABASE_URL=postgresql+asyncpg://sba:PASSWORD@sba_postgres:5432/sba_gameplay + +# Security +SECRET_KEY=generate-a-secure-64-char-key-here + +# Discord OAuth +DISCORD_CLIENT_ID=your-client-id +DISCORD_CLIENT_SECRET=your-client-secret +DISCORD_SERVER_REDIRECT_URI=https://gameplay.sba.manticorum.com/api/auth/discord/callback/server +FRONTEND_URL=https://gameplay.sba.manticorum.com + +# CORS +CORS_ORIGINS=["https://gameplay.sba.manticorum.com"] + +# Redis - use existing SBA redis +REDIS_URL=redis://sba_redis:6379 + +# League APIs +SBA_API_URL=https://api.sba.manticorum.com +SBA_API_KEY=your-sba-api-key + +# Access Control (empty = all users, or comma-separated Discord IDs) +ALLOWED_DISCORD_IDS= +``` + +**Frontend** (`frontend-sba/.env`): +```bash +# API URLs (same domain, proxied by NPM) +NUXT_PUBLIC_API_URL=https://gameplay.sba.manticorum.com +NUXT_PUBLIC_WS_URL=https://gameplay.sba.manticorum.com + +# Discord OAuth +NUXT_PUBLIC_DISCORD_CLIENT_ID=your-client-id +NUXT_PUBLIC_DISCORD_REDIRECT_URI=https://gameplay.sba.manticorum.com/auth/callback + +# Internal API URL for SSR (Docker network) +NUXT_API_URL_INTERNAL=http://backend:8000 +``` + +### Step 4: Create Production Docker Compose Override + +Create `docker-compose.production.yml`: +```yaml +# Production overrides for Linode deployment +# Usage: docker compose -f docker-compose.yml -f docker-compose.production.yml up -d + +services: + backend: + build: + context: ./backend + target: production + environment: + - APP_ENV=production + - DEBUG=false + networks: + - sba-database_default + - nginx-proxy-manager_npm_network + restart: always + # Don't expose port externally - NPM handles routing + ports: !reset [] + expose: + - "8000" + + frontend-sba: + build: + context: ./frontend-sba + target: production + environment: + - NODE_ENV=production + networks: + - nginx-proxy-manager_npm_network + restart: always + ports: !reset [] + expose: + - "3000" + depends_on: + - backend + + # Don't need local redis - use existing sba_redis + redis: + profiles: + - disabled + +networks: + sba-database_default: + external: true + nginx-proxy-manager_npm_network: + external: true +``` + +### Step 5: Run Database Migrations + +```bash +# Build backend first +docker compose -f docker-compose.yml -f docker-compose.production.yml build backend + +# Run migrations +docker compose -f docker-compose.yml -f docker-compose.production.yml run --rm backend \ + alembic upgrade head +``` + +### Step 6: Start Services + +```bash +docker compose -f docker-compose.yml -f docker-compose.production.yml up -d +``` + +### Step 7: Configure Nginx Proxy Manager + +Access NPM at `http://LINODE_IP:81` and create proxy host: + +**Proxy Host Settings**: +- Domain: `gameplay.sba.manticorum.com` +- Scheme: `http` +- Forward Hostname: `strat-gameplay-webapp-frontend-sba-1` +- Forward Port: `3000` +- Websockets Support: ✅ Enabled +- SSL: Request new Let's Encrypt certificate + +**Custom Locations** (for API routing): +| Location | Scheme | Forward Host | Port | +|----------|--------|--------------|------| +| `/api` | http | strat-gameplay-webapp-backend-1 | 8000 | +| `/socket.io` | http | strat-gameplay-webapp-backend-1 | 8000 | + +### Step 8: Verify Deployment + +```bash +# Health check +curl https://gameplay.sba.manticorum.com/api/health + +# Check logs +docker compose -f docker-compose.yml -f docker-compose.production.yml logs -f +``` + +## Maintenance Commands + +```bash +cd ~/container-data/strat-gameplay-webapp + +# View logs +docker compose -f docker-compose.yml -f docker-compose.production.yml logs -f backend +docker compose -f docker-compose.yml -f docker-compose.production.yml logs -f frontend-sba + +# Restart services +docker compose -f docker-compose.yml -f docker-compose.production.yml restart + +# Pull updates and redeploy +git pull +docker compose -f docker-compose.yml -f docker-compose.production.yml build +docker compose -f docker-compose.yml -f docker-compose.production.yml up -d + +# Run migrations after update +docker compose -f docker-compose.yml -f docker-compose.production.yml run --rm backend \ + alembic upgrade head +``` + +## Rollback Procedure + +```bash +# Check previous commits +git log --oneline -10 + +# Rollback to specific commit +git checkout + +# Rebuild and restart +docker compose -f docker-compose.yml -f docker-compose.production.yml build +docker compose -f docker-compose.yml -f docker-compose.production.yml up -d +``` + +## Monitoring + +### Health Endpoints +- Backend: `https://gameplay.sba.manticorum.com/api/health` +- Frontend: `https://gameplay.sba.manticorum.com` (200 OK) + +### Log Locations +```bash +# Container logs +docker logs strat-gameplay-webapp-backend-1 + +# Application logs (if volume mounted) +~/container-data/strat-gameplay-webapp/backend/logs/ +``` + +## Resource Estimates + +| Service | RAM | CPU | Notes | +|---------|-----|-----|-------| +| Backend | ~200MB | Low | Increases with concurrent games | +| Frontend | ~150MB | Low | Nuxt SSR | +| **Total** | ~350MB | Low | Well within 5.8GB available | + +## Security Considerations + +- [ ] Use strong `SECRET_KEY` (64+ characters) +- [ ] Restrict `ALLOWED_DISCORD_IDS` for beta testing +- [ ] SSL enforced via NPM +- [ ] Database credentials not exposed externally +- [ ] Redis not exposed externally (Docker network only) + +## Future Scaling Options + +If load increases beyond single-server capacity: + +1. **Vertical**: Upgrade Linode plan (easy, immediate) +2. **Database**: Migrate to managed PostgreSQL (Linode, Neon, Supabase) +3. **Horizontal**: Add second app server behind load balancer +4. **CDN**: Cloudflare for static assets and DDoS protection \ No newline at end of file