Environment variables
Configure Convex, Nuxt, and Better Auth without mixing build-time and runtime concerns.
Better Convex Nuxt connects three environments: the Nuxt build, the deployed Nuxt server and browser, and the Convex deployment. Put each value in the environment that consumes it.
Nuxt variables
| Variable | Required | Purpose |
|---|---|---|
SITE_URL | Yes with auth | Exact public Nuxt origin used by the same-origin proxy |
NUXT_PUBLIC_CONVEX_URL | Yes | Public Convex deployment URL, usually ending in .convex.cloud |
NUXT_PUBLIC_CONVEX_SITE_URL | With auth for local or custom domains | Convex HTTP Actions origin used by the same-origin auth proxy |
BCN_AUTH_PROXY_IP_SECRET | Yes with auth | Private signature key shared only with the Convex environment |
BCN_AUTH_TRUSTED_CLIENT_IP_HEADER | Outside exact loopback development | Header that your host overwrites with exactly one client IP |
The module also reads CONVEX_URL and CONVEX_SITE_URL while Nuxt config is evaluated. Prefer the NUXT_PUBLIC_* names in deployment environments: Nuxt can apply those native public runtime-config overrides after the image was built.
SITE_URL=https://app.example.com
NUXT_PUBLIC_CONVEX_URL=https://example.convex.cloud
NUXT_PUBLIC_CONVEX_SITE_URL=https://example.convex.site
BCN_AUTH_PROXY_IP_SECRET=
BCN_AUTH_TRUSTED_CLIENT_IP_HEADER=For local development, keep these values with the Convex CLI selection in the
ignored .env.local that better-convex convex configure creates, and pass
--dotenv .env.local to Nuxt commands. Do not add a sibling .env with a
second copy. The endpoint values are public. BCN_AUTH_PROXY_IP_SECRET is not:
generate it separately, set the same value in Nuxt and Convex, and leave the
example blank until then so missing configuration stops auth requests. Do not place it
in runtimeConfig.public, commit it, or expose it to browser code.
Convex variables for authentication
These values exist in the Convex deployment, not in the browser bundle:
| Variable | Required with auth | Purpose |
|---|---|---|
SITE_URL | Yes | Exact public Nuxt origin used as the Better Auth base and trusted origin |
CONVEX_SITE_URL | Built in | Deployment-owned HTTP Actions origin used as the Convex session JWT issuer |
BETTER_AUTH_SECRETS | Yes | Versioned Better Auth encryption/signing secrets, newest version first |
BCN_AUTH_PROXY_IP_SECRET | Yes | Same separate proxy signature key used by the Nuxt server |
export BCN_AUTH_PROXY_IP_SECRET="$(openssl rand -base64 32)"
pnpm exec better-convex convex env set SITE_URL https://app.example.com
printf '1:%s' "$(openssl rand -base64 32)" | pnpm exec better-convex convex env set BETTER_AUTH_SECRETS
printf '%s' "$BCN_AUTH_PROXY_IP_SECRET" | pnpm exec better-convex convex env set BCN_AUTH_PROXY_IP_SECRETInject that same exported BCN_AUTH_PROXY_IP_SECRET into the Nuxt process with your secret manager, or start Nuxt from the same shell. Do not print or commit it. A blank Nuxt value deliberately fails closed.
Convex injects CONVEX_SITE_URL into functions as a deployment-owned built-in,
and the CLI rejects attempts to override it. Do not shadow or manually provision
it. Configure the matching public URL for Nuxt through
NUXT_PUBLIC_CONVEX_SITE_URL.
SITE_URL must be an origin only: no path, query, or fragment. Use HTTPS outside loopback development. Configure separate values for preview and production deployments.
Every Convex command in these docs uses better-convex convex. This wrapper
reads the target deployment only from .env.local. It rejects a file with
more than one target, ignores CONVEX_* variables from the shell, and rejects
target flags such as --prod. Before any production command, check that
.env.local holds the production deploy key. See
Deployment.
BETTER_AUTH_SECRET and AUTH_SECRET are rejected, not treated as aliases or decryption fallbacks; BETTER_AUTH_SECRETS is the sole accepted Better Auth secret setting.
Rotate BETTER_AUTH_SECRETS by adding a higher-numbered current value first, for example 2:new,1:old. Better Auth writes with the first version and retains the remaining versions for decryption. Do not reuse a Better Auth secret as the proxy signature key.
Build-time versus deploy-time
CONVEX_URL, SITE_URL, and BCN_AUTH_TRUSTED_CLIENT_IP_HEADER are read when nuxt.config.ts runs, so the build needs them. If a platform builds once and promotes the same artifact between environments, a later CONVEX_URL does not replace the baked public config. Use NUXT_PUBLIC_CONVEX_URL and NUXT_PUBLIC_CONVEX_SITE_URL as native deploy-time overrides, or rebuild for each environment.
The server limits accept the deploy-time overrides NUXT_PUBLIC_CONVEX_SERVER_MAX_RESPONSE_BYTES and NUXT_PUBLIC_CONVEX_SERVER_QUERY_TIMEOUT_MS. Each value must be a positive integer; an invalid value makes requests fail.
Auth identity is also environment-specific. A preview Nuxt origin must point to a Convex deployment whose SITE_URL matches that preview exactly. Do not share production cookies, secrets, or Convex data with previews.
Check before you deploy
Check all seven points:
- The browser can reach
NUXT_PUBLIC_CONVEX_URL. - The Nuxt server can reach both Convex origins.
- Nuxt and Convex have the same exact public origin in
SITE_URL. - Convex exposes its deployment-owned
CONVEX_SITE_URL, and Nuxt targets that exact origin. BETTER_AUTH_SECRETSexists only in Convex and its secret manager.BCN_AUTH_PROXY_IP_SECRETmatches in Nuxt and Convex but is absent from public config.- Outside exact loopback development,
BCN_AUTH_TRUSTED_CLIENT_IP_HEADERnames a header that your host overwrites with exactly one client IP.
Continue with Deployment for the complete release checklist.