dc96e15643
- Add lib/state.py: in-memory state store with subsystem collectors (firewall, dnsmasq, nginx, acme, wireguard) - Refactor all handlers: read from state on GET, call refresh_state() after mutations instead of invoking subprocesses per request - daemon/server.py: add refresh_state(), /status/all, /status/refresh; populate state at startup - webui/api/certs.py: async step-by-step ACME issuance (validate, issue with request_id, poll status) replacing blocking endpoint - webui/server.py: render pages from state instead of direct lib calls - Update templates, JS for async cert issuance with polling UI - Update tests for state-based mocking; add test_state.py - Fix SIM105 lint issue (contextlib.suppress) - Add TODO.md with certificate issuance issue tracking Resolves: WebUI 30s timeout freeze during cert issuance (Problem 1)
48 lines
2.4 KiB
Markdown
48 lines
2.4 KiB
Markdown
# TODO — Certificate Issuance Issues
|
||
|
||
## Problem 1: Timeout Mismatch Causes WebUI Freeze → FIXED
|
||
|
||
**Date Found:** May 30, 2026
|
||
**Date Fixed:** May 30, 2026
|
||
|
||
**Symptom:** Clicking "Issue Certificate" in the WebUI freezes for ~30 seconds, then returns a 500 error with "Daemon request timed out". Meanwhile the daemon silently runs `acme.sh` in the background for up to 120s before timing out itself.
|
||
|
||
**Root Cause:**
|
||
- `daemon/client.py` — WebUI client uses `timeout=30` for all daemon requests
|
||
- `daemon/handlers/acme.py` — Daemon allows `acme.sh` subprocess `timeout=120`
|
||
- The WebUI gives up at 30s while the daemon is still legitimately processing
|
||
|
||
**Fix Applied:** Replaced blocking issue endpoint with async step-by-step issuance:
|
||
- `POST /acme/validate` — Pre-flight checks (instant): acme.sh installed, email configured, webroot ready, DNS resolves, challenge configured
|
||
- `POST /acme/issue` — Returns immediately with `request_id`, spawns background task
|
||
- `GET /acme/issue/status` — Client polls for step-by-step progress
|
||
- UI shows pre-check results, then step progress with polling (no timeout issues)
|
||
- Blocking DNS check prevents wasted acme.sh calls when domain doesn't resolve
|
||
|
||
**Files Changed:** `daemon/handlers/acme.py`, `webui/api/certs.py`, `webui/templates/certs.html`, `webui/static/app.js`
|
||
|
||
---
|
||
|
||
## Problem 2: ZeroSSL Rate Limits Block Certificate Issuance
|
||
|
||
**Date Found:** May 30, 2026
|
||
|
||
**Symptom:** `acme.sh` fails to issue a certificate for `218broad.vacuum.network` with:
|
||
```
|
||
The retryafter=86400 value is too large (> 600), will not retry anymore.
|
||
```
|
||
|
||
**Root Cause:** ZeroSSL CA returns a `retry-after` of 86400 seconds (24 hours), likely from a prior failed challenge. `acme.sh` has a hard cap of 600s on retry-after values and refuses to proceed when the CA requests a longer wait.
|
||
|
||
**Files:** N/A (acme.sh behavior, not a project code issue)
|
||
|
||
**Workarounds:**
|
||
- Switch CA to Let's Encrypt: `acme.sh --set-default-ca --server letsencrypt`
|
||
- Wait 24 hours and retry
|
||
- Investigate and clean up prior failed challenges for the domain on ZeroSSL's side
|
||
|
||
## Status
|
||
|
||
- **Problem 1:** ✅ FIXED (2026-05-30) — Refactored to async step-by-step issuance with polling. State store collectors replace blocking subprocess calls on every request.
|
||
- **Problem 2:** ℹ️ N/A — ZeroSSL rate limit is external to the project. Workarounds: switch CA to Let's Encrypt, wait 24h, or clean up failed challenges on ZeroSSL's side.
|