seekrit
Docs/Rotate secrets on a schedule

Rotate secrets on a schedule

This guide is the how-to; see Secret rotation for how it works and what trust boundary it involves. Rotation is admin-managed and configured per secret. The step that makes it possible — wrapping the environment's data key to your organization's rotator key — happens in your browser or CLI, never on a server.

1. Pick what to rotate

You want to rotateKindYou also need
A value only your own code checks (API key, webhook secret)generatednothing
An existing Postgres role's passwordpostgresa registered Postgres target
An existing MySQL/MariaDB account's passwordmysqla registered MySQL target
An existing Redis ACL user's passwordredisa registered Redis target

The secret must already exist — rotation replaces a value, it doesn't create one. For the database kinds you need a target registered for temporary access; rotation reuses the same connection details and admin credential:

seekrit pg target add --name prod-db --host db.example.com --database app \
  --admin-url "postgres://admin:…@db.example.com:5432/app"

2. Enable rotation

With the CLI — a generated value, rotated every 30 days:

seekrit rotation enable API_SIGNING_KEY --app web --env production \
  --kind generated --every 30d --now

An existing Postgres role, re-keyed weekly:

seekrit rotation enable DATABASE_PASSWORD --app web --env production \
  --kind postgres --target prod-db --username app_user --every 7d --now

--now rotates immediately as well as on the schedule, which is the fastest way to confirm the target and account name are right — a misconfigured policy fails loudly here instead of quietly in an email tomorrow.

In the web dashboard: open the environment → Rotationconfigure rotation, pick the secret, the kind, and a cadence. For a database kind, pick the target and type the account name.

The first time you enable rotation in an environment, your client unwraps that environment's data key and re-wraps it to the rotator key. That is the grant the broker needs to write a new value — you will be asked to unlock if your key is locked. A second rotating secret in the same environment needs no key access at all.

note

--username names an account that already exists. Rotation changes its password in place; it never creates or drops the account, so grants and ownership survive. Make sure your registered target's admin credential can ALTER that account.

3. Live with it

seekrit rotation list                     # every policy: cadence, status, next run
seekrit rotation show DATABASE_PASSWORD   # one policy in full, including the last failure
seekrit rotation rotate DATABASE_PASSWORD # rotate now (e.g. after a suspected exposure)

Consumers need no changes — the next resolve returns the new value:

seekrit run --app web --env production -- ./server

Every rotation appends a secret version, so seekrit secrets get DATABASE_PASSWORD always decrypts the current one, and the version history shows which versions rotation produced.

4. Pause, fix, resume

If a rotation fails — the database is unreachable, the account was renamed, the admin credential lost its privileges — seekrit records the error, emails your admins, and retries with a backoff. After five consecutive failures the policy stops retrying and shows as failed.

seekrit rotation show DATABASE_PASSWORD   # `lastError` says what went wrong
seekrit rotation pause DATABASE_PASSWORD  # stop rotating while you work on it
seekrit rotation resume DATABASE_PASSWORD # resume, clearing the failure streak
seekrit rotation set-interval DATABASE_PASSWORD --every 30d

The dashboard's rotation card shows the same state inline, with the last error and per-policy rotate / pause / disable controls.

caution

A rotation re-keys your database before it stores the new value. If the write-back fails in between, consumers hold a password that no longer works until the retry succeeds — seekrit emails you and retries with a fresh value automatically. Pick a cadence your deployment can absorb, and make sure your apps can re-resolve (or be restarted) after a rotation rather than caching a credential for their whole lifetime.

Turning it off

seekrit rotation disable DATABASE_PASSWORD

The secret and every version it has are untouched — only the schedule goes away. When the last policy in an environment is disabled, the rotator's key grant is dropped too, so seekrit's ability to decrypt that environment ends with the feature. Every action here is written to the audit log (secret.rotation_configured, secret.rotated, secret.rotation_failed, secret.rotation_disabled).