The web UI's certificate from Let's Encrypt, through Jarl

tls.acme names the certificate and jarl: the Jarl server and a token that
may only write the challenge record. Steward gets the certificate with
DNS-01 (lego), writing the record through Jarl's API into every view that
has the zone, renews it with a third of its lifetime left and swaps it
in without a restart. A check runs before every order: Jarl, the zone,
the token's permission, a test record, the zone's name servers, public
resolvers, clean-up; each step says what to fix. Staging by default.

With a certificate, each listener serves HTTPS and plain HTTP on one port
(redirecting plain HTTP, except from the server itself).

steward cert / cert check / cert renew, Server -> Certificate in the web
UI, GET /certificate, POST /certificate/check|renew. docs/certificates.md
and docs/jarl.md (the Jarl user and the token's grant).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
abrown38andClaude Opus 5.5 committed 2026-10-14 15:46:36 +01:00
1 parent d0ee2c8844
commit 7b3f0f764c
32 files changed
+2544 -27

No files matched your search

+27
View File
@@ -71,6 +71,33 @@ sandbox is only tested by installing the package in a container that
runs systemd (`--privileged /sbin/init`) and pointing a client container
at it.
## Certificates
`internal/certs` has unit tests with a fake Jarl and an in-process DNS
server, covering every failure the check reports. To test a real order:
1. Run Jarl's e2e and keep its jarld and named:
`KEEP=1 PEBBLE=0 JARL_BIND_ROOT=... WORK=DIR scripts/e2e.sh` in `../jarl`.
jarld is then on `127.0.0.1:28053` and named on `127.0.0.1:25353`, with
the zone `adbraun.test` in two views.
2. Make the restricted user and token there, as docs/jarl.md says, with
`DIR/jarl --config DIR/cli.yaml`.
3. Start Pebble against that named:
`docker run -d --network host ghcr.io/letsencrypt/pebble -config test/config/pebble-config.json -dnsserver 127.0.0.1:25353`,
and copy its `/test/certs/pebble.minica.pem` out.
4. Point a scratch stewardd at both:
```yaml
tls:
acme: {domain: dhcp.adbraun.test, email: t@adbraun.test, agree_tos: true,
directory: https://localhost:14000/dir, ca_bundle: pebble.minica.pem,
resolvers: ["127.0.0.1:25353"], check_propagation: false}
jarl: {server: http://127.0.0.1:28053, token_file: jarl.token}
```
`check_propagation` has to be off here: the test named isn't on port 53.
The unit tests cover that step.
## The web UI
Plain JavaScript modules under `internal/web/static/`, built with the