Skip to content

Secrets and Keychain

Hostwright supports a typed manifest secret-reference model. The manifest stores a reference, never a secret value:

services:
api:
image: ghcr.io/example/api@sha256:...
secretEnv:
API_TOKEN: keychain://hostwright.api/api-token

A keychain:// reference in hostwright.yaml resolves against the macOS Keychain only at confirmed execution, and the resolved value is never persisted.

Rules enforced by validation:

  • Plaintext sensitive keys under env fail validation.
  • secretEnv values must use one of five typed schemes (below).
  • The same key cannot appear in both env and secretEnv.

secretEnv accepts:

  • keychain://<service>/<account>: a Hostwright-owned Keychain item, managed with hostwright secret;
  • env-file:///absolute/path#KEY: one key from a guarded local env file;
  • local-file:///absolute/path: the whole contents of a guarded local file;
  • external://<provider>/<item> and plugin://<provider>/<item>: an explicitly registered external or plugin provider.

Planning, status, state persistence, diagnostics, events, and errors see only redacted secret-reference metadata. A confirmed lifecycle command resolves references once, immediately before the create step, for the exact project/service/key combination. If the configured backend cannot resolve a reference, the command fails before mutation.

Hostwright also redacts reference labels themselves, because a service or account name can reveal local context, so a reference never appears in plans, state rows, diagnostics bundles, or error messages. Only the resolved value reaches the runtime, and only at the boundary that needs it.

Terminal window
hostwright secret create keychain://hostwright.api/api-token
hostwright secret update keychain://hostwright.api/api-token
hostwright secret list
hostwright secret check keychain://hostwright.api/api-token
hostwright secret delete keychain://hostwright.api/api-token

create and update read the value from stdin or an attended no-echo terminal; a secret value is never accepted as a command argument. list and check return metadata only, never a value. delete verifies exact ownership and item identity before removal. Every mutation persists a redacted intent record before touching the Keychain, so an interrupted operation is inspectable with hostwright recovery and, for an exactly verified create, reversible through the same command.

The underlying macOS Keychain backend queries an exact service/account pair only, excludes synchronizable (iCloud-synced) items, and disables authentication UI so CLI processes run without a Keychain prompt.

Rejected The following are rejected:

  • plaintext secret persistence in state, events, or diagnostics;
  • Keychain access groups or synchronizable (iCloud-synced) items;
  • cloud secret managers or registry credential storage outside the documented registry login Keychain item and the five secretEnv schemes above;
  • mounted secret files or multiline/binary secret payloads beyond what env-file:// and local-file:// already cover;
  • Compose/Kubernetes secrets: compatibility.

See State store for the persistence boundary and Security and safety for the wider posture.