Configuration
The CLI and the frontend server it starts read their configuration from the environment. Every command loads the project's .env files first, so a project keeps its configuration in a file instead of exporting variables by hand.
The .env files
Before it parses its options, every command loads .env.local, then .env, from the current working directory:
DMS_API_BASE_URL=http://localhost:5010
DMS_CLIENT_BASE_URL=http://localhost:3001
DMS_BOOTSTRAP_SECRET=replace_with_a_strong_random_value
DMS_SESSION_SECRET=replace_with_at_least_32_characters
- A variable already in the environment is never overwritten, so
DMS_API_BASE_URL=… ajs dms buildand a CI job's injected secrets win over a file left in the checkout..env.localwins over.env. - A variable exported as an empty string counts as set.
- Only the current directory is read: never a parent directory, and never the generated workspace, which is handed its environment by the command that starts it.
- The values reach the workspace build
buildstarts and the serversdevandstartrun, which inherit the environment. - A missing file is not an error; an unreadable one is reported and skipped.
DMS_API_BASE_URL line in .env counts as an explicit backend. ajs dms dev then stops discovering the backend from .antelope/dev.json and keys its workspace on that URL, so it no longer follows a development backend that lands on another port. Leave the variable out of .env to keep discovery for dev.The secrets
| Secret | Used by | Where it comes from |
|---|---|---|
DMS_BOOTSTRAP_SECRET | dev, build, prepare, sent as x-dms-bootstrap | The backend's frontend.bootstrapSecret. dev and prepare read the development credential from .antelope/dms-dev.json when they call the project's own backend; build takes only an explicit value. |
DMS_SESSION_SECRET | The frontend server | You. 32 characters or more: openssl rand -hex 32. dev generates one when the variable is unset; build and start require it. |
DMS_HTML_RENDER_SECRET | The frontend server, to verify the backend's signed e-mail render requests | The manifest, then the variable |
DMS_OAUTH_RELAY_SECRET | The frontend server, presented to the backend's OAuth endpoints | The manifest, then the variable |
The bootstrap credential is never sent by browser traffic: the CLI presents it to the backend's frontend manifest and module archive only.
- Prefer the variable to
--bootstrap-secret, since a command line is visible to every process on the machine. - A credential that holds a space, a line break or a non-ASCII character is refused before any request, since it could not travel in a header.
Secrets the manifest publishes
The backend publishes htmlRender.serviceSecret and oauth.relaySecret in the manifest it serves to an authenticated caller:
| Command | Manifest source |
|---|---|
dev | The manifest it fetches. |
start | The manifest build cached. |
A variable you set always wins over the manifest value. When several modules publish the same secret, the first in manifest-priority order wins, and a module that publishes another value is named in a warning.
Before the server starts, dev and start warn about each secret they do not have and what stops working without it. Once the server is ready, they list where the others came from, never their values:
Secrets: DMS_HTML_RENDER_SECRET, DMS_OAUTH_RELAY_SECRET from the build-time manifest
Session secret rules
An explicit DMS_SESSION_SECRET is always used as it is, and an empty or too-short value is refused, even by dev:
$ DMS_SESSION_SECRET=short ajs dms build -b http://localhost:5050
✖ DMS_SESSION_SECRET is too short: 5 characters, at least 32 needed
build and start sign sessions with it, so it must stay the same across restarts.
→ Create one: openssl rand -hex 32, then set it in the environment or ./.env
build and start never generate one, so a deployment cannot silently sign everyone out on restart. The generated server checks the value again as a safety net.
Server address and cookies
| Variable | dev | start |
|---|---|---|
PORT (or -p) | 3001; moves to the next free port | 3001; stops when in use |
HOST | 127.0.0.1 | 0.0.0.0 |
DMS_COOKIE_SECURE | false | true |
Reverse proxies and additional routes
DMS_TRUSTED_PROXY_HOPS and DMS_COUNTRY_HEADER describe the reverse proxies in front of the server. See Security.
These variables add routes on top of those the modules declare:
| Variable | Guide |
|---|---|
DMS_BACKEND_PROXIES | Routing and the backend proxy |
DMS_PUBLIC_ENDPOINTS | Public endpoints |
DMS_AUTH_ESTABLISH_ENDPOINTS | Sessions and sign-in |
Public dashboard URL
DMS_CLIENT_BASE_URL is the public URL of the dashboard, used in the links e-mails carry: in e-mail renders, it overrides the public.dms.clientBaseUrl the manifest gives the modules.
Environment variables
This table is generated from the list ajs dms help environment prints. Run pnpm docs:reference in this repository after changing that list.
| Variable | What it sets |
|---|---|
DMS_API_BASE_URL | Backend URL, same as -b; clean ignores it |
DMS_BOOTSTRAP_SECRET | Same as --bootstrap-secret |
DMS_SESSION_SECRET | Session key, 32 characters or more; build and start need one, dev makes one when unset |
DMS_OFFLINE | Same as --offline, unless 0, false, no or off |
DMS_PREPARE_STRICT | Same as prepare --strict, read like DMS_OFFLINE |
PORT | Same as -p |
HOST | Address the server binds to (default: 127.0.0.1 for dev, 0.0.0.0 for start) |
DMS_COOKIE_SECURE | Secure cookies unless false (default: false in dev, true in start) |
DMS_TRUSTED_PROXY_HOPS | Trusted reverse-proxy hops, counted from the right (default: 0) |
DMS_COUNTRY_HEADER | Proxy country header relayed to the backend when a proxy is trusted (default: CF-IPCountry; empty: none) |
DMS_HTML_RENDER_SECRET | E-mail render secret, used when the backend publishes none in the manifest |
DMS_OAUTH_RELAY_SECRET | OAuth relay secret, used when the backend publishes none in the manifest |
DMS_AUTH_ESTABLISH_ENDPOINTS | More backend endpoints /auth/establish may open a session from, comma-separated |
DMS_PUBLIC_ENDPOINTS | More backend routes the proxy serves to anyone, as a JSON array |
DMS_BACKEND_PROXIES | More backend prefixes the server proxies, as a JSON array of { path, auth? } |
DMS_CLIENT_BASE_URL | Public frontend URL used in links and e-mails |
NO_COLOR | Same as --no-color |
ANTELOPEJS_VERBOSE | Same as --verbose |
ANTELOPEJS_QUIET | Same as -q, unless 0 or false |
NO_UPDATE_NOTIFIER, CI | Either one turns the update check off |
In the terminal, the same list:
$ ajs dms help environment
Environment (read from the shell, then ./.env.local, then ./.env)
DMS_API_BASE_URL Backend URL, same as -b; clean ignores it
DMS_BOOTSTRAP_SECRET Same as --bootstrap-secret
DMS_SESSION_SECRET Session key, 32 characters or more; build and
start need one, dev makes one when unset
DMS_OFFLINE Same as --offline, unless 0, false, no or off
DMS_PREPARE_STRICT Same as prepare --strict, read like DMS_OFFLINE
PORT Same as -p
HOST Address the server binds to (default: 127.0.0.1
for dev, 0.0.0.0 for start)
DMS_COOKIE_SECURE Secure cookies unless false (default: false in
dev, true in start)
DMS_TRUSTED_PROXY_HOPS Trusted reverse-proxy hops, counted from the
right (default: 0)
DMS_COUNTRY_HEADER Proxy country header relayed to the backend when
a proxy is trusted (default: CF-IPCountry;
empty: none)
DMS_HTML_RENDER_SECRET E-mail render secret, used when the backend
publishes none in the manifest
DMS_OAUTH_RELAY_SECRET OAuth relay secret, used when the backend
publishes none in the manifest
DMS_AUTH_ESTABLISH_ENDPOINTS More backend endpoints /auth/establish may open
a session from, comma-separated
DMS_PUBLIC_ENDPOINTS More backend routes the proxy serves to anyone,
as a JSON array
DMS_BACKEND_PROXIES More backend prefixes the server proxies, as a
JSON array of { path, auth? }
DMS_CLIENT_BASE_URL Public frontend URL used in links and e-mails
NO_COLOR Same as --no-color
ANTELOPEJS_VERBOSE Same as --verbose
ANTELOPEJS_QUIET Same as -q, unless 0 or false
NO_UPDATE_NOTIFIER, CI Either one turns the update check off
A variable set in the shell wins over both files, and .env.local wins over .env.
Only the current directory is read: the generated workspace never loads a .env
of its own.
Workspaces live in ~/.antelopejs/dms-frontend, one per backend URL. dev without
-b keys its own on the project directory instead; pass -b to share one with
build and start. ajs dms workspaces lists them.