Reference
app.json & env reference
The precise lookup page: every field in app.json with its type and default, the full
catalog of reserved ASTRODOCK_* variables (and when each one is present), and the
shape of an app-declared env[] entry. For the how-and-why, see
App structure & app.json.
app.json schema
Plain JSON, no comments. The CLI and the platform validate against this schema, so a malformed
manifest is caught at apply.
Top level
| Field | Type | Req | Default | Notes |
|---|---|---|---|---|
schemaVersion | string | yes | — | Must be "1". |
slug | string | yes | — | Pattern ^[a-z0-9-]+$, max 40 chars. Immutable identity — names the process/container, internal DB, and storage prefix. |
name | string | yes | — | Human display name (min length 1). |
description | string | no | — | Shown in the dashboard. |
subdomain | string | yes | — | Pattern ^[a-z0-9-]+$, max 40 chars. App served at https://<subdomain>.<base-domain>. Mutable. |
source | object | yes | — | Where code comes from. See below. |
runtime | object | yes | — | How the app is built and run. See below. |
auth | object | yes | — | Auth mode. See below. |
database | object | yes | — | Database mode. See below. |
storage | object | yes | — | Object-storage mode. See below. |
env | array | no | [] | App-declared variables (names + metadata). See below. |
source
| Field | Type | Req | Default | Notes |
|---|---|---|---|---|
branch | string | no | "main" | Branch deployed and watched for webhook pushes. |
repoPath | string | no | "" | Subdirectory to deploy from (monorepos). "" = repo root. |
githubRepo | string | no | — | owner/repo to connect. Can also be set via the CLI or dashboard. |
runtime
| Field | Type | Req | Default | Notes |
|---|---|---|---|---|
type | enum | yes | — | "node" (buildpack) or "docker" (Dockerfile container). |
buildCommand | string | no | "npm run build" | Node only. Frontend build command. |
dockerfile | string | no | "Dockerfile" | Docker only. Path to the Dockerfile, relative to repoPath. |
auth / database / storage
| Block | Field | Values | Effect |
|---|---|---|---|
auth | mode | platform · public | platform injects the auth vars and registers an app secret for /verify; public injects none. |
database | mode | internal · external · none | internal provisions a Postgres DB and injects ASTRODOCK_DATABASE_URL; external makes that var a required secret you set; none injects nothing. |
storage | mode | internal · external · none | internal provisions a bucket/prefix + key and injects ASTRODOCK_STORAGE_*; external makes those required secrets; none injects nothing. |
Change & immutability
| Field | Behavior |
|---|---|
slug | Immutable. Changing it means a new app. |
subdomain | Mutable — triggers a routing re-provision + new TLS certificate. |
runtime.type | Mutable — the next deploy switches execution path; the old process/container is torn down. |
database.mode / storage.mode | Mutable but non-migrating: switching points the app at a different (or empty) store. No data is copied. |
Reserved ASTRODOCK_* variables
The platform injects these into your app at deploy; the app reads
them and never sets or declares them. An app-declared key may not start with ASTRODOCK_.
"auto" means the platform generates it; "user-required" means an operator must set it before deploy
(the external resource modes).
| Variable | Present when | Source | Meaning |
|---|---|---|---|
ASTRODOCK_APP_SLUG | always | auto | App slug / identity. |
ASTRODOCK_APP_NAME | always | auto | Display name. |
ASTRODOCK_APP_URL | always | auto | Public URL, https://<sub>.<domain>. |
ASTRODOCK_BASE_DOMAIN | always | auto | Platform base domain. |
ASTRODOCK_PORT | always | auto | The port the server MUST bind. |
ASTRODOCK_ENV | always | auto | Deploy environment, e.g. production. |
ASTRODOCK_DATABASE_URL | database ≠ none | auto (internal) / user-required (external) | Full connection string. Same name in both modes. |
ASTRODOCK_DATABASE_ENGINE | database ≠ none | auto | The engine, e.g. postgres. |
ASTRODOCK_STORAGE_ENDPOINT | storage ≠ none | auto / user-required | S3 endpoint URL. |
ASTRODOCK_STORAGE_REGION | storage ≠ none | auto / user-required | S3 region. |
ASTRODOCK_STORAGE_BUCKET | storage ≠ none | auto / user-required | Bucket name. |
ASTRODOCK_STORAGE_PREFIX | storage = internal | auto | App's key prefix within the shared bucket. |
ASTRODOCK_STORAGE_ACCESS_KEY | storage ≠ none | auto / user-required | S3 access key. |
ASTRODOCK_STORAGE_SECRET_KEY | storage ≠ none | auto / user-required | S3 secret key. |
ASTRODOCK_AUTH_URL | auth = platform | auto | Control-plane /verify base URL. |
ASTRODOCK_APP_ID | auth = platform | auto | App ID for /verify (equals the slug). |
ASTRODOCK_APP_SECRET | auth = platform | auto | App secret for /verify. |
ASTRODOCK_APP_JWT_SECRET | auth = platform | auto | Secret the app uses to sign its own sessions. |
The PORT alias
Because process.env.PORT is near-universal in Node hosting, the platform also exports
PORT set to the same value as ASTRODOCK_PORT. This is the single documented
unprefixed exception. Prefer ASTRODOCK_PORT in your own code.
One name, internal or external
ASTRODOCK_DATABASE_URL and the ASTRODOCK_STORAGE_* set use the same names
whether the resource is internal or external. Your app reads one variable and never knows the
difference — moving from the bundled store to a hosted one is a value change, not a code change.
App-declared env[] entries
Each entry in the env array declares one of your variables — its name and
metadata only, never its value. Secret values are set out-of-band with
astrodock set-secret or in the dashboard.
| Property | Type | Req | Default | Meaning |
|---|---|---|---|---|
key | string | yes | — | Variable name. Must match ^[A-Z][A-Z0-9_]*$ (UPPER_SNAKE_CASE) and must not start with ASTRODOCK_. |
secret | boolean | no | false | If true, the value is write-only — masked in the UI/API, set via set-secret, never stored in the manifest. |
required | boolean | no | false | If true, a deploy is blocked until a value exists (the required-variable gate). |
default | string | no | — | Non-secret default, applied if the operator sets nothing. Not allowed when secret: true. |
description | string | no | — | Shown in the dashboard and to coding agents. |
Example — one required secret and one optional value with a default:
"env": [
{ "key": "OPENAI_API_KEY", "secret": true, "required": true,
"description": "Used to draft line items" },
{ "key": "INVOICE_PREFIX", "secret": false, "required": false,
"default": "INV-", "description": "Prefix for invoice numbers" }
]
Two rules the schema enforces
A declared key may never start with ASTRODOCK_ (that prefix is reserved),
and default may not be combined with secret: true (a secret has no
plaintext default in the manifest).
Setting values
app.json declares variable names; you supply values separately so
nothing secret ever lands in git:
# reads the value from stdin — never stored in shell history or the repo
astrodock set-secret OPENAI_API_KEY
astrodock set-secret ASTRODOCK_DATABASE_URL # external-mode credentials, same command
Non-secret values with a default need nothing set. Required values without a default
block the deploy until you set them — see the required-variable
gate.
Related
- App structure & app.json — the how-and-why behind these fields.
- The deploy lifecycle — when these variables are read and gated.
- Dockerfile apps — the same env, injected into a container.
- External database · External storage