| Region & hostnames |
Values follow D1 = Option A (decided): dashboard eu.agentset.ai, API api.eu.agentset.ai, custom-domain target cname.eu.agentset.ai. |
NEXT_PUBLIC_DEPLOYMENT_REGION new | eu | ● | ● | – | us on the US stack. Drives model and provider allowlists, Stripe region metadata and startup guards. Must differ. |
NEXT_PUBLIC_APP_SHORT_DOMAIN | eu.agentset.ai | ● | – | – | Build-time. Also yields cname.eu.agentset.ai. The default silently falls back to agentset.ai, so set it. Must differ. |
NEXT_PUBLIC_APP_HOSTNAME new | eu.agentset.ai | ● | – | – | Option A only. Unset on US (falls back to app.<SHORT_DOMAIN>). |
NEXT_PUBLIC_API_HOSTNAME new | api.eu.agentset.ai | ● | – | – | Option A only. |
APP_DOMAIN required | https://eu.agentset.ai | ● | ● | – | Exists as optional in packages/emails; becomes required on EU (R1). Email links and List-Unsubscribe. Must be added to turbo.json globalEnv. |
NEXT_PUBLIC_VERCEL_ENV | Vercel system variable | ● | – | – | Turn on "Automatically expose System Environment Variables", or links fall back to localhost. |
NEXT_PUBLIC_APP_NAME | unset (defaults to Agentset) | ○ | – | – | Shared with US is fine. |
| Auth |
BETTER_AUTH_URL | https://eu.agentset.ai | ● | – | – | Exact app origin, no trailing slash (checked against the request origin). |
BETTER_AUTH_SECRET | openssl rand -base64 32 | ● | – | – | Must be unique per region. Never copy the US value. |
GITHUB_CLIENT_ID
GITHUB_CLIENT_SECRET | <the existing OAuth app's values> | ● | – | – | shared with US Same OAuth app with the EU callback added (card 12). Only differs if a separate EU app is created. |
GOOGLE_CLIENT_ID
GOOGLE_CLIENT_SECRET | <the existing web client's values> | ● | – | – | shared with US Same web client with the EU redirect URI added (card 13). |
| Database & Redis |
DATABASE_URL | <Supabase transaction pooler :6543>?pgbouncer=true | ● | ● | – | Must differ. No sslmode: L1 verifies TLS against the pinned Supabase root CA, and a URL sslmode would override it. Test before turning on Enforce SSL. Also needed at build time (Prisma generate). |
DIRECT_URL | <Supabase session pooler :5432>?sslmode=require | – | – | – | Migrations only: .env.eu.local or a GitHub secret for the migrate workflow. Same TLS parameters; check with db:status:eu. |
REDIS_URL | <Upstash REST URL> | ● | ● | – | Same database as the Modal TCP credentials. Must differ. |
REDIS_TOKEN | <Upstash REST token, not read-only> | ● | ● | – | |
REDIS_HOST
REDIS_PORT
REDIS_PASSWORD | <Upstash TCP endpoint> / 6379 / <password> | – | – | ● | Parsing service writes chunk batches here. |
| AI providers |
DEFAULT_AZURE_RESOURCE_NAME | <EU resource subdomain> | ● | ● | – | Must differ. The startup guard rejects the US resource. |
DEFAULT_AZURE_API_KEY | <KEY 1 of the EU resource> | ● | ● | – | Jobs embed chunks; web embeds queries and runs LLMs. |
DEFAULT_COHERE_BASE_URL new | https://<eu-resource>.services.ai.azure.com/providers/cohere | ● | ◐ | – | Unset on US (SDK default api.cohere.com). Required on EU: the R4 guard refuses to start without it, in web and in every job (jobs never rerank). |
DEFAULT_COHERE_API_KEY | <Azure resource KEY 1> | ● | ◐ | – | On EU this holds the Foundry key; a Cohere dashboard key is not needed. Jobs: required by the engine env import until J6. |
| Parsing service link |
PARTITION_API_URL | <EU Modal web endpoint, base URL, no /ingest> | ◐ | ● | – | Jobs call it. Web: build-time env validation, and R4 checks it is the EU URL. Must differ. |
PARTITION_API_KEY | openssl rand -hex 32 | ◐ | ● | ● | Same value as AGENTSET_API_KEY in the Modal secret. Must differ from US. Web: build-time env validation. |
| Object storage (R2) |
S3_ENDPOINT | https://<ACCOUNT_ID>.eu.r2.cloudflarestorage.com | ● | ● | – | The guard asserts .eu.. The non-EU endpoint can't see EU buckets. |
S3_ACCESS_KEY
S3_SECRET_KEY | <R2 token scoped to the 3 EU buckets> | ● | ● | – | Must differ. |
S3_BUCKET | <EU uploads bucket> | ● | ● | – | Must equal R2_CHUNKS_BUCKET_NAME. |
IMAGES_S3_BUCKET | <EU images bucket> | ● | ● | – | Must equal R2_BUCKET_NAME. |
ASSETS_S3_BUCKET | <EU assets bucket> | ● | ● | – | |
ASSETS_S3_URL | https://eu-assets.agentset.ai | ● | ● | – | Also feeds the next/image allowlist once R1 derives it from this variable. |
| Jobs (Trigger.dev) |
TRIGGER_SECRET_KEY | <tr_prod_ key of the EU project> | ● | – | – | Must differ: a US key would run EU jobs in the US project. |
TRIGGER_PROJECT_ID | <proj_ ref of the EU project> | – | – | – | Deploy time only: packages/jobs/.env.eu.local (git-ignored) or a GitHub secret. |
TRIGGER_ACCESS_TOKEN | <tr_pat_ personal access token> | – | – | – | GitHub secret, only for CI deploys. |
TRIGGER_API_URL | unset (Tier 1) | – | – | ○ | Only for a self-hosted EU Trigger.dev (Tier 2). Defaults to https://api.trigger.dev. |
| Billing |
STRIPE_API_KEY | <EU restricted rk_live_ key> | ● | ● | – | EU-specific. Separate restricted key on the shared account, so it can be revoked on its own. |
NEXT_PUBLIC_STRIPE_PUBLIC_KEY | <account pk_live_ key> | ● | ◐ | – | shared with US Jobs: required by the Stripe env import until J6. |
STRIPE_WEBHOOK_SECRET | <whsec_ of the EU endpoint> | ● | – | – | EU-specific (EU endpoint). Must differ. |
| Email |
RESEND_API_KEY | <the existing US key> | ● | ● | – | shared with US Same account and sender domain. Jobs send the webhook-failure emails. |
| Alerts |
DISCORD_HOOK_ALERTS
DISCORD_HOOK_CRON
DISCORD_HOOK_SUBSCRIBERS
DISCORD_HOOK_ERRORS | <the US webhook URLs> or unset | ○ | – | – | shared with US Optional. EU messages carry an [EU] tag and IDs only (A3). Unset, alerts fall back to the function logs. |
| Vercel API (customer domains) |
VERCEL_PROJECT_ID | <EU project prj_ ID> | ● | – | – | Must differ: customer domains attach to the EU project. |
VERCEL_TEAM_ID | <same team_ ID> | ● | – | – | shared with US |
VERCEL_API_TOKEN | <new team-scoped token> | ● | – | – | Separate token, stored as Sensitive. |
| Parsing service (Modal EU secret & deploy) |
AGENTSET_REGION new | eu | – | – | ● | Deploy time (shell/CI): selects the app name, secret name and region="eu" / routing_region="eu-west"; the environment comes from MODAL_ENVIRONMENT. Runtime too (kill-switch), so it must also be in the EU secret. Unset keeps US behaviour. |
MODAL_ENVIRONMENT | eu | – | – | – | Deploy time (shell/CI) only. Selects the Modal environment for deploy and secret lookup; never deploy EU into the default environment. |
AGENTSET_API_KEY | = PARTITION_API_KEY | – | – | ● | Checked on every request. |
DATALAB_API_KEY | <the existing Datalab key> | – | – | ● | shared with US Same account; EU processing is requested per call. |
DATALAB_PROCESSING_LOCATION new | eu | – | – | ● | Sent on every Datalab upload and convert request (P4). Unset on US. |
R2_ENDPOINT_URL | https://<ACCOUNT_ID>.eu.r2.cloudflarestorage.com | – | – | ● | Same as S3_ENDPOINT. |
R2_ACCESS_KEY_ID
R2_SECRET_ACCESS_KEY | <EU-scoped R2 token> | – | – | ● | |
R2_CHUNKS_BUCKET_NAME | = S3_BUCKET | – | – | ● | Mismatch shows up as "Document JSON not found". |
R2_BUCKET_NAME | = IMAGES_S3_BUCKET | – | – | ● | |
R2_PUBLIC_URL | per D7 (default https://eu-files.agentset.ai) | – | – | ● | Final before the first EU ingest: written into chunk text. |
FIRECRAWL_API_KEY | unset (crawl off) | – | – | ○ | optional on EU after the kill-switch change. |
YOUTUBE_API_KEY
PROXY_USERNAME
PROXY_PASSWORD | unset (YouTube off) | – | – | ○ | optional on EU after the kill-switch change. |
MODAL_TOKEN_ID
MODAL_TOKEN_SECRET | <workspace API token> | – | – | – | GitHub secrets, only for CI deploys. |
| Not set on EU (disabled services) |
| Leave these unset on Vercel EU and Trigger EU. A copied US value would point the EU cell at a US account, so the R4 guard refuses to start if any of them is set. The ones the engine's env validation requires today become optional through the named code item, which must land before the first EU deploy. |
DEFAULT_TURBOPUFFER_API_KEY | unset (no managed vector store) | – | – | – | not set on EU Required by the engine env today; optional after E10. EU namespaces use the customer's own key. |
DEFAULT_TURBOPUFFER_REGION new | unset | – | – | – | not set on EU Introduced by E1 for the US managed store (defaults to aws-us-east-1). EU namespaces carry their own region. |
DEFAULT_PINECONE_API_KEY
DEFAULT_PINECONE_HOST | unset | – | – | – | not set on EU Required by the engine env today; optional after E10. |
SECONDARY_PINECONE_API_KEY
SECONDARY_PINECONE_HOST | unset | – | – | – | not set on EU Required by the engine env today; optional after E10. |
DEFAULT_ZEROENTROPY_API_KEY | unset (ZeroEntropy off) | – | – | – | not set on EU Required by the engine env today; optional after E5, which also hides the zerank models on EU. |
TINYBIRD_API_URL
TINYBIRD_API_KEY | unset (no delivery logs) | – | – | – | not set on EU J3 makes them explicitly optional and skips delivery logging when they are unset. |
NEXT_PUBLIC_POSTHOG_KEY | unset (no analytics) | – | – | – | not set on EU Already optional; A1 also keeps the PostHog script and its proxy rewrites out of the EU build. |
EMAIL_FROM_DOMAIN | unset | – | – | – | not set on EU Not needed: EU reuses the US sender domain. Only relevant if a separate EU sender domain is added later. |
| Tooling (optional) |
NEXT_TELEMETRY_DISABLED | 1 | ○ | – | – | Keeps Next.js build telemetry off the processor list. |
CHECKPOINT_DISABLE | 1 | – | – | – | Prisma CLI telemetry, wherever EU migrations run. |
SKIP_ENV_VALIDATION | never set on EU | – | – | – | Validation is the first line of defence against a missing EU value. |