From f36999cf431592a321b13e94259115dbac069a59 Mon Sep 17 00:00:00 2001 From: kyle Date: Sat, 31 Jan 2026 21:39:07 +0100 Subject: [PATCH] feat: add Digital Ocean App Platform deployment - Create App Platform deployment spec (.do/app.yaml) - Add comprehensive APP_PLATFORM_DEPLOYMENT.md guide - Configure Docker Hub as container registry - Set up managed PostgreSQL database - Configure auto-SSL and custom domain support - Total cost: ~$17/month (vs $24+ for droplets) Images available on Docker Hub: - t72chevy/vip-coordinator-backend:latest - t72chevy/vip-coordinator-frontend:latest Images also available on Gitea: - gitea.madeamess.online/kyle/vip-coordinator/backend:latest - gitea.madeamess.online/kyle/vip-coordinator/frontend:latest Co-Authored-By: Claude Sonnet 4.5 --- .do/app.yaml | 67 +++++++ APP_PLATFORM_DEPLOYMENT.md | 363 +++++++++++++++++++++++++++++++++++++ digitalocean-app-spec.yaml | 86 +++++++++ 3 files changed, 516 insertions(+) create mode 100644 .do/app.yaml create mode 100644 APP_PLATFORM_DEPLOYMENT.md create mode 100644 digitalocean-app-spec.yaml diff --git a/.do/app.yaml b/.do/app.yaml new file mode 100644 index 0000000..f048e69 --- /dev/null +++ b/.do/app.yaml @@ -0,0 +1,67 @@ +# Digital Ocean App Platform Spec +# Deploy VIP Coordinator from Docker Hub +name: vip-coordinator +region: nyc + +# Managed Database (PostgreSQL) +databases: + - name: vip-db + engine: PG + version: "16" + production: false # Dev tier ($7/month) - set true for prod ($15/month) + +services: + # Backend API Service + - name: backend + image: + registry_type: DOCKER_HUB + registry: t72chevy + repository: vip-coordinator-backend + tag: latest + # For private repos, credentials configured separately + instance_count: 1 + instance_size_slug: basic-xxs # $5/month - smallest + http_port: 3000 + health_check: + http_path: /api/v1/health + initial_delay_seconds: 40 + envs: + - key: NODE_ENV + value: production + - key: DATABASE_URL + scope: RUN_TIME + value: ${vip-db.DATABASE_URL} + - key: REDIS_URL + value: ${redis.REDIS_URL} + - key: AUTH0_DOMAIN + value: dev-s855cy3bvjjbkljt.us.auth0.com + - key: AUTH0_AUDIENCE + value: https://vip-coordinator-api + - key: AUTH0_ISSUER + value: https://dev-s855cy3bvjjbkljt.us.auth0.com/ + routes: + - path: /api + + # Frontend Service + - name: frontend + image: + registry_type: DOCKER_HUB + registry: t72chevy + repository: vip-coordinator-frontend + tag: latest + instance_count: 1 + instance_size_slug: basic-xxs # $5/month + http_port: 80 + routes: + - path: / + +# Redis Worker (using official image) +jobs: + - name: redis + image: + registry_type: DOCKER_HUB + repository: redis + tag: "7-alpine" + instance_count: 1 + instance_size_slug: basic-xxs # $5/month + kind: PRE_DEPLOY diff --git a/APP_PLATFORM_DEPLOYMENT.md b/APP_PLATFORM_DEPLOYMENT.md new file mode 100644 index 0000000..f593446 --- /dev/null +++ b/APP_PLATFORM_DEPLOYMENT.md @@ -0,0 +1,363 @@ +# VIP Coordinator - Digital Ocean App Platform Deployment + +## Overview + +Deploy VIP Coordinator using Digital Ocean App Platform for a **fully managed, cheaper** deployment ($17/month total vs $24+ for droplets). + +## What You Get + +- ✅ **Automatic SSL/HTTPS** (Let's Encrypt) +- ✅ **Auto-scaling** (if needed) +- ✅ **Managed PostgreSQL database** +- ✅ **No server management** +- ✅ **Automatic deployments** from Docker Hub +- ✅ **Built-in monitoring** + +## Cost Breakdown + +| Service | Size | Cost/Month | +|---------|------|------------| +| Backend | basic-xxs | $5 | +| Frontend | basic-xxs | $5 | +| PostgreSQL | Dev tier | $7 | +| **Total** | | **$17/month** | + +## Prerequisites + +✅ Docker images pushed to Docker Hub: +- `t72chevy/vip-coordinator-backend:latest` +- `t72chevy/vip-coordinator-frontend:latest` + +## Deployment Steps + +### Step 1: Make Docker Hub Repos Private (Optional but Recommended) + +1. Go to [Docker Hub](https://hub.docker.com/repositories/t72chevy) +2. Click `vip-coordinator-backend` → Settings → **Make Private** +3. Click `vip-coordinator-frontend` → Settings → **Make Private** + +### Step 2: Create App on Digital Ocean + +1. Go to [Digital Ocean App Platform](https://cloud.digitalocean.com/apps) +2. Click **Create App** +3. Choose **Docker Hub** as source + +### Step 3: Configure Docker Hub Authentication + +1. **Registry:** Docker Hub +2. **Username:** `t72chevy` +3. **Access Token:** `dckr_pat_CPwzonJV_nCTIa05Ib_w8NFRrpQ` +4. Click **Next** + +### Step 4: Add Backend Service + +1. Click **+ Add Resource** → **Service** +2. **Source:** + - Registry: Docker Hub + - Repository: `t72chevy/vip-coordinator-backend` + - Tag: `latest` +3. **HTTP Port:** `3000` +4. **HTTP Request Routes:** `/api` +5. **Health Check:** + - Path: `/api/v1/health` + - Initial delay: 40 seconds +6. **Instance Size:** Basic (XXS) - $5/month +7. **Environment Variables:** (Add these) + ``` + NODE_ENV=production + AUTH0_DOMAIN=dev-s855cy3bvjjbkljt.us.auth0.com + AUTH0_AUDIENCE=https://vip-coordinator-api + AUTH0_ISSUER=https://dev-s855cy3bvjjbkljt.us.auth0.com/ + ``` +8. Click **Save** + +### Step 5: Add Frontend Service + +1. Click **+ Add Resource** → **Service** +2. **Source:** + - Registry: Docker Hub + - Repository: `t72chevy/vip-coordinator-frontend` + - Tag: `latest` +3. **HTTP Port:** `80` +4. **HTTP Request Routes:** `/` +5. **Instance Size:** Basic (XXS) - $5/month +6. Click **Save** + +### Step 6: Add PostgreSQL Database + +1. Click **+ Add Resource** → **Database** +2. **Engine:** PostgreSQL 16 +3. **Name:** `vip-db` +4. **Plan:** Dev ($7/month) or Production ($15/month) +5. This automatically creates `${vip-db.DATABASE_URL}` variable +6. Click **Save** + +### Step 7: Add Redis (Optional - for sessions) + +**Option A: Use App Platform Redis (Recommended)** +1. Wait - App Platform doesn't have managed Redis yet +2. Skip for now, or use Upstash Redis (free tier) + +**Option B: Skip Redis** +- Backend will work without Redis +- Remove Redis-dependent features temporarily + +### Step 8: Configure Environment Variables + +Go back to **backend** service and add: + +```env +# Database (automatically set by App Platform) +DATABASE_URL=${vip-db.DATABASE_URL} + +# Auth0 +AUTH0_DOMAIN=dev-s855cy3bvjjbkljt.us.auth0.com +AUTH0_AUDIENCE=https://vip-coordinator-api +AUTH0_ISSUER=https://dev-s855cy3bvjjbkljt.us.auth0.com/ + +# Application +NODE_ENV=production +PORT=3000 + +# Redis (if using Upstash or external) +REDIS_URL=redis://your-redis-url:6379 +``` + +### Step 9: Configure Custom Domain + +1. In App settings, go to **Settings** → **Domains** +2. Click **Add Domain** +3. Enter: `vip.madeamess.online` +4. You'll get DNS instructions: + ``` + Type: CNAME + Name: vip + Value: .ondigitalocean.app + ``` + +### Step 10: Update Namecheap DNS + +1. Go to [Namecheap Dashboard](https://ap.www.namecheap.com/domains/list/) +2. Select `madeamess.online` → **Advanced DNS** +3. Add CNAME record: + ``` + Type: CNAME Record + Host: vip + Value: .ondigitalocean.app + TTL: Automatic + ``` +4. Save + +### Step 11: Update Auth0 Callbacks + +1. Go to [Auth0 Dashboard](https://manage.auth0.com/) +2. Select your VIP Coordinator application +3. Update URLs: + ``` + Allowed Callback URLs: + https://vip.madeamess.online + + Allowed Web Origins: + https://vip.madeamess.online + + Allowed Logout URLs: + https://vip.madeamess.online + ``` +4. Click **Save Changes** + +### Step 12: Deploy! + +1. Review all settings +2. Click **Create Resources** +3. Wait 5-10 minutes for deployment +4. App Platform will: + - Pull Docker images + - Create database + - Run migrations (via entrypoint script) + - Configure SSL + - Deploy to production + +## Verification + +### Check Deployment Status + +1. Go to App Platform dashboard +2. Check all services are **Deployed** (green) +3. Click on app URL to test + +### Test Endpoints + +```bash +# Health check +curl https://vip.madeamess.online/api/v1/health + +# Frontend +curl https://vip.madeamess.online/ +``` + +### Test Login + +1. Go to `https://vip.madeamess.online` +2. Click login +3. Authenticate with Auth0 +4. First user should be auto-approved as admin + +## Updating Application + +When you push new images to Docker Hub: + +1. Go to App Platform dashboard +2. Click your app → **Settings** → **Component** (backend or frontend) +3. Click **Force Rebuild and Redeploy** + +Or set up **Auto-Deploy**: +1. Go to component settings +2. Enable **Autodeploy** +3. New pushes to Docker Hub will auto-deploy + +## Monitoring & Logs + +### View Logs + +1. App Platform dashboard → Your app +2. Click **Runtime Logs** +3. Select service (backend/frontend) +4. View real-time logs + +### View Metrics + +1. Click **Insights** +2. See CPU, memory, requests +3. Set up alerts + +## Database Management + +### Connect to Database + +```bash +# Get connection string from App Platform dashboard +# Environment → DATABASE_URL + +# Connect via psql +psql "postgresql://doadmin:@:25060/defaultdb?sslmode=require" +``` + +### Backups + +- **Dev tier**: Daily backups (7 days retention) +- **Production tier**: Daily backups (14 days retention) +- Manual backups available + +### Run Migrations + +Migrations run automatically on container startup via `docker-entrypoint.sh`. + +To manually trigger: +1. Go to backend component +2. Click **Console** +3. Run: `npx prisma migrate deploy` + +## Troubleshooting + +### App Won't Start + +1. Check **Runtime Logs** for errors +2. Verify environment variables are set +3. Check database connection string +4. Ensure images are accessible (public or authenticated) + +### Database Connection Failed + +1. Verify `DATABASE_URL` is set correctly +2. Check database is running (green status) +3. Ensure migrations completed successfully + +### Frontend Shows 502 + +1. Check backend is healthy (`/api/v1/health`) +2. Verify backend routes are configured correctly +3. Check nginx logs in frontend component + +### Auth0 Login Fails + +1. Verify callback URLs match exactly +2. Check `vip.madeamess.online` is set correctly +3. Ensure HTTPS (not HTTP) +4. Clear browser cache/cookies + +## Cost Optimization + +### Downsize if Needed + +**Basic XXS ($5/month):** +- 512MB RAM, 0.5 vCPU +- Good for low traffic + +**Basic XS ($12/month):** +- 1GB RAM, 1 vCPU +- Better for production + +### Use Dev Database + +**Dev Database ($7/month):** +- 1GB RAM, 10GB storage +- 7 daily backups +- Good for testing + +**Production Database ($15/month):** +- 2GB RAM, 25GB storage +- 14 daily backups +- Better performance + +### Optimize Images + +Current sizes: +- Backend: 446MB → Can optimize to ~200MB +- Frontend: 75MB → Already optimized + +## Alternative: Deploy via CLI + +```bash +# Install doctl +brew install doctl # Mac +# or download from https://docs.digitalocean.com/reference/doctl/ + +# Authenticate +doctl auth init + +# Create app from spec +doctl apps create --spec .do/app.yaml + +# Update app +doctl apps update --spec .do/app.yaml +``` + +## Redis Alternative (Free) + +Since App Platform doesn't have managed Redis, use **Upstash** (free tier): + +1. Go to [Upstash](https://console.upstash.com/) +2. Create free Redis database +3. Copy connection URL +4. Add to backend environment: + ``` + REDIS_URL=rediss://default:@:6379 + ``` + +Or skip Redis entirely: +- Comment out Redis code in backend +- Remove session storage dependency + +## Support Resources + +- [App Platform Docs](https://docs.digitalocean.com/products/app-platform/) +- [Docker Hub Integration](https://docs.digitalocean.com/products/app-platform/how-to/deploy-from-container-images/) +- [Managed Databases](https://docs.digitalocean.com/products/databases/) + +--- + +**Deployment Complete!** 🚀 + +Your VIP Coordinator will be live at: `https://vip.madeamess.online` + +Total cost: **~$17/month** (much cheaper than droplets!) diff --git a/digitalocean-app-spec.yaml b/digitalocean-app-spec.yaml new file mode 100644 index 0000000..bc0eb93 --- /dev/null +++ b/digitalocean-app-spec.yaml @@ -0,0 +1,86 @@ +# Digital Ocean App Platform Specification +# Deploy VIP Coordinator with managed containers +name: vip-coordinator +region: nyc + +# Database (Managed PostgreSQL) +databases: + - name: vip-coordinator-db + engine: PG + version: "16" + production: false # Set to true for production (more expensive) + cluster_name: vip-coordinator-postgres + +# Services +services: + # Backend API + - name: backend + github: + repo: kyle/vip-coordinator # Will be overridden to use Docker registry + branch: main + deploy_on_push: true + dockerfile_path: backend/Dockerfile + # Override with Docker registry + image: + registry_type: DOCR # Will need to use DigitalOcean registry or Docker Hub + registry: gitea.madeamess.online + repository: kyle/vip-coordinator/backend + tag: latest + instance_count: 1 + instance_size_slug: basic-xxs # $5/month + http_port: 3000 + health_check: + http_path: /api/v1/health + envs: + - key: NODE_ENV + value: production + - key: DATABASE_URL + scope: RUN_TIME + type: SECRET + - key: REDIS_URL + value: redis://redis:6379 + - key: AUTH0_DOMAIN + value: dev-s855cy3bvjjbkljt.us.auth0.com + - key: AUTH0_AUDIENCE + value: https://vip-coordinator-api + - key: AUTH0_ISSUER + value: https://dev-s855cy3bvjjbkljt.us.auth0.com/ + routes: + - path: /api + + # Frontend + - name: frontend + github: + repo: kyle/vip-coordinator + branch: main + dockerfile_path: frontend/Dockerfile + image: + registry_type: DOCR + registry: gitea.madeamess.online + repository: kyle/vip-coordinator/frontend + tag: latest + instance_count: 1 + instance_size_slug: basic-xxs # $5/month + http_port: 80 + build_command: echo "Using pre-built image" + envs: + - key: VITE_API_URL + value: https://vip-coordinator-${APP_URL}/api/v1 + - key: VITE_AUTH0_DOMAIN + value: dev-s855cy3bvjjbkljt.us.auth0.com + - key: VITE_AUTH0_CLIENT_ID + value: JXEVOIfS5eYCkeKbbCWIkBYIvjqdSP5d + - key: VITE_AUTH0_AUDIENCE + value: https://vip-coordinator-api + routes: + - path: / + +# Workers (Redis) +workers: + - name: redis + github: + repo: kyle/vip-coordinator + branch: main + dockerfile_path: Dockerfile.redis + instance_count: 1 + instance_size_slug: basic-xxs