seekrit

Self-hosted provisioner

Temporary-access targets choose where provisioning runs via the executor. By default (in_do) the seekrit broker decrypts your database admin credential transiently to run CREATE ROLE / DROP USER itself. The remote executor moves that work into your network: the broker signs each command and sends it to a seekrit-provisioner daemon you run, which holds the admin credential locally. seekrit orchestrates but never sees it — pure zero-knowledge even for provisioning.

note

The remote executor is for the Postgres and MySQL/MariaDB providers. SSH certificate signing is in_do-only for now.

How it works

The broker holds only a shared HMAC key (wrapped to its per-org keypair, like any admin secret). Your database admin credential lives only on the daemon. Every command the broker sends is signed HMAC-SHA256; the daemon verifies the signature, rejects stale or replayed commands, and runs the already-rendered SQL.

 broker (seekrit)                         your network
 ────────────────                         ────────────
 signs ProvisionCommand ──── POST ───▶ seekrit-provisioner ──▶ Postgres / MySQL
 (HMAC, shared key)                    verify sig · freshness ·
                                       replay · run SQL as admin

The credential you hand a consumer stays zero-knowledge as always — the consumer generates it and sends only a verifier. The daemon only ever handles the admin credential, which now never leaves your network.

1. Mint the shared key

seekrit provisioner keygen
# → a base64 key on stdout. Keep it secret.

Use the same value in both places below: --hmac-key when you register the target, and SEEKRIT_PROVISIONER_HMAC_KEY on the daemon.

2. Register a remote target

The admin connection string does not go to seekrit here — only the HMAC key is wrapped and uploaded. Point --provisioner-url at where the daemon will listen.

KEY=$(seekrit provisioner keygen)

seekrit pg target add \
  --name prod-db --host db.internal --database app \
  --access readonly \
  --executor remote \
  --provisioner-url https://provisioner.internal:8088/ \
  --hmac-key "$KEY"

seekrit mysql target add takes the same --executor remote --provisioner-url --hmac-key flags. For the readonly / readwrite presets, run the one-time group-role setup SQL the command prints (Postgres) as a database admin.

3. Run the daemon

Run it where it can reach the database, holding the same key plus the real admin connection string:

docker run -d --name seekrit-provisioner -p 8088:8088 \
  -e SEEKRIT_PROVISIONER_HMAC_KEY="$KEY" \
  -e SEEKRIT_PROVISIONER_DATABASE_URL="postgres://admin:secret@db.internal:5432/app" \
  seekritdev/provisioner:latest

Prebuilt multi-arch images (amd64 + arm64) are published to Docker Hub as seekritdev/provisioner — pin a release tag (e.g. :0.1.0) or :edge for the latest main. The image is a single static binary on scratch — no OS, no shell. GET /healthz returns {"ok":true} for liveness probes.

Environment

VariableRequiredDefaultPurpose
SEEKRIT_PROVISIONER_HMAC_KEYyesBase64 shared key; must match the target's --hmac-key.
SEEKRIT_PROVISIONER_DATABASE_URLyesAdmin postgres://… or mysql://… string. Held only here.
SEEKRIT_PROVISIONER_PROVIDERnoinferred from URLpostgres or mysql, if ambiguous.
SEEKRIT_PROVISIONER_DB_TLSnorequirerequire or disable (local/plaintext DB).
SEEKRIT_PROVISIONER_ADDRno0.0.0.0:8088Listen address.
SEEKRIT_PROVISIONER_MAX_SKEW_SECSno300Freshness window (and replay-cache TTL).

Lease as usual

Nothing changes for the consumer. seekrit pg lease prod-db mints a credential exactly as with the in-DO executor — the difference is entirely in where the CREATE ROLE ran.

caution

The HMAC authenticates and integrity-protects every command regardless of transport, so plain HTTP behind your own ingress is safe. Still, front the daemon with TLS if it is reachable beyond localhost, so command contents stay confidential in transit. The daemon holds a privileged database credential — keep it on a private network and scope that credential to only what provisioning needs.

Security properties

  • Authenticity — a missing or bad signature is rejected (401) before any database work; verification is constant-time.
  • Anti-replay — commands outside a ±5-minute window are rejected (400), and each nonce is single-use within that window.
  • Least exposure — the daemon runs only the SQL the broker rendered, returns no query results, and never logs the admin URL, the key, or the statements.