Certificates
Every certificate mipo has installed, one row per generation (server-1, server-2, …), with the state the manager derived from the files on disk and the live bindings. Issuing and uploading only STAGE a certificate; activating one on the user-interface binding is a separate step that is verified against :443 and rolled back automatically if the new certificate is not actually served. The scanner ingress on :8443 follows the published anchor and is never changed from this page.
Inputs
| Name | Description | Allowed values | Default |
|---|---|---|---|
Certificate (.crt / .pem) | The full chain to upload: server certificate plus intermediates | PEM file | — |
Private key (.key / .pem) | The key matching the uploaded certificate. It is stored beside the generation and never returned | PEM file | — |
Name | How the uploaded certificate is listed | Text | Derived from the first hostname and the issuer |
Fields & columns
| Name | Description |
|---|---|
Generation | The on-disk generation: server-N.crt and server-N.key under the certificate directory |
Source | Let's Encrypt, Uploaded, or Self-signed — where the certificate came from |
In use by | Which bindings serve it: "UI :443", "Scanner ingress :8443", "Rollback target (UI)". Empty means it is serving nothing |
State | Active (served by a binding), Unavailable (its files are gone), Expired, Failed (a persisted check failed), Retired (served once, not any more), or Ready |
Checks | The persisted, host-independent verdict: passed, warning or failed. Live checks such as hostname coverage are re-run when you activate |
Last run | The issuance run that produced the certificate, and what triggered it |
How to
Serve a certificate that is Ready
- Find the row and click "Activate on UI…". The button is disabled, with the reason in its tooltip, when the certificate cannot be served.
- The dialog shows the current and the new certificate side by side, with every field and every check.
- Read the banner: the current certificate keeps serving until the new one is proven served on :443.
- Click "Activate on :443" and re-confirm your identity when asked.
- The result is shown in the dialog: "Active" with the new generation, or "Rolled back" with the reason mipo restored the previous certificate.
Upload a certificate from your own CA
- Click "Upload certificate…".
- Choose the PEM chain and the matching PEM private key.
- Click Validate first. Nothing is stored: the preview shows the subject, hostnames, issuer, expiry, fingerprint, whether it covers the public hostname, and each check.
- If the preview looks right, click "Save as Ready". The certificate is staged, not served.
- Activate it when you are ready, from this page or from rung 6 (Activate) on SSL Status.
Remove a certificate you no longer need
- Delete removes ONE named generation: its row, its certificate and its private key file. It is disabled, with the reason in the tooltip, on any row the "In use by" column is not empty for.
- Confirm the dialog, which names the generation, and re-confirm your identity when asked.
- "Clean up…" in the page header does the same for everything the retention policy has made surplus. It first shows exactly which generations it proposes and why; nothing is removed until you confirm that list.
- The clean-up proposes a generation only when it is expired, failed its checks or has lost its files, or when it is beyond the newest two still-servable ones for its profile and source.
- Past scans, audit events and issuance runs are never touched — only the certificate row and its files.
Go back to the previous certificate
- The row marked "Rollback target (UI)" is the generation the binding came from; only that row offers "Roll back".
- Rolling back re-activates it through the same verified path, so a rollback that is not served is itself undone.
- If there is no rollback target, the row action is absent and the API answers NO_ROLLBACK_TARGET.
Gotchas
- Setting up TLS for the first time? Start on SSL Status. It walks the whole path in order and offers each action when it is due; this page is the inventory behind it.
- A staging certificate is never served. Its Activate action is disabled with "Proof only — never served", on every binding, whatever else is configured.
- A successful staging run lands a normal-looking row: its checks pass and it reads Ready, because a staging certificate is exactly what a staging run was asked to produce. Ready means the bytes are sound, not that it can be served — the Activate action is still refused, and so is a rollback to it. Promote the profile to the production account to get one that can be served.
- Activation is verified. If :443 does not actually serve the new certificate, mipo restores the previous one and the result says so — the certificate stays in the inventory as Ready.
- If even the rollback cannot be verified, the result is an unverifiable state: check :443 by hand and follow the TLS runbook. That case also raises a critical alarm.
- The scanner ingress (:8443) follows the published anchor. Activating a certificate here never changes what scanners are handed, which is exactly the coupling that took the scanner fleet down on 2026-09-14.
- "Unavailable" means the row exists but server-N.crt or server-N.key is gone from disk. Such a certificate cannot be activated until the files are restored.
- Uploading never activates, and neither does issuing. There is no path that changes what browsers see without an explicit, re-authenticated confirmation.
- Two tabs cannot fight: activation carries the certificate id you were looking at, and the server refuses with "the active certificate changed" if someone else moved the binding first.
- Deletion is refused for anything in use — the certificate on :443, the rollback target, the one the scanner anchor matches, and any generation named by an activation that is still in flight. The refusal lists which of those it is.
- A clean-up re-checks every generation at the moment it removes it, not when it showed you the list. A generation that came back into use in between is kept and reported, not deleted.
- Deleting a generation does not free its number. Generation numbers only ever count up, so server-4 will not be reused after you remove it.
API calls (8)
| Method | Path | Description |
|---|---|---|
| GET | /api/admin/ssl/certificates | List every generation with its derived state, usage and checks |
| GET | /api/admin/ssl/certificates/:id | Read one certificate in full |
| POST | /api/admin/ssl/certificates/upload | Preview (dryRun) or stage a PEM certificate and key as Ready |
| GET | /api/admin/ssl/bindings/ui/activation-preview | Read the current-versus-new diff and the engine's blocking reasons |
| POST | /api/admin/ssl/bindings/ui/activate | Activate a certificate on :443, verified, with automatic rollback |
| POST | /api/admin/ssl/bindings/ui/rollback | Re-activate the binding's previous generation |
| DELETE | /api/admin/ssl/certificates/:id | Delete one generation: its row and its files. Refused while anything is using it |
| POST | /api/admin/ssl/certificates/prune | Preview the retention policy (dryRun) or remove the generations you name |
Related
- Certificate Profiles — Profiles are what issue the Let's Encrypt certificates listed here
- SSL Status — The guided path: one page that walks from accounts to a served, auto-renewed certificate, and shows what :443 serves now
- Issuance Runs — The run that produced a certificate, step by step — and why an issuance that produced none failed