Deployment
Overview
| Platform | Best For | Scaling | Cost |
|---|---|---|---|
| Cloudflare Workers | Global edge, high traffic | Automatic | Free tier + pay-per-request |
| Docker | Self-hosted, private infra | Manual | Server cost |
| Bun/VPS | Full server control | Manual | Server cost |
Prerequisites
- Production Google Cloud credentials (setup guide)
- Production Google Sheet shared with the service account
Cloudflare Workers (Recommended)
Your API runs in 300+ edge locations worldwide with zero cold starts and automatic HTTPS.
One-Click Deploy
Click the deploy button on the GitHub README to:
- Fork the repository to your GitHub account
- Connect it to Cloudflare Workers Builds
- Deploy the worker to Cloudflare's edge network
After deploying, set secrets in the Cloudflare dashboard (Workers & Pages > your worker > Settings > Variables and Secrets):
GOOGLE_SHEET_ID- Your Google Sheet IDGOOGLE_CREDENTIALS_EMAIL- Service account emailGOOGLE_PRIVATE_KEY- Service account private keyCLOUDFLARE_TURNSTILE_SECRET_KEY- (optional) Turnstile secret key
Manual Deploy
bun install
bunx wrangler loginSet production secrets (you'll be prompted for each value):
bun run workers:secret GOOGLE_SHEET_ID
bun run workers:secret GOOGLE_CREDENTIALS_EMAIL
bun run workers:secret GOOGLE_PRIVATE_KEY
# Optional
bun run workers:secret CLOUDFLARE_TURNSTILE_SECRET_KEY
bun run workers:secret CLOUDFLARE_TURNSTILE_SITE_KEY
bun run workers:secret ALLOWED_ORIGINSDeploy:
bun run deploy:workersYour Worker is live at https://subs-api.YOUR_SUBDOMAIN.workers.dev.
Local Workers Development
cp .env.example .dev.vars
# Edit .dev.vars with your credentials
bun run dev:workers
# http://localhost:8787Custom Domain
- Go to Cloudflare Dashboard > Workers & Pages > Your Worker > Triggers > Custom Domains
- Click "Add Custom Domain" and enter your domain (e.g.,
api.yourdomain.com) - DNS and SSL are configured automatically
Update CORS to match:
bun run workers:secret ALLOWED_ORIGINS
# Enter: https://yourdomain.com,https://www.yourdomain.comMonitoring
# Real-time logs
bun run workers:tail
# Filter by status or method
bun run workers:tail --status 500
bun run workers:tail --method POST
# List deployments
bunx wrangler deployments list
# Rollback
bunx wrangler rollbackAnalytics are available in the Cloudflare Dashboard under Workers & Pages > Your Worker > Metrics.
Cost
| Tier | Requests | Price |
|---|---|---|
| Free | 100,000/day | Free |
| Paid | 10M/month | ~$50/month |
Troubleshooting
"Module not found": rm -rf node_modules && bun install && bun run deploy:workers
Secret not found: bunx wrangler secret list to verify, then re-set with bun run workers:secret SECRET_NAME
Request timeout: Workers have a 30s CPU time limit. Check Google Sheets API latency. Enable debug logging: bun run workers:secret LOG_LEVEL (enter debug).
Docker
Docker Compose
cp .env.example .env.production
# Edit .env.production with production values
docker-compose up -ddocker-compose logs -f # view logs
docker-compose down # stopDocker
docker build -t signup-api .
docker run -d \
--name signup-api \
-p 3000:3000 \
--env-file .env.production \
--restart unless-stopped \
signup-apiReverse Proxy
Use Nginx or Caddy for SSL and domain routing:
Nginx:
server {
listen 443 ssl http2;
server_name yourdomain.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}Caddy (automatic HTTPS):
yourdomain.com {
reverse_proxy localhost:3000
}Direct Bun (VPS)
curl -fsSL https://bun.sh/install | bash
git clone https://github.com/briansunter/subs.git
cd subs && bun install
cp .env.example .env # edit with production values
bun run startFor process management, use PM2:
bun install -g pm2
pm2 start index.ts --name signup-api --interpreter bun
pm2 save && pm2 startupCloud Platforms
Render
- Create a Web Service, connect your GitHub repo
- Build command:
bun install, Start command:bun run start - Add environment variables in the dashboard
Fly.io
fly launch
fly secrets set GOOGLE_SHEET_ID=your_id GOOGLE_CREDENTIALS_EMAIL=your_email
fly secrets set GOOGLE_PRIVATE_KEY="your_key"
fly deploySecurity Checklist
- [ ] Set
ALLOWED_ORIGINSto specific domains (not*) - [ ] Use HTTPS in production
- [ ] Never commit
.envfiles - [ ] Use different credentials for dev/production
- [ ] Rotate service account keys periodically
- [ ] Consider rate limiting (Cloudflare's built-in, or Nginx/Caddy)
Monitoring
Health Check
curl https://your-domain.com/api/healthSet up automated monitoring with UptimeRobot, Pingdom, or a simple cron:
*/5 * * * * curl -sf https://your-domain.com/api/health || echo "API down" | mail -s "Alert" admin@example.comPrometheus Metrics
See Prometheus Metrics for scrape configuration, Grafana dashboards, and alert rules.
Log Aggregation
Set LOG_LEVEL=warn in production. Logs are structured JSON (Pino) and work with Datadog, Loki, Logtail, or any log aggregation service.
Next Steps
- Troubleshooting - Common issues and solutions
- API Reference - All endpoints and schemas
- Configuration - All environment variables