Secrets
Environment variables per environment — production, preview and development — with the keys Camplax injects for you.
Every project has a vault for environment variables: API keys, feature flags, anything your app reads from process.env. Values live in the vault, never in your repo, and reach the running app as environment variables — your code cannot tell the difference between a value you set and one Camplax injected.
Three environments, plus branch overlays
Each key can exist once per environment — and, inside preview, once per git branch:
| Layer | Who reads it |
|---|---|
production | The live app at your-app.camplax.app and your custom domains |
preview | Every branch preview, overlaid on production |
preview + branch | One specific branch's preview, overlaid on both |
development | camplax dev and camplax env pull on your laptop, overlaid on production |
The merge order, with later layers winning:
- Production: production.
- Preview: production → preview → that branch's overlay.
- Development: production → development.
So one STRIPE_KEY in production, a test key under preview, and a different test key under preview + branch feature/billing gives you three apps on three sets of credentials without a single if in your code.
Setting secrets
In the console: open Settings → Secrets. Add a key, pick the environments it applies to, optionally scope a preview value to a branch, and choose whether it is sensitive. Paste a whole .env file into the import box to load many at once — existing keys are updated, not duplicated.
From the CLI:
camplax env pull # vault → local .env
camplax env push # local .env → vault
env pull writes the development view — your development keys over any non-sensitive production keys, with managed names like DATABASE_URL left out. It is the one read that can reveal values, so it is owner-only; project keys cannot call it. env push uploads KEY=value lines to both the production and development layers, then restarts the app so the new values are live. It only accepts UPPER_SNAKE_CASE keys, skips empty values, and refuses keys Camplax manages — DATABASE_URL, DIRECT_URL, BETTER_AUTH_SECRET, R2_PREFIX, AUTH_PROVIDERS, AUTH_CLAIMS, PORT and anything starting CAMPLAX_. When camplax.json lists env names, push sends only those keys.
Applying without a rebuild
Saving a secret does not bounce the app by itself. Ask for apply on the write, or run it explicitly:
POST /v1/projects/:slug/settings/secrets/apply
This pushes the current vault into the running app's environment and restarts it — a few seconds of restart, not a rebuild. camplax env push does this for you at the end. If the app has not been deployed yet, the values are simply saved for the first deploy. One guarantee worth knowing: deleting a key in the vault really does remove it from the process — it does not linger as a stale value.
The keys Camplax injects
Some environment variables are set by the platform on every deploy, and they always win — a vault entry with the same name is ignored. These are the ones your code will actually use:
| Variable | What it carries |
|---|---|
DATABASE_URL | Pooled connection string for your project's database |
DIRECT_URL | Direct (unpooled) connection string — for migrations and admin tools |
BETTER_AUTH_SECRET | The sign-in secret your app's auth is built with |
CAMPLAX_URL | This deployment's own URL — https://your-app.camplax.app or the preview host |
CAMPLAX_API_URL | The Camplax API base URL |
CAMPLAX_PROJECT_ID / CAMPLAX_PROJECT_SLUG | Which project this app is |
CAMPLAX_ENVIRONMENT | production or preview |
CAMPLAX_GIT_COMMIT / CAMPLAX_GIT_BRANCH / CAMPLAX_DEPLOY_ID | Exactly which code this is |
CAMPLAX_ANALYTICS_KEY | The key your app sends analytics and errors with |
CAMPLAX_AI_API_KEY | A project key scoped to ai:invoke, present once the AI gateway is enabled |
CAMPLAX_LOG_INGEST / CAMPLAX_LOG_INGEST_TOKEN | Where and how the runtime ships its logs |
R2_PREFIX | This environment's storage prefix |
PORT | The port your server must listen on — 8080 |
A few more appear situationally — CAMPLAX_REALTIME_TOKEN on production, CAMPLAX_PREVIEW_GATE_SHA256 on locked previews, CAMPLAX_TURNSTILE_SITE_KEY when bot checks are on, AUTH_PROVIDERS and AUTH_CLAIMS for sign-in configuration. Because the platform owns them, they cannot be set or edited in the vault — trying returns a forbidden error.
To match what hosted templates expect, Camplax also fills the usual framework aliases only when you did not set them: POSTGRES_URL from DATABASE_URL, AUTH_SECRET and NEXTAUTH_SECRET from BETTER_AUTH_SECRET, AUTH_URL and NEXTAUTH_URL from CAMPLAX_URL.
Write-only, on purpose
A production or preview secret is sealed by default: the console shows it as dots, and it cannot be read back — not by the list endpoint, not by env pull, not by the reveal call. To change a sealed value you replace it. This is the same contract as Vercel's sensitive variables:
- Sealing is one-way. A sensitive variable cannot be made readable again; replace the value instead.
- Development is the exception. Development values are always readable, which is what lets
env pullround-trip a working.env. - Reveal exists but is narrow.
GET /settings/secrets/:key/revealreturns a value only for a non-sensitive secret you set, only for owner and member roles, and every reveal is written to the project's activity log. Managed values can never be revealed. - MCP and project keys can list secret names and presence — never values.
The API
All under /v1/projects/:slug/settings, authenticated with a console session, a CLI token, or a project key holding env:read (reads) or env:write (writes):
| Method | Path | What it does |
|---|---|---|
GET | /secrets | List keys — metadata only, never values |
GET | /secrets/for-build | Which key names exist — for build and log surfaces |
POST | /secrets | Set a key: { key, value, environments, branch, sensitive, apply } |
POST | /secrets/import | Bulk-upsert a pasted .env body |
POST | /secrets/apply | Push the vault onto the running app and restart it |
POST | /secrets/redact | Scrub known values out of a string — used on logs |
PATCH | /secrets/:key | Replace a value or change sensitivity — ?environment= / ?branch= select the layer |
GET | /secrets/:key/reveal | Read back a non-sensitive value (owner/member, logged) |
DELETE | /secrets/:key | Delete a key from one layer |
Under the hood: values live in a secrets KV namespace, one entry per key per layer; the platform database holds only names and flags.