318 lines
9.1 KiB
Markdown
318 lines
9.1 KiB
Markdown
---
|
|
name: grey-haven-deployment-cloudflare
|
|
description: Deploy TanStack Start applications to Cloudflare Workers/Pages with GitHub Actions, Doppler, Wrangler, database migrations, and rollback procedures. Use when deploying Grey Haven applications.
|
|
---
|
|
|
|
# Grey Haven Cloudflare Deployment
|
|
|
|
Deploy **TanStack Start** applications to Cloudflare Workers using GitHub Actions, Doppler for secrets, and Wrangler CLI.
|
|
|
|
## Deployment Architecture
|
|
|
|
### TanStack Start on Cloudflare Workers
|
|
- **SSR**: Server-side rendering with TanStack Start server functions
|
|
- **Edge Runtime**: Global deployment on Cloudflare's edge network
|
|
- **Database**: PostgreSQL (PlanetScale) with connection pooling
|
|
- **Cache**: Cloudflare KV for sessions, R2 for file uploads
|
|
- **Secrets**: Managed via Doppler, injected in GitHub Actions
|
|
|
|
### Core Infrastructure
|
|
- **Workers**: Edge compute (TanStack Start)
|
|
- **KV Storage**: Session management
|
|
- **R2 Storage**: File uploads and assets
|
|
- **D1 Database**: Edge data (optional)
|
|
- **Queues**: Background jobs (optional)
|
|
|
|
## Wrangler Configuration
|
|
|
|
### Basic `wrangler.toml`
|
|
```toml
|
|
name = "grey-haven-app"
|
|
main = "dist/server/index.js"
|
|
compatibility_date = "2025-01-15"
|
|
node_compat = true
|
|
|
|
[vars]
|
|
ENVIRONMENT = "production"
|
|
DATABASE_POOL_MIN = "2"
|
|
DATABASE_POOL_MAX = "10"
|
|
|
|
# KV namespace for session storage
|
|
[[kv_namespaces]]
|
|
binding = "SESSIONS"
|
|
id = "your-kv-namespace-id"
|
|
preview_id = "your-preview-kv-namespace-id"
|
|
|
|
# R2 bucket for file uploads
|
|
[[r2_buckets]]
|
|
binding = "UPLOADS"
|
|
bucket_name = "grey-haven-uploads"
|
|
preview_bucket_name = "grey-haven-uploads-preview"
|
|
|
|
# Routes
|
|
routes = [
|
|
{ pattern = "app.greyhaven.studio", zone_name = "greyhaven.studio" }
|
|
]
|
|
```
|
|
|
|
### Environment-Specific Configs
|
|
- **Development**: `wrangler.toml` with `ENVIRONMENT = "development"`
|
|
- **Staging**: `wrangler.staging.toml` with staging routes
|
|
- **Production**: `wrangler.production.toml` with production routes
|
|
|
|
## Doppler Integration
|
|
|
|
### Required GitHub Secrets
|
|
- `DOPPLER_TOKEN`: Doppler service token for CI/CD
|
|
- `CLOUDFLARE_API_TOKEN`: Wrangler deployment token
|
|
|
|
### Required Doppler Secrets (Production)
|
|
```bash
|
|
# Application
|
|
BETTER_AUTH_SECRET=<random-secret>
|
|
BETTER_AUTH_URL=https://app.greyhaven.studio
|
|
JWT_SECRET_KEY=<random-secret>
|
|
|
|
# Database (PlanetScale)
|
|
DATABASE_URL=postgresql://user:pass@host/db
|
|
DATABASE_URL_ADMIN=postgresql://admin:pass@host/db
|
|
|
|
# Redis (Upstash)
|
|
REDIS_URL=redis://user:pass@host:port
|
|
|
|
# Email (Resend)
|
|
RESEND_API_KEY=re_...
|
|
|
|
# OAuth Providers
|
|
GOOGLE_CLIENT_ID=...
|
|
GOOGLE_CLIENT_SECRET=...
|
|
GITHUB_CLIENT_ID=...
|
|
GITHUB_CLIENT_SECRET=...
|
|
|
|
# Cloudflare
|
|
CLOUDFLARE_ACCOUNT_ID=...
|
|
CLOUDFLARE_API_TOKEN=...
|
|
|
|
# Monitoring (optional)
|
|
SENTRY_DSN=https://...@sentry.io/...
|
|
AXIOM_TOKEN=xaat-...
|
|
```
|
|
|
|
## GitHub Actions Deployment
|
|
|
|
### Production Deployment Flow
|
|
```yaml
|
|
# .github/workflows/deploy-production.yml
|
|
- Checkout code
|
|
- Setup Node.js 22 with cache
|
|
- Install dependencies (npm ci)
|
|
- Install Doppler CLI
|
|
- Run tests (doppler run --config test)
|
|
- Build (doppler run --config production)
|
|
- Run database migrations
|
|
- Deploy to Cloudflare Workers
|
|
- Inject secrets from Doppler
|
|
- Run smoke tests
|
|
- Rollback on failure
|
|
```
|
|
|
|
### Key Deployment Commands
|
|
```bash
|
|
# Build with Doppler secrets
|
|
doppler run --config production -- npm run build
|
|
|
|
# Run migrations before deployment
|
|
doppler run --config production -- npm run db:migrate
|
|
|
|
# Deploy to Cloudflare
|
|
npx wrangler deploy --config wrangler.production.toml
|
|
|
|
# Inject secrets into Workers
|
|
doppler secrets download --config production --format json > secrets.json
|
|
cat secrets.json | jq -r 'to_entries | .[] | "\(.key)=\(.value)"' | while read -r line; do
|
|
key=$(echo "$line" | cut -d= -f1)
|
|
value=$(echo "$line" | cut -d= -f2-)
|
|
echo "$value" | npx wrangler secret put "$key"
|
|
done
|
|
rm secrets.json
|
|
```
|
|
|
|
## Database Migrations
|
|
|
|
### Drizzle Migrations (TanStack Start)
|
|
```typescript
|
|
// scripts/migrate.ts
|
|
import { drizzle } from "drizzle-orm/node-postgres";
|
|
import { migrate } from "drizzle-orm/node-postgres/migrator";
|
|
import { Pool } from "pg";
|
|
|
|
const pool = new Pool({
|
|
connectionString: process.env.DATABASE_URL_ADMIN,
|
|
});
|
|
|
|
const db = drizzle(pool);
|
|
|
|
async function main() {
|
|
console.log("Running migrations...");
|
|
await migrate(db, { migrationsFolder: "./drizzle/migrations" });
|
|
console.log("Migrations complete!");
|
|
await pool.end();
|
|
}
|
|
|
|
main().catch((err) => {
|
|
console.error("Migration failed:", err);
|
|
process.exit(1);
|
|
});
|
|
```
|
|
|
|
**package.json scripts**:
|
|
```json
|
|
{
|
|
"scripts": {
|
|
"db:migrate": "tsx scripts/migrate.ts",
|
|
"db:migrate:production": "doppler run --config production -- tsx scripts/migrate.ts"
|
|
}
|
|
}
|
|
```
|
|
|
|
## Rollback Procedures
|
|
|
|
### Wrangler Rollback
|
|
```bash
|
|
# List recent deployments
|
|
npx wrangler deployments list --config wrangler.production.toml
|
|
|
|
# Rollback to previous deployment
|
|
npx wrangler rollback --config wrangler.production.toml
|
|
|
|
# Rollback to specific deployment ID
|
|
npx wrangler rollback --deployment-id abc123 --config wrangler.production.toml
|
|
```
|
|
|
|
### Database Rollback
|
|
```bash
|
|
# Drizzle - rollback last migration
|
|
doppler run --config production -- drizzle-kit migrate:rollback
|
|
|
|
# Alembic - rollback one migration
|
|
doppler run --config production -- alembic downgrade -1
|
|
```
|
|
|
|
### Emergency Rollback Playbook
|
|
1. **Identify issue**: Check Cloudflare Workers logs, Sentry
|
|
2. **Rollback Workers**: `npx wrangler rollback`
|
|
3. **Rollback database** (if needed): `drizzle-kit migrate:rollback`
|
|
4. **Verify rollback**: Run smoke tests
|
|
5. **Notify team**: Update Linear issue
|
|
6. **Root cause analysis**: Create postmortem
|
|
|
|
## Cloudflare Resources Setup
|
|
|
|
### KV Namespace (Session Storage)
|
|
```bash
|
|
# Create KV namespace
|
|
npx wrangler kv:namespace create "SESSIONS" --config wrangler.production.toml
|
|
npx wrangler kv:namespace create "SESSIONS" --preview --config wrangler.production.toml
|
|
|
|
# List KV namespaces
|
|
npx wrangler kv:namespace list
|
|
```
|
|
|
|
### R2 Bucket (File Uploads)
|
|
```bash
|
|
# Create R2 bucket
|
|
npx wrangler r2 bucket create grey-haven-uploads
|
|
npx wrangler r2 bucket create grey-haven-uploads-preview
|
|
|
|
# List R2 buckets
|
|
npx wrangler r2 bucket list
|
|
```
|
|
|
|
## Monitoring
|
|
|
|
### Wrangler Tail (Real-time Logs)
|
|
```bash
|
|
# Stream production logs
|
|
npx wrangler tail --config wrangler.production.toml
|
|
|
|
# Filter by status code
|
|
npx wrangler tail --status error --config wrangler.production.toml
|
|
```
|
|
|
|
### Sentry Integration (Error Tracking)
|
|
```typescript
|
|
import * as Sentry from "@sentry/browser";
|
|
|
|
Sentry.init({
|
|
dsn: process.env.SENTRY_DSN,
|
|
environment: process.env.ENVIRONMENT,
|
|
tracesSampleRate: 1.0,
|
|
});
|
|
```
|
|
|
|
## Local Development
|
|
|
|
### Wrangler Dev (Local Workers)
|
|
```bash
|
|
# Run Workers locally with Doppler
|
|
doppler run --config dev -- npx wrangler dev
|
|
|
|
# Run with remote mode (uses production KV/R2)
|
|
doppler run --config dev -- npx wrangler dev --remote
|
|
```
|
|
|
|
## Supporting Documentation
|
|
|
|
All supporting files are under 500 lines per Anthropic best practices:
|
|
|
|
- **[examples/](examples/)** - Complete deployment examples
|
|
- [github-actions-workflow.md](examples/github-actions-workflow.md) - Full CI/CD workflows
|
|
- [wrangler-config.md](examples/wrangler-config.md) - Complete wrangler.toml examples
|
|
- [doppler-secrets.md](examples/doppler-secrets.md) - Secret management patterns
|
|
- [migrations.md](examples/migrations.md) - Database migration examples
|
|
- [INDEX.md](examples/INDEX.md) - Examples navigation
|
|
|
|
- **[reference/](reference/)** - Deployment references
|
|
- [rollback-procedures.md](reference/rollback-procedures.md) - Rollback strategies
|
|
- [monitoring.md](reference/monitoring.md) - Monitoring and alerting
|
|
- [troubleshooting.md](reference/troubleshooting.md) - Common issues and fixes
|
|
- [INDEX.md](reference/INDEX.md) - Reference navigation
|
|
|
|
- **[templates/](templates/)** - Copy-paste ready templates
|
|
- [wrangler.toml](templates/wrangler.toml) - Basic wrangler config
|
|
- [deploy-production.yml](templates/deploy-production.yml) - GitHub Actions workflow
|
|
|
|
- **[checklists/](checklists/)** - Deployment checklists
|
|
- [deployment-checklist.md](checklists/deployment-checklist.md) - Pre-deployment validation
|
|
|
|
## When to Apply This Skill
|
|
|
|
Use this skill when:
|
|
- Deploying TanStack Start to Cloudflare Workers
|
|
- Setting up CI/CD with GitHub Actions
|
|
- Configuring Doppler multi-environment secrets
|
|
- Running database migrations in production
|
|
- Rolling back failed deployments
|
|
- Setting up KV namespaces or R2 buckets
|
|
- Troubleshooting deployment failures
|
|
- Configuring monitoring and alerting
|
|
|
|
## Template Reference
|
|
|
|
These patterns are from Grey Haven's production templates:
|
|
- **cvi-template**: TanStack Start + Cloudflare Workers
|
|
- **cvi-backend-template**: FastAPI + Python Workers
|
|
|
|
## Critical Reminders
|
|
|
|
1. **Doppler for ALL secrets**: Never commit secrets to git
|
|
2. **Migrations BEFORE deployment**: Run `db:migrate` before `wrangler deploy`
|
|
3. **Smoke tests AFTER deployment**: Validate production after deploy
|
|
4. **Automated rollback**: GitHub Actions rolls back on failure
|
|
5. **Connection pooling**: Match wrangler.toml pool settings with database
|
|
6. **Environment-specific configs**: Separate wrangler files per environment
|
|
7. **KV/R2 bindings**: Configure in wrangler.toml, create with CLI
|
|
8. **Custom domains**: Use Cloudflare Proxy for DDoS protection
|
|
9. **Monitoring**: Set up Sentry + Axiom + Wrangler tail
|
|
10. **Emergency playbook**: Know how to rollback both Workers and database
|