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 rotate | Kind | You also need |
|---|---|---|
| A value only your own code checks (API key, webhook secret) | generated | nothing |
| An existing Postgres role's password | postgres | a registered Postgres target |
| An existing MySQL/MariaDB account's password | mysql | a registered MySQL target |
| An existing Redis ACL user's password | redis | a 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 → Rotation → configure 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.
--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.
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).