seekrit
Docs/Northflank

Sync to Northflank

Northflank injects a secret group's values into the services and jobs that inherit it, at deploy time. A binding writes one secret group — the platform's unit of injection.

At a glance
What seekrit writesA secret group's variables map
Addressed byProject slug + secret group slug
Connection carriesThe token alone — a Northflank token names its own team
Token permissionAn API role granting Secrets → Secret Groups: read and update on the project
Takes effectNext deploy, or restart dependents on the group's page
Value visibilityReadable by anyone with access to the project's secret groups

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 API token

In Northflank, go to Team settings → API tokens and create one with a role granting Secrets → Secret Groups read and update on the project you are syncing into. Read is not optional here — see why this connector reads first.

A Northflank token is issued by exactly one team and carries that scope itself, so a Northflank connection has nothing else to configure:

printf '%s' "$NORTHFLANK_API_TOKEN" | seekrit sync connect \
  --name acme-northflank --provider northflank

2. Bind an environment

A binding writes one secret group, which the project's services and jobs inherit. Create the group in Northflank first (Project → Secrets → Create secret group), then name it and its project by the slug in their URLs, not by their display names:

seekrit sync verify acme-northflank --provider northflank \
  --project default-project --secret-group app-secrets

seekrit sync enable --connection acme-northflank --provider northflank \
  --project default-project --secret-group app-secrets \
  --app storefront --env production --acknowledge-decryption

seekrit checks both against Northflank's own slug pattern before storing them, so the common slip — pasting the display name, spaces and all — fails at the form rather than as a bare 404 inside a run nobody is watching.

Verify walks the project's secret-group metadata (names and ids, never values) to confirm the group exists and the token can see it.

There is no environment field. Northflank has no per-group environment axis — separate environments are separate projects, or separate groups restricted to a stage — so a seekrit environment maps to a group, one to one.

seekrit writes only the group's variables. Its priority, restrictions, secret type, secret files, and linked addons are yours: a push leaves them exactly as you configured them.

note

Northflank injects a secret group's values at deploy time. A synced change reaches a running service on its next deploy, or when you use restart dependents on the group's page. seekrit does not restart anything on your behalf.

Why a push reads the group first

Northflank's variables map is replace-semantics: PATCH with secrets.variables sets the group's map to exactly what was sent, so a key absent from the payload is deleted. There is no per-variable endpoint and no merge flag — the whole map is the unit of writing.

So a run reads the group's current variables and writes back (existing − removed) ∪ seekrit. Sending only seekrit's names would be one request instead of two, and would silently delete every variable in the group that seekrit does not manage — a hand-added LOG_LEVEL, another team's key. A secrets manager may fail a push; it may not quietly destroy the values beside it.

caution

That read is the one place a connector sees plaintext seekrit did not already hold, so it is worth being precise about what it costs. The read uses show=this, which excludes secrets inherited from linked addons — database credentials and the like — so only the group's own variables are read. In the recommended setup, a group dedicated to this binding, every value read is one seekrit just decrypted anyway.

The read only sees foreign values in exactly the case where not reading would destroy them, and they are used for one thing: writing them straight back, unchanged. Nothing is cached, logged, audited, or kept past the run.

Give a binding a secret group of its own and this never arises — everything in it came from seekrit to begin with.

Troubleshooting

SymptomCauseFix
401 or 403, whole run stoppedThe token was revoked, or its role lacks Secret Groups read or update on this projectBoth permissions are required — the read is not optional, see above
404 on the group, whole run stoppedThe group doesn't exist, or the slug is wrongCreate it in Northflank first; seekrit will not. Take both slugs from the resource URL
A slug is rejected when enablingA display name was pasted instead of the URL slugSlugs are lowercase, hyphen-separated, with no spaces
A hand-added variable disappearedSomething wrote the group's map without mergingseekrit always merges. Check for another tool, or a PATCH from your own automation
Values pushed, service unchangedNorthflank injects at deploy timeDeploy, or use restart dependents on the group
Run reported partial, 429 in the errorNorthflank rate-limited the tokenNothing to do — seekrit honors Retry-After and retries

See also