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 <noreply@anthropic.com>
This commit is contained in:
2026-01-31 21:39:07 +01:00
parent e9de71ce29
commit f36999cf43
3 changed files with 516 additions and 0 deletions

67
.do/app.yaml Normal file
View File

@@ -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

363
APP_PLATFORM_DEPLOYMENT.md Normal file
View File

@@ -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: <app-name>.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: <your-app>.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:<password>@<host>: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 <app-id> --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:<password>@<host>: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!)

View File

@@ -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