seekrit
Docs/Bunnyshell

Sync to Bunnyshell

Bunnyshell interpolates variables while it builds an environment, and hands the result to the containers it starts. A binding writes one of two collections: an environment's variables, or a project's — the latter reaching environments that do not exist yet.

At a glance
What seekrit writesAn environment's variables, or a project's
Addressed byA Bunnyshell environment ID or project ID
Connection carriesThe token alone — both IDs are globally unique
Token permissionA token whose user can change variables in the organization
Takes effectNext deployment of the environment
Value visibilityHidden in the dashboard when marked secret (the default); encrypted at rest either way

New to sync? Read Third-party sync first — the decryption grant, name mapping, deletions, and failure handling are the same on every destination.

1. Create an access token

Bunnyshell issues one at environments.bunnyshell.com/access-token — the same token bns configure saves. It carries its user's access to every organization they belong to, so the least-privilege setup is a machine user in only the organization it syncs.

There is no second half to state. A Bunnyshell connection carries nothing beyond the provider: both variable collections name their parent by a globally unique ID, so the token plus the destination is the whole address.

printf '%s' "$BUNNYSHELL_TOKEN" \
  | seekrit sync connect --name acme-bunnyshell --provider bunnyshell

2. Bind an environment

A binding writes one of two scopes. --bunnyshell-environment names an environment, whose variables every component in it inherits:

seekrit sync verify acme-bunnyshell --provider bunnyshell \
  --bunnyshell-environment env-9f3a2b

seekrit sync enable --connection acme-bunnyshell --provider bunnyshell \
  --bunnyshell-environment env-9f3a2b \
  --app storefront --env production --acknowledge-decryption

--project names a project instead, and is the one that reaches an environment which does not exist yet — every environment created in the project from then on inherits its variables, which is how you seed the ephemeral environments a webhook will spin up per branch or per pull request:

seekrit sync enable --connection acme-bunnyshell --provider bunnyshell \
  --project prj-4c8d1e \
  --app storefront --env preview --acknowledge-decryption

Pass one or the other, never both. Get either ID from bns environments list / bns projects list, or from the dashboard URL.

caution

A project binding's blast radius is the project, not one environment. Every environment created in it afterwards inherits these values, and there may be many. An existing environment is not touched — it keeps whatever it already has, and an environment-scoped value always beats the project's, so a project binding does not fight an environment binding pointed at the same name.

note

Values are marked secret. Bunnyshell's isSecret hides a value in the dashboard and keeps it encrypted inside an exported environment definition. seekrit sets it by default.

It is a weaker guarantee than Netlify's flag of the same name: Bunnyshell encrypts every variable with an organization key whether or not the flag is set, so this is about who can read it, not whether it is stored in the clear. The flag is only sent when seekrit creates a variable — an update never mentions it, so one you deliberately un-secreted stays that way. Pass --no-bunnyshell-secret to create dashboard-visible variables instead.

How a push behaves

  • There is no bulk write and no upsert here. A run pages through the collection to find which names already exist, then creates or updates each one individually. That makes Bunnyshell the destination where the per-run budget (400 requests) binds hardest.
  • A write is skipped when nothing would change. Bunnyshell's listing discloses current values, and seekrit uses that for exactly one thing — skipping a redundant write. Those values are never stored, logged, or audited.
  • Every variable's parent is re-checked before it is touched. Bunnyshell IDs are opaque strings with no documented format, so seekrit cannot validate them by shape the way it validates a Netlify site ID. Instead the connector confirms each listed variable really belongs to this binding's environment or project before editing it — a filter that failed to bite cannot turn into an edit of a neighbouring environment's variables. A create names its parent in the request body as a required relation, so an unresolvable ID is a 422 naming the field, not a write that lands somewhere broader.
  • A truncated listing fails the run loudly rather than making a deletion look already done.
  • A value Bunnyshell echoes back in an error is scrubbed before the reason is stored on the run row.

Bunnyshell interpolates variables while it builds, so a pushed value reaches the workload on the environment's next deployment. seekrit starts none: a secret rotation should not restart someone's environment as a side effect.

Name rules

note

Bunnyshell will not accept every name seekrit will. Variable names take letters, numbers, underscores, dashes, and dots, cannot begin with a digit, cannot begin with BNS_, which Bunnyshell reserves for the variables it injects itself, and must be at least 3 characters and at most 255. A name that breaks one of those is reported as a failure against that name alone; the rest of the environment still pushes. Watch for the length floor and the leading digit if you use a --prefix.

Troubleshooting

SymptomCauseFix
401 or 403, whole run stoppedThe token was revoked, or its user can't change variables in that organizationMint a new token from a user with the right role
422 naming environment or projectThe ID doesn't resolveCheck it against bns environments list / bns projects list. A create names its parent as a required relation, so this fails safely rather than writing elsewhere
Both scope flags rejected--bunnyshell-environment and --project were both passedA binding writes one collection; pass one
A new environment didn't get the valuesIt was created before the project binding, or the binding is environment-scopedProject variables are inherited at creation only. Bind the project, and existing environments keep what they have
A value looks wrong in an environmentAn environment-scoped value shadows the project'sThat is Bunnyshell's precedence. Remove the environment-level one
A variable is visible in the dashboardIt already existed when seekrit first wrote it — the secret flag is only sent at creationDelete it in Bunnyshell and let the next sync recreate it
One name failed, rest landedThe mapped name is under 3 characters, starts with a digit, or begins BNS_Fix the prefix or rename
Run reported partial on a big environmentThe 400-request budget, which binds hard hereNothing to do — the engine re-runs immediately until it drains

See also