Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.slipway.sh/llms.txt

Use this file to discover all available pages before exploring further.

Secrets are encrypted-at-rest key/value pairs that resolve into your services.*.env and services.*.build.args values at deploy time. Use them for anything you wouldn’t paste into a public Slack channel: API tokens, database URLs, signing keys. For non-sensitive config like log levels or feature flags, use Variables instead — they’re cheaper to manage and visible in the UI.

Two scopes

  • Repository secrets/{slug}/repos/{id}/secrets. Scoped to one repo.
  • Organization secrets/{slug}/settings/secrets. Shared across every repo in the org.
The same name can exist in both stores. Bare ${secret.NAME} references prefer the repo store with org fallback; explicit ${secret.repo.NAME} / ${secret.org.NAME} are strict.

Creating a secret

Both UIs work the same way:
  1. Click Add secret.
  2. Enter the name (^[A-Z][A-Z0-9_]*$).
  3. Paste the value.
  4. Save.
Values are AES-256-GCM encrypted with a per-row data-encryption key, which is itself wrapped by the configured Key-Encryption-Key provider (env-derived for self-hosted dev clusters, AWS KMS in production). After save, the value is never returned by the API or shown in the UI again. You can update it (which generates a new ciphertext under a fresh DEK) or delete it. To rotate, update.

How secrets reach your container

When a deploy starts:
  1. slipway parses the spec and collects every ${secret.*} reference.
  2. For each reference, it looks up the row in the configured scope and decrypts the value.
  3. Resolved values are written to a per-deployment Kubernetes Secret (sl-env-<dep-id>-<service>) in the tenant namespace.
  4. The pod spec consumes that secret via envFrom: secretRef. Values never appear in the Deployment object, the pod spec JSON, or etcd’s plaintext.
For build.args, the same flow lands in sl-buildargs-<dep-id>-<service> in the build namespace. The buildctl invocation expands them via the shell, never via container args.
Bare ${UPPERCASE} is deprecated. It still works (aliased to ${secret.UPPERCASE}) and emits a warning at deploy time. Migrate to the explicit form before the next minor release.

What slipway logs about secrets

Every deploy emits a secrets_resolved event with the resolved set: [{name, scope, source}, ...]. Never values. The event log shows you that DATABASE_URL was resolved from the repo store, which is useful for debugging precedence issues without leaking the value. If a referenced secret doesn’t exist, the deploy fails at this phase with a clear error, before any tenant pod starts.

Permissions

RoleRead namesRead valuesCreate / update / delete
Vieweryesnono
Developeryesnoyes
Adminyesnoyes
Owneryesnoyes
No role can read a secret’s value through the UI or API — values are write-only after creation. Roles that can edit can also rotate (overwrite).