A single master key seals every secret the platform holds. Replacing it cannot be an edit to one environment variable — that would strand everything already sealed under the old value. Rotation is the mechanism that changes the key without an outage, and this page is about what it is and what an operator takes on. The step-by-step for an incident lives in the operations runbook, not here; if this page and that one ever say the same thing, one of them is wrong.
A ring, not a key#
The platform reads its key from a ring, not a single variable. Most of the
time the ring holds one key, COOLMS_SECRET_MASTER_KEY. During a rotation it
holds two: the new key as current, and the old key as previous
(COOLMS_SECRET_MASTER_KEY_PREVIOUS), set only for the length of the rotation.
That second slot is the whole reason rotation does not require an outage. While both keys are present, new values seal under the current key and old values still open under the previous one, so the system keeps working with a mix of the two. A malformed previous key is refused by name rather than ignored, because a mistyped key that was silently dropped would leave old values unreadable with no signal.
What rotating does#
The work is to re-seal everything under the new key. The command walks every kind a module registered (the six on the Secrets page, and any a module adds), opens each value, and re-seals the ones still under the previous key. A sealed value's marker names its form, not its key, so only opening it can say which key it is under — which is why this is a read of every value, not a lookup.
It reports three numbers per kind: how many are under the current key, under the previous key, and under neither. The rotation is closed when every kind reports zero under the previous key — and that is a measurement the command makes, not a judgement the operator makes: the exit status says closed or open, so it can gate a script rather than needing someone to read a report and decide. It is idempotent and resumable — a value already under the current key is skipped, so a second run re-seals nothing and an interrupted run is finished by running it again.
What an operator is signing up for#
Three things about the shape of a rotation, which the runbook then turns into steps:
- A window with two keys live. For the length of the rotation both keys are in the environment. The rotation is not done when the command is run once; it is done when it reports zero under the previous key across every kind, which on a fleet may take more than one host and more than one run.
- Retiring the old key is a separate decision — in fact two. The command never removes the previous key. Taking it out of the running environment is one act; taking it out of the vault is another, and it waits on which backups must still be restorable, because a backup taken before the rotation only opens under the old key. Rotation gets you to zero-under-previous; what happens to the old key after that is the operator's call, made twice.
- A value under neither key cannot be repaired by rotating. If a value opens under no held key, the command reports it and leaves it — rotation re-seals what it can read, and cannot recover what no key opens. That is a restore problem or a data problem, surfaced, not silently carried.
Status, honestly#
The key ring and sealing ship today. The coolms:secret:rotate command that
performs the walk is built but has not yet shipped in a release — it is on
the development branch and lands in a later one. The operations runbook for
rotation is written ahead of it. Until the command is in the release you run,
this page describes a mechanism the platform is designed around rather than one
you can invoke; that is marked here rather than left for you to discover at the
prompt.