Enrollment Secrets
Enrollment Secrets
Admin only. This panel is hidden from non-admin operators. If the tab isn’t visible in your Settings nav, your account doesn’t have the Admin role.
An enrollment secret is a shared password that a fresh Mimir agent presents to the server on first contact — the credential that says “I’m allowed to join this fleet.” The server checks the secret, optionally consumes one slot against a usage cap, and either accepts the agent into the fleet or rejects the enrollment attempt.
Once an agent is enrolled, it stops using the secret. Subsequent communication uses the agent’s own client certificate (issued at enrollment time), so revoking the secret has no effect on already-enrolled agents — it only prevents new agents from joining with that value. This makes it safe to rotate secrets aggressively: a leaked secret stops being useful the moment you revoke it without disrupting the existing fleet.
What you get
Three surfaces on the panel, top to bottom:
- Reveal card — appears at the top only after you create a new
secret. Shows the plaintext value with a green border and a
one-shot Copy to clipboard button. The card explicitly warns
“Secret created for
<name>. Copy it now — it will not be shown again.” - Active secrets — a table of every secret that’s currently
usable for new enrollments. Four columns:
- Name — the label you gave the secret at creation.
- Created — when it was minted, in your Time & Display format.
- Uses — for capped secrets,
consumed / max(e.g.12 / 50). For uncapped secrets, the bare count (12) orNone yetfor a fresh row. - Revoke — a destructive button on the right.
- Revoked secrets — a muted table below the active one, only visible if there’s at least one revoked row. Same columns minus Revoke; the Uses column shows the final lifetime count.
- Generate secret form — at the very bottom. Two fields and a
button:
- Secret name — free text, required. Suggested patterns:
datacenter-east,corp-laptops-2026Q2,provisioner-bootstrap. - Max uses — optional integer. Leave blank to make the secret
uncapped (any number of agents can enroll until you revoke it).
Type a positive integer to cap it. Once the cap is reached, the
server stops accepting new enrollments with this secret, but
the row stays in the Active secrets table marked
N / N— you still have to click Revoke manually to move it to the Revoked table. - Generate secret — submits the form.
- Secret name — free text, required. Suggested patterns:
How to mint a secret
- Open Settings → Enrollment.
- Type a memorable Secret name. The name shows up in the active/revoked tables, in your audit logs, and is the only context anyone (including you, six months from now) will have to recognize what this secret is for.
- Optionally type a Max uses cap. Common patterns:
- Provisioning a known number of machines? Cap at that number
plus a small margin (
50if you’re rolling out 47 laptops). Once the cap is hit, the secret stops accepting new enrollments — closing the window against any leak. Remember to click Revoke when you’re done; the row stays Active at50 / 50until you do. - Continuous provisioning (a new VM image bakes in the secret, fleet grows over time)? Leave blank.
- Bootstrapping a single specific host? Cap at
1.
- Provisioning a known number of machines? Cap at that number
plus a small margin (
- Click Generate secret. The green reveal card appears at the top of the panel.
- Click Copy to clipboard. Paste the value into your
provisioning system (Ansible Vault, Terraform variable,
mimir-launcher install --enrollment-secret=…invocation, etc.). - Click the ✕ on the reveal card when you’re done — or leave it open until you navigate away. Once the card is gone, the plaintext is unrecoverable.
A toast confirms Enrollment secret created and the new row appears
in Active secrets below. The Uses column on the fresh row
reads None yet (no agent has come in with it) or 0 / N if you
capped it.
How to revoke a secret
-
Find the row in Active secrets.
-
Click the red Revoke button on the right.
-
Confirm in the modal:
Revoke “datacenter-east”? No new agents will be able to enroll using this secret. Already-enrolled agents are unaffected.
-
Click Revoke.
The row moves to the Revoked secrets table below and is no longer accepted at the enrollment endpoint. Already-enrolled agents keep working — their authentication is now based on their own client certificate, not the secret they originally presented.
There’s no “un-revoke” or “resume”. If you revoked the wrong row, mint a new secret with the same name (Mimir allows duplicate names — the row id is what’s unique) and re-provision.
Choosing a max-uses cap
The cap is a blast-radius limit on leaks, not a security boundary in itself.
- Uncapped — operationally easiest, highest blast radius. A leaked uncapped secret remains useful to an attacker until someone notices and revokes it. Use for continuous-provisioning workflows where the convenience of “the image always has the same secret” outweighs the risk, paired with monitoring on the enrollment endpoint.
- Cap = exact rollout size — stops accepting new enrollments on the last legitimate agent’s success. Mathematically the safest pattern but brittle — if one machine fails to enroll on the first try and retries from scratch, you’ve consumed two slots for one host.
- Cap = rollout size + small margin — the typical compromise.
expected_hosts + 5gives operational slack while still bounding leaks. - Cap = 1 — for one-off bootstrapping. Mint, install, and the secret stops accepting new enrollments after the first success.
Once the cap is reached, the row stays in Active secrets marked
N / N. The next enrollment attempt is filtered out before the
secret is even checked — the agent sees a generic unauthorized
response, not a “you exhausted me” signal — so audit logs and
agent logs both look like a wrong-secret attempt. To actually move
the row to the Revoked secrets table (and make the audit story
clean), click Revoke manually.
Where the secret travels
The secret leaves Mimir three ways:
- Manually, when you copy it from the reveal card into a provisioning system.
- In your agent installer’s configuration. Whatever bootstraps
the agent — your image bake, an Ansible role, a one-shot install
script — has to land the secret in a place
mimir-launcher/mimir-agentreads at startup. - Across the TCP+TLS connection to Mimir’s enrollment endpoint when an agent presents it. The server hashes it on receipt; the plaintext is never written to disk server-side.
The reveal card is the only place the plaintext exists inside Mimir. The database stores a hash; even an admin with direct SQL access cannot recover the plaintext from a stored row.
Troubleshooting
The reveal card disappeared before I copied the secret. It only goes away when you click ✕, navigate elsewhere, or refresh — no auto-dismiss. If you missed it, the secret is in the database but unrecoverable. Click Revoke on the row and mint a new one.
Failed to create enrollment secret. Almost always a
non-positive Max uses value — the form’s number input accepts 0
or negative values but the server rejects them. Use a positive
integer or leave it blank.
An agent reports unauthorized at enrollment. Three causes,
in order of frequency:
- The secret was revoked between when you copied it and when the agent tried to enroll. Check the Revoked secrets table.
- The secret was capped and the cap is exhausted. Mimir
pre-filters exhausted rows before the bcrypt check, so the
agent’s
unauthorizedis indistinguishable from a wrong-secret response on the wire — check the Uses column in the Active secrets table;N / Nmeans the cap is full. (A rarer race-loss case during a burst of concurrent enrollments surfaces assecret_exhaustedHTTP 403 on the agent log; that path only fires for the request that lost the atomic UPDATE.) - The secret was copied incorrectly — an extra trailing newline or whitespace from a clipboard manager will fail verification. Recopy from the reveal card if it’s still open, or mint a new secret and re-provision.
An agent enrolled but doesn’t appear on the Hosts page. Two possibilities. Either the host hasn’t reported its first heartbeat yet (give it a minute), or enrollment succeeded but the agent’s subsequent heartbeats are being rejected (check the server log for client-cert errors — that’s a different failure mode than the secret).
The Uses column reads None yet after a successful enrollment.
Refresh the page. The panel loads once on entry and doesn’t poll;
new enrollment counts only show up on the next fetch.
See also
- Settings → Users — for human access to Mimir. Enrollment secrets are for agents; the two credential systems don’t overlap.
- Your operator runbook for the full agent-installation procedure
(which side of
mimir-launcher install --enrollment-secret=…to put the value on, what file the launcher reads at startup, etc.). The runbook lives outside the public docs.