Wheelhouse docs

Issue a certificate and bind it to the web UI#

You will end up with a certificate issued by an ACME authority, held in the router's PKI store and renewed by the router itself. There is one thing to be clear about before you start, because the obvious assumption is wrong:

Before you start#

  • The operator role and a licence.
  • A DNS name that resolves to this router from the internet.
  • Port 80 reachable on the address that name resolves to. The router validates with HTTP-01. If port 80 cannot reach it, the commit fails with certbot's own message and nothing changes.
  • An e-mail address for expiry notices.

Step 1 — Request it#

Security → Certificates → + Request via ACME.

FieldWhat it is
Certificate nameThe PKI name other services reference. Letters, digits, _ and - only — the field strips anything else as you type.
Account e-mailWhere expiry notices go
Domain namesComma separated. The first is the subject; the rest are additional names.
Listen addressOptional, the address port 80 arrives on. Leave it as all addresses unless you have a reason.
RSA key size2048, 3072 or 4096. 2048 is the default and is not written into the configuration.
ACME directoryLet's Encrypt production by default.
what it stages
set pki certificate router acme domain-name router.example.com
set pki certificate router acme email admin@example.com
set pki certificate router acme listen-address 203.0.113.2
set pki certificate router acme rsa-key-size 4096

The directory URL and the key size are written only when they differ from the defaults, so a plain request is three lines.

Step 2 — Open port 80 for the validation#

The installer's default ruleset does not admit port 80 from the WAN, so HTTP-01 will fail unless you add a rule.

set firewall ipv4 input filter rule 70 action accept
set firewall ipv4 input filter rule 70 description 'acme http-01'
set firewall ipv4 input filter rule 70 protocol tcp
set firewall ipv4 input filter rule 70 destination port 80

Leave it in place: renewal needs it too, and the router renews on its own.

Step 3 — Commit#

The router runs certbot at commit time. That means the commit is slow, and that a failure to validate is a failed commit with certbot's message attached — not a half-configured certificate. Nothing is changed when it fails.

Step 4 — Check it#

Security → Certificates lists the PKI store with an expiry countdown per certificate and a tile counting the ones ACME manages. From a shell:

bash
show pki certificate

And from outside, against whatever is actually serving it:

bash
openssl s_client -connect router.example.com:443 -servername router.example.com </dev/null 2>/dev/null \
  | openssl x509 -noout -issuer -subject -dates

Using it for the web UI on 8443#

The Wheelhouse agent reads its certificate from files named by --tls-cert and --tls-key. It does not read the router's PKI store. To serve the web UI with an ACME-issued certificate you would point those two flags at the files certbot maintains on the router, using a systemd drop-in rather than editing the packaged unit:

/etc/systemd/system/wheelhouse-agent.service.d/tls.conf
[Service]
ExecStart=
ExecStart=/usr/bin/wheelhouse-agent … --tls-cert <path> --tls-key <path>

The paths those certificates are written to on a Wheelhouse image are not recorded in this project — <TODO: owner>. Find them on your own router before relying on this, and be aware of two consequences:

  • The agent reads the certificate at start-up. A renewal that rewrites the files does not reach a running agent; it needs a restart. Nothing arranges that for you today.
  • A drop-in survives an image upgrade; editing the packaged unit does not. An image upgrade installs a fresh /lib/systemd/system/wheelhouse-agent.service.

What the self-signed certificate is, and is not#

With no --tls-cert, and --tls-self-signed set, the agent generates a P-256 certificate into its data directory, valid for the host name, localhost and every local address at the time. It is not a substitute for a trusted certificate — it is strictly better than plaintext, because it stops passive capture of session cookies on the LAN, and the login screen says so.

The agent replaces that certificate on sight in three cases, and logs why: it is unreadable, it has expired or expires within 30 days, or it was generated as a CA. That last one is worth knowing if you trusted an older one: earlier builds generated it with certificate-signing usage and told the operator to trust it, which made a key on the router a trust anchor for every site the browser visits. If you added such a certificate to a trust store, remove it.

Undoing it#

delete pki certificate router
delete service https certificates certificate router

The Certificates page's detail panel has a delete for the certificate. Removing the firewall rule that admitted port 80 is separate, and stops future renewals.

See also#


Checked against ui/src/pages/Certificates.tsx · agent/tls.go · agent/main.go · docs/security.md

Updated 2026-09-02 certificates acme tls