# Banatie Production Deployment Plan ## Architecture ### Isolated Banatie Stack (5 containers): ``` banatie-landing - Landing Page (node:20-alpine) banatie-api - API Service (node:20-alpine) banatie-postgres - PostgreSQL 15 (isolated from VPS PostgreSQL) banatie-minio - MinIO storage (SNMD mode) banatie-minio-init - Initialization (one-shot) ``` ### Domains: ``` banatie.app → banatie-landing:3000 api.banatie.app → banatie-api:3000 storage.banatie.app → banatie-minio:9001 (MinIO Console) ``` ### File Structure: ``` ~/workspace/projects/banatie-service/ # Git repository (code + config) ├── apps/ │ ├── api-service/Dockerfile │ └── landing/Dockerfile ├── packages/database/ └── prod-env/ ├── docker-compose.yml # Production compose (run from here!) ├── .env # Config without secrets (in git) └── secrets.env # Secrets (NOT in git) /opt/services/data/banatie/ # Runtime data only ├── postgres/ # PostgreSQL data ├── storage/drive{1-4}/ # MinIO SNMD ├── logs/ # API logs ├── results/ # Generated images └── uploads/ # Uploaded files ``` --- ## Docker Images | Container | Image | Internal Port | |-----------|-------|---------------| | banatie-landing | Built from apps/landing/Dockerfile | 3000 | | banatie-api | Built from apps/api-service/Dockerfile | 3000 | | banatie-postgres | postgres:15-alpine | 5432 | | banatie-minio | quay.io/minio/minio:latest | 9000 (API), 9001 (Console) | --- ## Deployment Steps ### Step 1: Prepare VPS Directories ```bash # Create runtime data directory sudo mkdir -p /opt/services/data/banatie/{postgres,logs,results,uploads} sudo mkdir -p /opt/services/data/banatie/storage/drive{1,2,3,4} sudo chown -R $USER:$USER /opt/services/data/banatie ``` ### Step 2: Configure Repository ```bash cd ~/workspace/projects/banatie-service # Create secrets.env (not in git) cp prod-env/secrets.env.example prod-env/secrets.env nano prod-env/secrets.env # Fill in: GEMINI_API_KEY, etc. ``` ### Step 3: Configure Caddy Add to `/opt/services/configs/caddy/Caddyfile`: ```caddy banatie.app, www.banatie.app { reverse_proxy banatie-landing:3000 encode gzip header { Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" X-Content-Type-Options "nosniff" X-Frame-Options "DENY" } } api.banatie.app { reverse_proxy banatie-api:3000 encode gzip header { Strict-Transport-Security "max-age=31536000" X-Content-Type-Options "nosniff" } } storage.banatie.app { reverse_proxy banatie-minio:9001 header { Strict-Transport-Security "max-age=31536000" } } ``` ### Step 4: First Launch ```bash cd ~/workspace/projects/banatie-service/prod-env # Start stack docker compose up -d # Check status docker compose ps # View logs docker compose logs -f # Restart Caddy to apply config docker restart caddy # Create master key curl -X POST https://api.banatie.app/api/bootstrap/initial-key ``` --- ## Update Process ### Update Landing: ```bash cd ~/workspace/projects/banatie-service git pull origin main cd prod-env docker compose up -d --build banatie-landing ``` ### Update API: ```bash cd ~/workspace/projects/banatie-service git pull origin main cd prod-env docker compose up -d --build banatie-api ``` ### Update Both: ```bash git pull origin main cd prod-env docker compose up -d --build banatie-landing banatie-api ``` ### Full Restart: ```bash cd ~/workspace/projects/banatie-service/prod-env docker compose down docker compose up -d --build ``` **Downtime:** ~2-3 minutes for image build --- ## DNS Records (add in GoDaddy) | Record | Type | Value | |--------|------|-------| | banatie.app | A | 62.146.239.118 | | www | CNAME | banatie.app | | api | A | 62.146.239.118 | | storage | A | 62.146.239.118 | --- ## Migration from Static Landing After successful Docker deployment: 1. Remove `/var/www/banatie.app/` (old static files) 2. Replace banatie.app section in Caddyfile (static → reverse_proxy) 3. `docker restart caddy` --- ## Network Architecture ### Internal Network (banatie-internal) - All containers communicate internally - No external port exposure - PostgreSQL and MinIO API only accessible internally ### External Network (proxy-network) - Shared with Caddy reverse proxy - Landing, API, and MinIO Console exposed to Caddy - SSL termination at Caddy --- ## Security Notes 1. **No exposed ports** - All traffic goes through Caddy with SSL 2. **Isolated PostgreSQL** - Separate from VPS main database 3. **Secrets management** - `secrets.env` not tracked in git 4. **MinIO SNMD mode** - Erasure coding for data protection --- ## Troubleshooting ### Check container status: ```bash cd ~/workspace/projects/banatie-service/prod-env docker compose ps docker compose logs banatie-api docker compose logs banatie-landing ``` ### Restart specific service: ```bash docker compose restart banatie-api ``` ### Full rebuild: ```bash docker compose down docker compose build --no-cache docker compose up -d ``` ### Check Caddy logs: ```bash docker logs caddy ```