buildmymcpserver/.env.production.example
Marco Sadjadi cf423de3d5
All checks were successful
Deploy to Production / deploy (push) Successful in 1m22s
@
feat(billing): in-app embedded Stripe checkout + webhook hardening

Checkout previously used hosted ui_mode → window.location to checkout.stripe.com,
which pops out of the installed PWA into the system browser. Switch to embedded:

- API: ui_mode embedded_page (stripe-node v22 / API 2025-10 renamed the enum),
  return_url instead of success/cancel_url, returns client_secret.
- web: @stripe/react-stripe-js EmbeddedCheckout mounted in an in-app modal;
  NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY baked at build (Dockerfile arg + compose arg).
- .env.production.example: full Stripe section (was missing) + admin-email
  placeholder (INF-001).

Also bundled (same files): BILL-002 invoice.paid resets quota only on
subscription_cycle; BILL-003 webhook dedup rolled back on handler failure;
BILL-001 change-plan writes plan locally; BILL-004 webhook cross-checks
sub.customer before trusting metadata.orgId; INF-003 API routed off the raw
docker.sock through a locked-down tecnativa/docker-socket-proxy (CONTAINERS+POST).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@
2026-05-29 20:56:40 +02:00

98 lines
4.1 KiB
Plaintext

# ============================================================================
# Production environment for buildmymcpserver.com
# Copy to .env.production on the server and fill every value marked CHANGE-ME.
# Never commit the filled file — .env.production is gitignored.
#
# Used two ways by docker-compose.prod.yml:
# 1. compose interpolation -> docker compose --env-file .env.production ...
# 2. container env -> env_file: .env.production
# ============================================================================
# ---- Core ----
NODE_ENV=production
# ---- Postgres (the compose file owns the container) ----
POSTGRES_USER=bmm
POSTGRES_PASSWORD=CHANGE-ME-strong-db-password
POSTGRES_DB=bmm
# ---- Host ports (loopback only — picked free on the shared box) ----
POSTGRES_PORT=5440
REDIS_PORT=6390
API_PORT=4000
WEB_PORT=4001
# ---- Connection strings ----
# api + web reach the DBs over the compose network (service names).
# The generator overrides these to 127.0.0.1 (it uses host networking).
DATABASE_URL=postgresql://bmm:CHANGE-ME-strong-db-password@postgres:5432/bmm
REDIS_URL=redis://redis:6379
# ---- API ----
PORT=4000
# ---- Public URLs (must match the Cloudflare DNS records) ----
NEXT_PUBLIC_APP_URL=https://buildmymcpserver.com
NEXT_PUBLIC_API_URL=https://api.buildmymcpserver.com
# Used to build the Google OAuth redirect URI and as the JWKS origin.
CONTROL_PLANE_PUBLIC_URL=https://api.buildmymcpserver.com
# Reachable by generated MCP containers — must be public so they can resolve it.
CONTROL_PLANE_URL=https://api.buildmymcpserver.com
OAUTH_ISSUER=https://api.buildmymcpserver.com
# ---- Crypto ----
# REQUIRED in production. The API refuses to boot on the all-zero placeholder.
# Generate with: openssl rand -hex 32
SECRETS_ENCRYPTION_KEY=CHANGE-ME-run-openssl-rand-hex-32
# ---- Admin bootstrap (upserted idempotently on API boot) ----
ADMIN_EMAIL=CHANGE-ME-admin@example.com
ADMIN_PASSWORD=CHANGE-ME-strong-admin-password
ADMIN_NAME=CHANGE-ME-Admin
# ---- Anthropic (empty = mock generation; set for real Claude generation) ----
ANTHROPIC_API_KEY=
# ---- Google OAuth ("Continue with Google") ----
# Google Cloud Console -> APIs & Services -> Credentials -> OAuth client (Web).
# Authorized redirect URI must be EXACTLY:
# https://api.buildmymcpserver.com/v1/auth/google/callback
GOOGLE_OAUTH_ID=
GOOGLE_OAUTH_SECRET=
# ---- OAuth signing keys (RS256 JWKS) ----
# Auto-generated on first boot into this dir; persisted in the bmm_keys volume.
OAUTH_KEY_DIR=./keys
# ---- Runner / Generator ----
# Host used in a generated server's public URL (http://RUNNER_HOST:<port>).
# Generated MCP containers bind host ports in RUNNER_PORT_RANGE_* — this range
# is kept clear of every other app already running on the box.
# NOTE: per-server subdomain routing through nginx is not wired yet — a
# generated server is currently reachable at the host port directly. Treat
# public exposure of generated servers as a follow-up before GA. See DEPLOY.md.
RUNNER_HOST=buildmymcpserver.com
RUNNER_PORT_RANGE_START=4400
RUNNER_PORT_RANGE_END=4900
# ---- Stripe (billing) ----
# Secret key (server-side only — NEVER expose). From Stripe Dashboard → Developers → API keys.
STRIPE_SECRET_KEY=CHANGE-ME-sk_live_...
# Publishable key (safe to expose). Used by the embedded in-app checkout.
STRIPE_PUBLISHABLE_KEY=CHANGE-ME-pk_live_...
# Same publishable key, exposed to the web client bundle at BUILD time (the web
# image is rebuilt by the deploy, so this must be set before deploying or the
# in-app checkout shows "not configured"). Keep it identical to STRIPE_PUBLISHABLE_KEY.
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=CHANGE-ME-pk_live_...
# Webhook signing secret — from the endpoint you create at /v1/billing/webhook.
STRIPE_WEBHOOK_SECRET=CHANGE-ME-whsec_...
# Price IDs (price_… not prod_…) from each product's pricing in the Dashboard.
STRIPE_PRICE_PRO_MONTHLY=CHANGE-ME-price_...
STRIPE_PRICE_PRO_YEARLY=CHANGE-ME-price_...
STRIPE_PRICE_TEAM_MONTHLY=CHANGE-ME-price_...
STRIPE_PRICE_TEAM_YEARLY=CHANGE-ME-price_...
# ---- Observability (optional) ----
SENTRY_DSN=
OTEL_EXPORTER_OTLP_ENDPOINT=