Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Deployment

Vault uses Cloudflare for all deployments: Workers for the API, Pages for the web app, and Workers Assets for static sites.

Environments

EnvironmentPurposeTrigger
StagingTestingPush to main
ProductionLivePush to production

URLs

PackageStagingProduction
Webvault-staging.pages.devvault.oxc.sh
APIvault-api-staging.workers.devvault-api.workers.dev
Docsvault-docs-staging.oxc.devdocs.vault.oxc.sh
CDNvault-cdn.oxc.dev

Deployment Commands

Web App

# Deploy to staging (automatic on main push)
pnpm --filter @pwm/web deploy:staging
 
# Deploy to production
pnpm --filter @pwm/web deploy:production

API

# Deploy to staging
pnpm --filter @pwm/api deploy:staging
 
# Deploy to production
pnpm --filter @pwm/api deploy:production

Documentation

# Deploy to staging
pnpm --filter @pwm/docs deploy:staging
 
# Deploy to production
pnpm --filter @pwm/docs deploy:production

CDN

# Deploy static assets
pnpm --filter @pwm/cdn deploy:production

Git Workflow

Feature Development

# 1. Create feature branch
git checkout -b feature/OXC-123-description origin/main
 
# 2. Develop and commit
git commit -m "feat(OXC-123): add feature"
 
# 3. Push and create PR
git push -u origin feature/OXC-123-description
gh pr create
 
# 4. Merge triggers staging deployment

Production Release

# 1. Ensure main is up to date
git checkout main
git rebase origin/main
 
# 2. Update CHANGELOG.md
git commit -m "docs: add CHANGELOG for vX.Y.Z"
 
# 3. Rebase production on main
git checkout production
git rebase main
 
# 4. Push to trigger production deployment
git push origin main
git push origin production --force-with-lease

Wrangler Configuration

API (packages/api/wrangler.toml)

name = "vault-api"
main = "src/index.ts"
compatibility_date = "2024-01-01"
 
[vars]
API_URL = "https://vault-api.workers.dev"
 
[[kv_namespaces]]
binding = "KV"
id = "abc123..."
 
[env.staging]
name = "vault-api-staging"
kv_namespaces = [
  { binding = "KV", id = "staging-kv-id" }
]
 
[env.production]
name = "vault-api-production"
kv_namespaces = [
  { binding = "KV", id = "production-kv-id" }
]

Web (packages/web/wrangler.toml)

name = "vault-web"
pages_build_output_dir = "./dist"
 
[env.staging]
name = "vault-staging"
 
[env.production]
name = "vault-production"
routes = [{ pattern = "vault.oxc.sh", custom_domain = true }]

Docs (packages/docs/wrangler.toml)

name = "vault-docs"
compatibility_date = "2025-12-18"
assets = { directory = "./docs/dist" }
 
[env.staging]
name = "vault-docs-staging"
routes = [{ pattern = "vault-docs-staging.oxc.dev", custom_domain = true }]
 
[env.production]
name = "vault-docs-production"
routes = [{ pattern = "docs.vault.oxc.sh", custom_domain = true }]

Environment Variables

API Secrets

# Set secret for staging
wrangler secret put JWT_SECRET --env staging
 
# Set secret for production
wrangler secret put JWT_SECRET --env production

Web Environment

Build-time variables in .env:

VITE_API_URL=https://vault-api.workers.dev
VITE_MOCK_AUTH=false

CI/CD Pipeline

GitHub Actions

name: Deploy
 
on:
  push:
    branches: [main, production]
 
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
 
      - name: Setup pnpm
        uses: pnpm/action-setup@v2
 
      - name: Install
        run: pnpm install
 
      - name: Typecheck
        run: pnpm typecheck
 
      - name: Test
        run: pnpm test
 
      - name: Deploy to Staging
        if: github.ref == 'refs/heads/main'
        run: |
          pnpm --filter @pwm/api deploy:staging
          pnpm --filter @pwm/web deploy:staging
        env:
          CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
 
      - name: Deploy to Production
        if: github.ref == 'refs/heads/production'
        run: |
          pnpm --filter @pwm/api deploy:production
          pnpm --filter @pwm/web deploy:production
        env:
          CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}

Rollback

Quick Rollback

# Rollback production to previous commit
git checkout production
git reset --hard HEAD~1
git push --force-with-lease

Specific Version Rollback

# Find commit to rollback to
git log --oneline production
 
# Reset to specific commit
git checkout production
git reset --hard <commit-sha>
git push --force-with-lease

Monitoring

Cloudflare Dashboard

  • Workers: Request counts, errors, latency
  • KV: Storage usage, read/write ops
  • Pages: Build status, deployment history

Logs

# Tail API logs
wrangler tail --env production
 
# Filter by status
wrangler tail --env production --status error

Custom Domains

Setup

  1. Add domain in Cloudflare DNS
  2. Configure routes in wrangler.toml
  3. Deploy with --env production

SSL/TLS

Cloudflare provides automatic SSL for all custom domains.

Database Migrations

KV doesn't require migrations, but for schema changes:

  1. Deploy backward-compatible API first
  2. Run migration script
  3. Remove backward compatibility
// Example migration script
async function migrateVaults(env: Env) {
  const list = await env.KV.list({ prefix: "vaults:" });
  for (const key of list.keys) {
    const vault = await env.KV.get(key.name, "json");
    if (!vault.version) {
      vault.version = 1;
      await env.KV.put(key.name, JSON.stringify(vault));
    }
  }
}

Related