Skip to content

Secrets management

Where secrets live and how to rotate them.

Never commit secrets. Use platform secret stores:

PlatformStore
GitHub Actionspnpm secrets:sync:github
Cloudflare Workerswrangler secret put / pnpm secrets:sync
Cloudflare PagesProject environment variables
Fly.iofly secrets set

Deploy workflows use the production environment. Sync from local .env files:

Terminal window
pnpm secrets:sync:github -- --dry-run
pnpm secrets:sync:github

Merge order (later wins): frontend/.envfrontend/.env.developmentdashboard/.envdashboard/.env.development → repo root .env. Empty keys are skipped. If FROM_EMAIL_ADDRESS is missing but MAILGUN_DOMAIN is set, no-reply@<domain> is derived automatically.

Keep production values in .env; use .env.development only for local overrides you do not want uploaded.

Requires gh CLI authenticated with secret write access.

Worker name: soultales-partner. Full runbook: dashboard/DEPLOY.md in the monorepo.

TypeExamplesWhere to set
PUBLIC_*PUBLIC_CLERK_PUBLISHABLE_KEY, PUBLIC_SITE_URLGitHub Actions build secrets + local .env
RuntimeCLERK_SECRET_KEY, STRIPE_SECRET_KEY, DIRECTUS_TOKENCloudflare Worker secrets only

Sync runtime secrets from dashboard/secrets.json:

Terminal window
cd dashboard
cp secrets.json.example secrets.json # first time only
pnpm secrets:sync

Set on the production environment (sync with pnpm secrets:sync:github from local .env / dashboard/secrets.json):

CLOUDFLARE_API_TOKEN, CLOUDFLARE_ACCOUNT_ID, PUBLIC_SITE_URL, PUBLIC_CLERK_PUBLISHABLE_KEY, PUBLIC_STRIPE_PUBLISHABLE_KEY, PUBLIC_CHATWOOT_WEBSITE_TOKEN

Worker runtime (webhooks and server): required keys — DIRECTUS_OUTBOUND_SECRET, CLERK_SECRET_KEY, CLERK_WEBHOOK_SIGNING_SECRET, STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, DIRECTUS_URL, DIRECTUS_TOKEN, DIRECTUS_ADMIN_TOKEN. Deploy fails if any required key is missing from GitHub production. Optional keys (Mailgun, Chatwoot, Google Places, OpenAI, etc.) are synced when set. The deploy workflow runs scripts/validate-worker-secrets.mjs --worker dashboard after each deploy.

The frontend deploy workflow also validates and syncs runtime secrets to soultales-www after each deploy (validate-worker-secrets.mjs --worker frontend).

DIRECTUS_OUTBOUND_SECRET must match on the Worker and Fly Directus (real-ireland-app), with FLOWS_ENV_ALLOW_LIST=DIRECTUS_OUTBOUND_SECRET on Directus.

Worker name: soultales-www. See frontend/DEPLOY.md.

DIRECTUS_URL, DIRECTUS_TOKEN, GOOGLE_API_KEY (YouTube thumbnails at build time), Better Auth secrets (AUTH_SECRET, BETTER_AUTH_URL), Turso connection (ASTRO_DB_REMOTE_URL / ASTRO_DB_APP_TOKEN or TURSO_DATABASE_URL / TURSO_AUTH_TOKEN), OAuth client IDs, Mailgun keys

DB_PASSWORD, R2 S3 credentials (STORAGE_S3_KEY, STORAGE_S3_SECRET), Directus KEY/SECRET

SECRET_KEY_BASE, Neon Postgres, Upstash Redis, R2 credentials: see helpdesk/.env.example

Copy .env.example files where provided. Use .env locally; files are gitignored.