AppEngine is configured entirely through environment variables — no config files. This page lists what's read, grouped by purpose. Set the required ones; leave the optional ones unset to disable the corresponding feature.
Required for boot
AppEngine refuses to start without these.
| Var | Example | Purpose |
|---|---|---|
NODE_ENV | production | Affects logging, rate limiting, error verbosity |
SERVER_PORT | 3300 | HTTP port |
MONGODB_CONN | mongodb://user:pass@host:27017 | Mongo connection string |
MONGODB_HOST | mongodb | Mongo host (used when MONGODB_CONN not set) |
MONGODB_PORT | 27017 | Mongo port |
MONGODB_USERNAME | admin | Mongo user |
MONGODB_PASSWORD | <secret> | Mongo password |
REDIS_CONN | redis://redis:6379 | Redis connection string |
REDIS_HOST | redis | Redis host (used when REDIS_CONN not set) |
REDIS_PORT | 6379 | Redis port |
JWT_SECRET | 64+ chars | HMAC key for issued tokens |
JWT_REFRESH_SECRET | 64+ chars | HMAC key for refresh tokens |
ROOT_ORG | myco | Initial root org id, created on first boot |
ROOT_USER | admin | Initial root user username |
ROOT_EMAIL | [email protected] | Initial root user email |
ROOT_PASSWORD | <secret> | Initial root user password |
Generate JWT secrets with:
openssl rand -base64 64
The shipped development.env uses 'secretKey' as the fallback. Do not run that in production.
URLs and addressing
| Var | Default | Purpose |
|---|---|---|
BASE_URL | http://localhost:3300 | The public URL AppEngine serves at; used in emails, callbacks |
APPENGINE_URL | http://localhost:3300 | Self-reference for internal calls |
APPENGINE_LOCAL_URL | https://proxy.appmint.io | Used as a fallback when AppEngine talks to itself in prod |
WEBSITEMINT_URL | http://localhost:3100 | URL of the websitemint admin |
BUILDER_URL | http://localhost:3100 | URL of the builder |
STUDIO_URL | (unset) | Vibe Studio URL, if deployed |
APP_URL | (unset) | Front-end app URL for email link generation |
SITE_HOST_NAME | (unset) | Override the host detection for Nginx pass-through |
SHARED_ORG | localhost | Org used for shared/free-tier pages |
SITE_ID | websitemint | Default site id |
INSTANCE_ID | local-dev | Display name for this AppEngine instance |
Auth + security
| Var | Required | Purpose |
|---|---|---|
JWT_SECRET | yes | HMAC key |
JWT_REFRESH_SECRET | yes | Refresh-token HMAC |
JWT_EXPIRES_IN | no | Access token TTL (default 8h) |
JWT_REFRESH_EXPIRES_IN | no | Refresh token TTL (default 30d) |
JWT_AUDIENCE | no | aud claim, defaults to appmint |
JWT_ISSUER | no | iss claim |
AUTH_TOKEN_AGE | no | Same as JWT_EXPIRES_IN, legacy |
REFRESH_TOKEN_AGE | no | Same as JWT_REFRESH_EXPIRES_IN, legacy |
RATE_LIMIT_MAX | no | Requests/min/IP. Default 100. Disable with very high value |
ALLOWED_ORIGINS | no | CORS allowlist, comma-separated |
TRUST_PROXY_HOPS | no | Number of upstream proxies to trust for IP detection |
ALLOW_SELF_SIGNED_CERTS | no | Set to true to accept self-signed TLS on outbound calls (dev only) |
Storage
| Var | Purpose |
|---|---|
S3_ENDPOINT | S3-compatible endpoint URL |
S3_KEY | Access key |
S3_SECRET | Secret key |
S3_BUCKET | Bucket name |
S3_REGION | Region (e.g., us-east-1, sfo3) |
S3_SPACE_BASE_URL | Public CDN URL for served assets |
FILE_PATH | Local path for filesystem fallback (default ./) |
IMAGE_SIZES | Comma-separated thumbnail sizes (e.g., 100,300,800) |
IMAGE_EXTENSIONS | Allowed upload extensions |
Set the S3 vars to use object storage. With them missing, AppEngine writes to the local filesystem under FILE_PATH — fine for dev, useless for multi-pod production.
AI providers
Set the keys for any LLM you want to use; leave the rest unset.
| Var | Provider |
|---|---|
OPENAI_API_KEY | OpenAI |
ANTHROPIC_API_KEY | Anthropic Claude |
DEEPSEEK_API_KEY | DeepSeek |
GEMINI_API_KEY | Google Gemini |
AI_PROVIDER | Default text provider (openai, anthropic, deepseek, gemini) |
AI_PROVIDER_TEXT | Override for text-only flows |
AI_PROVIDER_IMAGE | Provider for image generation |
AI_PRICING_OVERRIDES | JSON map of model → price-per-1k-tokens for usage metering |
ENABLE_TOKENIZATION | true to count tokens server-side |
The /ai/agent/stream endpoint requires at least one provider key. Without any, AI features 500.
| Var | Purpose |
|---|---|
EMAIL_SERVICE_ENABLED | true to enable outbound email |
MAILER_SERVICE_HOST | SMTP host |
MAILER_SERVICE_PORT | SMTP port |
For SaaS, prefer Postmark/SendGrid HTTP API providers configured per-org via the admin UI rather than a global SMTP. The global SMTP is for system emails (root-org notifications).
OAuth providers
Configure the ones your customers will use. Each comes in pairs (client id + secret).
| Provider | Vars |
|---|---|
GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET | |
FACEBOOK_APP_ID, FACEBOOK_APP_SECRET, FACEBOOK_CLIENT_ID, FACEBOOK_CLIENT_SECRET, FACEBOOK_CALL_BACK_URL | |
| GitHub | GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET, GITHUB_AUTH_URL |
TWITTER_API_KEY, TWITTER_API_SECRET, TWITTER_CLIENT_ID, TWITTER_CLIENT_SECRET, TWITTER_CONSUMER_SECRET | |
LINKEDIN_CLIENT_ID, LINKEDIN_CLIENT_SECRET | |
| TikTok | TIKTOK_CLIENT_ID, TIKTOK_CLIENT_SECRET |
PINTEREST_CLIENT_ID, PINTEREST_CLIENT_SECRET | |
REDDIT_CLIENT_ID, REDDIT_CLIENT_SECRET, REDDIT_USER_AGENT | |
| Snapchat | SNAPCHAT_CLIENT_ID, SNAPCHAT_CLIENT_SECRET |
| Slack | SLACK_CLIENT_ID, SLACK_CLIENT_SECRET |
| Twitch | TWITCH_CLIENT_ID, TWITCH_CLIENT_SECRET |
| Figma | FIGMA_CLIENT_ID, FIGMA_CLIENT_SECRET, FIGMA_REDIRECT_URI |
Maps + geo
| Var | Purpose |
|---|---|
GOOGLE_MAPS_API_KEY | Geocoding, Places autocomplete |
Payment + finance
| Var | Purpose |
|---|---|
STRIPE_PUBLISHABLE_KEY | Public key (sent to clients via config) |
BANKING_ROUTING_NUMBER | ACH routing for sponsored banking |
SPONSOR_BANK_API_KEY | Sponsor bank integration |
SPONSOR_BANK_API_URL | Sponsor bank base URL |
SPONSOR_BANK_ID | Sponsor bank id |
Stripe secret keys, PayPal credentials, Twilio account, etc. are configured per-org via the admin UI rather than env. That model lets multi-tenant deployments give each customer their own gateway.
Shipping + integrations
| Var | Purpose |
|---|---|
EASYPOST_API_KEY | EasyPost shipping rates + labels |
RESELLER_CLUB_API_KEY / _USER_ID / _BASE_URL | ResellerClub for domains |
DOMAIN_PROVIDER | Domain registrar used for site provisioning |
PEXELS_API_AUTH_TOKEN | Stock photo lookup |
VIDEOSDK_API_KEY / _SECRET_KEY / _API_ENDPOINT | Video calls |
Site provisioning + dev environments
| Var | Purpose |
|---|---|
KUBE_CONFIG_PATH | Path to a kubeconfig used for site deployments |
KUBERNETES_SERVICE_HOST / _PORT | Auto-detected when running in-cluster |
DEPLOY_TEMPLATE_PATH | Path to deploy templates |
GIT_LOCAL_REPO | Local git mirror |
GIT_TOKEN | Git access token |
GIT_USER | Git author username |
DEV_ENV_NODE_IMAGE_NAME | Container image for Node dev environments |
DEV_ENV_FLUTTER_IMAGE_NAME | Container image for Flutter dev environments |
DOCKER_TOKEN / DOCKER_USER / DOCKER_NAMESPACE / DOCKER_EMAIL / DOCKER_REGISTRY_SERVER | Image push credentials |
TAILWIND_LOCAL_REPO / TAILWIND_LOCAL_QUICK_REPO | Local Tailwind build paths |
SPINFORGE_PROVIDER_URL | SpinForge provider URL (if used) |
Workers + background jobs
| Var | Purpose |
|---|---|
ENABLE_SYNC_PROCESSORS | true/false — enable BullMQ processors |
ENABLE_SYNC_CONSUMERS | true/false — enable consumers |
ENABLE_SYNC_JOBS | true/false — enable cron jobs |
ENABLE_SYNC_SOCIAL_MEDIA | true/false — social media polling |
PROCESS_JOBS | Job processor mode |
SOCIAL_MEDIA_SERVICE_ENABLED | Enable social posting workers |
GOOGLE_ADS_SERVICE_ENABLED | Enable Google Ads sync |
If you split the deployment into web replicas + worker replicas, set ENABLE_SYNC_* to true only on workers and false on web. Both still need to be able to enqueue, but only workers should consume.
Operational + monitoring
| Var | Purpose |
|---|---|
MEMORY_LIMIT | Heap limit (in MB) AppEngine targets |
DISABLE_INTERNAL_HEALTH_CHECKS | Disable the internal liveness pings |
TRACK_USAGE_WHEN_DISABLED | Track usage even for orgs with disabled metering |
VERIFY_TOKEN | Webhook verification token |
VIBE_DATA_PATH | Path for Vibe Studio data |
Elasticsearch (optional)
| Var | Purpose |
|---|---|
ELASTICSEARCH_NODE | Cluster URL |
ELASTICSEARCH_USERNAME | Username |
ELASTICSEARCH_PASSWORD | Password |
Without these, full-text search falls back to MongoDB text indexes — adequate up to ~100k documents per searchable collection.
Cloudflare (optional)
| Var | Purpose |
|---|---|
CLOUDFLARE_ACCOUNT_ID | Account id |
CLOUDFLARE_API_TOKEN | API token |
Used for DNS record creation when AppEngine provisions sites with custom domains.
Secret management in production
Don't ship .env files to production servers. Use a real secret store:
- Kubernetes: External Secrets Operator + AWS Secrets Manager / GCP Secret Manager / Vault
- Docker Compose on a single box: Docker secrets via
secrets:blocks, not env files - Cloud platforms: their built-in secret store (Fly secrets, Render env groups, Vercel env)
Rotate JWT_SECRET and JWT_REFRESH_SECRET quarterly at minimum. Existing JWTs become invalid the moment you rotate — schedule it during a planned maintenance window or implement a graceful overlap (validate against new + old for 24h).
Vendor API keys (Stripe, OpenAI, etc.) configured at the org level rotate via the admin UI without restarting AppEngine.