Every device on a LAN behind an internal certificate authority can get real, browser-trusted HTTPS — except the UniFi console itself, whose certificate manager is a browser-only click-through with no documented API. Rather than store a real UniFi account credential in a cron job (or steal a live session cookie), reverse-engineering the console's own UI found a much better path.
UniFi OS's console settings expose an SSH toggle and a password-only "Change Password" control — there's
no key-upload option at the local console level (a per-admin "SSH Keys" feature some UniFi documentation
mentions belongs to the cloud identity system, not this local console UI). The path to real, durable
key-based access: set a one-time password through that control, log in exactly once with it, and use that
single session to append a real public key to ~/.ssh/authorized_keys directly. Password auth
is never needed again after that — every future automated session uses the key.
The certificate manager's actual request shapes aren't published anywhere — they were recovered by
monkey-patching window.fetch in the console's own page context immediately before triggering
each UI action for real, then reading back exactly what got sent. That surfaced the real, if undocumented,
routes:
| Action | Request |
|---|---|
| List certs | GET /api/userCertificates |
| Upload new | POST /api/userCertificates — JSON body {"name", "cert", "key"},
not multipart; the cert field is the leaf + intermediate chain concatenated into one PEM string |
| Activate | PUT /api/userCertificates/{id}/status — {"active": true} |
| Delete | DELETE /api/userCertificates/{id} |
curl against that local port returns the real certificate list with zero
authentication. The public HTTPS port is where session auth actually gets enforced (via the reverse proxy
in front); the backend process itself trusts anything arriving from localhost unconditionally. This is
presumably the exact mechanism UniFi's own built-in Let's Encrypt auto-renewal uses internally.
This is what makes real automation possible without ever handling a UniFi account password or a stolen
session cookie in a script: SSH in as a key-authenticated user (from step one), then curl
against the local port directly. No credentials to rotate, no session to keep alive, no browser automation
required at all for the actual renewal step.
name field with a timestamp.
This field is purely a UI label with no bearing on the certificate's actual content or hostname matching,
so the suffix is cosmetic — it just needs to be unique.
Worth keeping the safer operation order despite the extra step: create the new cert first, verify it's actually active, then delete the old one — rather than deleting first. That way a failure partway through never leaves the console with zero valid certificates installed, just a leftover old one alongside the new.
A daily cron job checks the currently-active certificate's real expiry date via the local API, and once within a threshold of expiring, mints a fresh certificate from the internal CA, uploads it, activates it, and removes the previous one — the exact same renewal shape used for every other internally-certificated service, just targeting a completely different, undocumented install mechanism under the hood. Verified end-to-end for real (an actual renewal run, not just the skip-path when nothing needs renewing) before trusting it unattended.