Environments & groups
Most apps share the bulk of their configuration. seekrit models this with groups: reusable secret bags that application environments compose. An application environment is then just its own secrets + the groups it pulls in, resolved and layered at runtime.
The model
- A group is an org-scoped secret bag with its own environments, keyed by
slug (
dev,staging,production,sandbox, …). - An application environment composes one or more groups. At resolve time each group is matched to the environment whose slug matches the app environment's.
- Values layer, lowest precedence first:
group secrets < app-env secrets < .env file < process env (highest wins)
So a shared DATABASE_URL in a group is overridden by the app's own value,
which is overridden by a local .env, which is overridden by an exported shell
variable.
Setting it up
Say an api and a worker share ~80% of their config. Put the shared values in
a group and compose it into each app's environments.
# 1. A shared group with a per-environment value set
seekrit group create --name "Common backend" --slug common
seekrit group env create --group common --name Production --slug production
seekrit secrets set DATABASE_URL 'postgres://…' --group common --env production
# 2. Compose it into each app environment
seekrit env groups add --app api --env production --group common
seekrit env groups add --app worker --env production --group common
# 3. App-specific secrets live on the app environment
seekrit secrets set QUEUE_NAME jobs --app worker --env production
Now worker/production resolves to common@production overlaid with
worker/production's own keys. Composing more than one group? Precedence follows
--position (higher wins); pass it on env groups add.
Local .env and process env
seekrit run auto-loads .env from the working directory and overlays it above
the managed layers, and the live shell overrides everything. This makes seekrit
the single way your app gets its environment while still letting you tweak
individual values locally.
echo 'VITE_CLIENT_BASE_URL=http://localhost:5173' > .env
SEEKRIT_TOKEN=skt_… seekrit run -- pnpm dev # .env wins over managed secrets
Point at other files with --env-file (repeatable; later files win), and see
exactly where each value came from with --explain:
seekrit run --env-file .env --env-file .env.local --explain -- pnpm dev
Swapping one group per boot
Group environments double as variants. To boot with a different slice of a
single group — say staging auth keys — while keeping everything else at dev,
override just that group:
seekrit run --with auth-providers=staging -- pnpm dev
Everything else resolves at the app environment's slug; only auth-providers
switches to its staging slice. Overrides are fail-closed: you can only pull a
slice you hold a key grant for. As a logged-in developer you hold them all; for a
service token, pre-authorize alternate slices at creation with
token create … --allow auth-providers=staging.
Committing a config file no longer pins an environment. seekrit.json names
only org + app; the environment is selected by the service token (or --env).