Skip to main content
Your spec references values with ${...}; slipway resolves them at deploy time. There are two stores:
  • Secrets — encrypted at rest. Slipway never returns a secret value after you create it; it only appears inside your running container. Use them for API tokens, database URLs, signing keys.
  • Variables — plaintext. Visible to anyone with viewer role or above. Use them for log levels, feature flags, registry hosts, build identifiers.
A missing reference fails the deploy before any container starts.

Scopes

Both stores have two scopes:
ScopeWhere you set itStrict reference
EnvironmentAn environment’s settings (or the composer’s Variables & Secrets step)${secret.env.NAME} / ${var.env.NAME}
OrganizationSettings → Secrets / Settings → Variables${secret.org.NAME} / ${var.org.NAME}
The bare shorthand — ${secret.NAME} / ${var.NAME} — resolves environment → org, first match wins. Use the shorthand when you want fallback; use the explicit env / org form when you want a strict lookup that never falls through. Environment values are defined once on the environment and apply to every deployment of it — the permanent instance, PR previews, and manual/dev instances all resolve the environment’s current values on each deploy. There are no per-instance overrides: editing variables & secrets from an instance’s settings edits the environment’s, and every deployment picks them up on its next redeploy (see the Stale chip).

Substitution syntax

services:
  api:
    build:
      args:
        NPM_TOKEN: ${secret.NPM_TOKEN}        # secret in build.args
        REGISTRY:  ${var.org.REGISTRY}        # explicit org variable
    env:
      DATABASE_URL: ${secret.DATABASE_URL}     # env first, org fallback
      STRIPE_KEY:   ${secret.env.STRIPE_KEY}   # env only — strict
      DATADOG_KEY:  ${secret.org.DATADOG_KEY}  # org only — strict
      LOG_LEVEL:    ${var.LOG_LEVEL}           # variable, env first, org fallback
FormResolves to
${secret.NAME} / ${var.NAME}env store first, org store as fallback
${secret.env.NAME} / ${var.env.NAME}environment store only — fails if missing
${secret.org.NAME} / ${var.org.NAME}org store only — fails if missing
${service.<name>.<field>}a sibling service’s URL / host / port — see composition
Names match ^[A-Z][A-Z0-9_]*$.

Hardcoded values are authoritative

A key with a plain literal value in the spec (NODE_ENV: production, PGHOST: postgres) — or a computed ${service.X} value — isn’t a reference. The spec value is what deploys, always. A variable or secret of the same name never overrides it, so the running config can’t silently drift from what the repo says. To let a value vary per environment, make it a reference instead of a literal:
env:
  NODE_ENV: ${var.NODE_ENV}   # now set per-environment (or org-wide) in the stores
That’s the single, explicit way to say “this is overridable.” The environment composer lists every hardcoded/computed key read-only under Defined in spec so you can see what the spec already handles, but there’s nothing to set there.

How values reach your container

Resolved env values are injected into your container’s environment at startup. They never appear in the pod definition, the deployment row, or anywhere a viewer would see them. Resolved build.args are passed to the build as build arguments only, never on the build command line.
A build.args value your Dockerfile then writes to disk (e.g. RUN echo $TOKEN > /etc/secret) gets baked into the image layer. Slipway can’t prevent that — keep credentials out of build args unless your Dockerfile consumes them in the same RUN step.

Setting values

Manage org-wide values under Settings → Secrets and Settings → Variables. Manage environment-scoped values on the environment’s settings or in its composer. To add one: click Add in the top right, give it an uppercase name and a value, and save. A secret’s value is masked and can’t be read back — to rotate, update it.
Org secrets page

The Secrets Manager

A repo’s Spec tab has a Secrets Manager below the rendered spec. It reads your effective spec the way a deploy does, lists every ${secret.*} / ${var.*} it references, and shows each as set (with the scope it resolves from) or missing. Click Set on any row to provide the value inline — handy for getting a new repo fully configured before its first deploy.

Per-service provenance

An environment’s Components tab is the read-only companion. Expand a service’s env to see every variable it receives, each tagged with where it resolves from — spec for a hardcoded literal, env for an environment value, org for an org value — plus an unset flag for any reference nothing satisfies yet. Secret values stay masked; variable and literal values are shown inline. Use the edit links to jump to the environment or org stores when a value needs changing.

What’s logged

Every deploy records what it resolved:
  • secrets_resolved lists {name, scope, source} per reference — never values.
  • vars_resolved lists {name, scope, source, value} — values included, because variables aren’t secret.
If you want a value kept out of the event log, make it a secret.

Permissions

RoleRead secret namesRead secret valuesRead variablesCreate / edit / delete
Vieweryesnoyesno
Developer / Admin / Owneryesnoyesyes
No role can read a secret’s value once it’s set — secrets are write-only after creation.