This guide covers production deployment via GitHub Actions and local development setup.
- Node.js >= 20.0.0
- pnpm >= 8.0.0
- wrangler (Cloudflare CLI)
# Install pnpm
npm install -g pnpm
# Install wrangler
npm install -g wrangler
# Or use pnpm
pnpm add -g wrangler- Create a Cloudflare account at https://dash.cloudflare.com
- Generate an API Token with D1 and Workers permissions
- Log in with wrangler (for local development):
wrangler login
EdgeAuth uses GitHub Actions for automated deployments. No manual deployment scripts needed!
Configure GitHub Secrets (Repository Settings → Secrets and variables → Actions):
-
CLOUDFLARE_API_TOKEN - Cloudflare API token with D1 and Workers permissions
How to get:
- Go to Cloudflare Dashboard → My Profile → API Tokens
- Create Token → Use template: "Edit Cloudflare Workers"
- Add permissions: Account.Cloudflare D1 (Edit), Account.Workers Scripts (Edit)
-
GH_PAT - GitHub Personal Access Token
How to get:
- GitHub Settings → Developer settings → Personal access tokens → Tokens (classic)
- Generate new token with
repoandworkflowpermissions
-
JWT_SECRET - Secret key for JWT token signing
Generate:
openssl rand -base64 32
-
PLUNK_API_KEY - Plunk email service API key
Get from: https://www.useplunk.com/dashboard
Add all secrets to GitHub:
Repository Settings → Secrets and variables → Actions → New repository secret
1. Create release branch
└─ git checkout -b release/v0.1.0
2. Update version in package.json
└─ "version": "0.1.0"
3. Create PR to main
└─ Opens PR for review
4. Merge PR
└─ Triggers Release workflow
├─ Creates Git tag (v0.1.0)
└─ Creates GitHub Release
5. Release published
└─ Triggers Deploy workflow
├─ Creates/gets D1 database
├─ Applies migrations
└─ Deploys 4 workers
The deploy.yml workflow automatically:
-
Creates Database (if doesn't exist)
- Database name:
edgeauth-db - Checks if already exists before creating
- Database name:
-
Applies Migrations
wrangler d1 migrations apply edgeauth-db --remote
- Uses Cloudflare's native migration system
- Automatically tracks applied migrations
- Idempotent (safe to run multiple times)
-
Deploys Workers
edgeauth-admin- Admin APIedgeauth-account- User registration & loginedgeauth-sso- SSO sessionsedgeauth-oauth- OAuth 2.0 provider
You can manually trigger deployment:
- Go to Actions tab in GitHub
- Select "Deploy" workflow
- Click "Run workflow"
- Choose branch and run
Check deployed workers:
wrangler deployments list edgeauth-admin
wrangler deployments list edgeauth-account
wrangler deployments list edgeauth-sso
wrangler deployments list edgeauth-oauthTest the API:
# Get worker URL from wrangler
curl https://edgeauth-account.<your-subdomain>.workers.dev/healthUse the setup script for complete local environment:
# From EdgeAuth root directory
pnpm setup:localThis script will:
- Install dependencies
- Build packages
- Create local D1 database
- Apply migrations using Cloudflare's native system
- Create
.dev.varsfiles with default values
Start any worker locally:
# Account API (default port 8787)
cd services/account-api
wrangler dev
# Admin API (port 8788)
cd services/admin-api
wrangler dev --port 8788
# SSO API (port 8789)
cd services/sso-api
wrangler dev --port 8789
# OAuth API (port 8790)
cd services/oauth-api
wrangler dev --port 8790# Run all tests
pnpm test
# Watch mode
pnpm test:dev
# Coverage
pnpm test:ciLocal D1 databases are stored in:
.wrangler/state/v3/d1/
To reset local database:
rm -rf .wrangler/state
pnpm setup:localEdgeAuth uses a single database (edgeauth-db) containing all tables:
users- User accountssso_sessions- SSO sessionsoauth_clients- OAuth clientsauthorization_codes- OAuth authorization codesaccess_tokens- OAuth access tokensrefresh_tokens- OAuth refresh tokens
Migrations are stored in /migrations and managed by Cloudflare's native system:
migrations/
├── 0001_create_users_table.sql
├── 0002_create_sso_sessions_table.sql
└── 0003_create_oauth_tables.sql
Key Features:
- Automatic tracking in
d1_migrationstable - Idempotent (safe to run multiple times)
- Sequential execution by filename
# List tables
wrangler d1 execute edgeauth-db --command "SELECT name FROM sqlite_master WHERE type='table';"
# Describe a table
wrangler d1 execute edgeauth-db --command "PRAGMA table_info(users);"
# Check applied migrations
wrangler d1 execute edgeauth-db --command "SELECT * FROM d1_migrations;"# Production
wrangler d1 execute edgeauth-db --command "SELECT * FROM users LIMIT 10;"
# Local
wrangler d1 execute edgeauth-db --local --command "SELECT * FROM users LIMIT 10;"# Export database to SQL file
wrangler d1 export edgeauth-db --output=backup.sql
# Restore from backup
wrangler d1 execute edgeauth-db --file=backup.sql# Create new migration file
wrangler d1 migrations create edgeauth-db <migration_name>
# This creates: migrations/XXXX_<migration_name>.sql
# Edit the file and add your SQL
# Apply locally
wrangler d1 migrations apply edgeauth-db --local
# Apply to production (via GitHub Actions)
# Commit and push - deployment workflow handles itProblem: Migration already applied
Solution: Cloudflare tracks migrations automatically. If you see this error, the migration was already applied. Use IF NOT EXISTS in your SQL to make migrations idempotent.
Check migration status:
wrangler d1 migrations list edgeauth-dbCheck logs:
wrangler tail edgeauth-accountView deployment errors:
wrangler deployments list edgeauth-accountReset local database:
# Delete local state
rm -rf .wrangler/state
# Re-run setup
pnpm setup:localIf you see JWT validation errors, ensure secrets are set:
# List secrets
wrangler secret list
# Set missing secret
wrangler secret put JWT_SECRETCommon issues:
-
Missing CLOUDFLARE_API_TOKEN
- Add in Repository Settings → Secrets
-
Insufficient permissions
- API token needs D1 and Workers permissions
-
Migration fails
- Check migration SQL syntax
- Ensure
IF NOT EXISTSfor idempotency
View workflow logs:
- Go to Actions tab in GitHub
- Click on failed workflow
- Check individual step logs
Runs on every PR and push to main:
- Lint
- Type check
- Tests
- Build verification
Runs when release/* branch PR is merged:
- Extracts version from package.json
- Creates Git tag
- Creates GitHub Release
- Deletes release branch
Runs when GitHub Release is published:
- Creates/gets D1 database
- Updates wrangler configs with database ID
- Applies migrations
- Deploys all workers to production
Previously used 3 separate databases, but consolidated to single database because:
- Simpler Migration Management - Use Cloudflare's native migration system
- No Performance Impact - SQLite has table-level isolation
- Easier to Manage - One database to backup, monitor, query
- Idempotent Deployments - Automatic migration tracking
Cloudflare automatically creates a d1_migrations table:
CREATE TABLE d1_migrations (
id INTEGER PRIMARY KEY,
name TEXT UNIQUE,
applied_at INTEGER
);Every migration is recorded, preventing duplicate execution.