Caddy previously ran as a host binary in /opt/caddy with a wgui-caddy
systemd/OpenRC unit. Only Caddy is containerized; the app still runs on the
host as root because it shells out to wg, ip and iptables.
- Add caddy-container-commands.ts as the single source of truth for the
run/exec/validate/inspect argument arrays. Every value stays a separate
argv element, the image is pinned to caddy:2.11.4-alpine, and the
entrypoint is set explicitly because some mirrors publish the image with
a null Entrypoint (which made Docker exec "run" as a binary).
- Rewrite install-caddy.sh: require_docker with distro-specific hints,
pull + recreate the container, assert it is running and echo the daemon
error instead of discarding it, normalize the admin socket path in
existing Caddyfiles, and clean up a legacy native install only after the
container is up so the ingress port is never unbound. Add
--purge-legacy / --purge for hosts that want to drop the old install
without installing the container.
- Move the admin socket to /var/lib/wgui/caddy/admin.sock so it lives
inside the mounted Caddy dir and reloads work over docker exec.
- Validate candidate configs in a throwaway container, mounting the TLS
dir read-only as well: provisioning the tls app loads every certificate
referenced by a tls directive, so without that mount a route with a
certificate failed validation and its Caddyfile was never committed.
- Report docker-based installed/version/service_active, skip
validate/reload with a warning when the image is absent, and update the
system setup tool check to look for docker.
- Issue certificates with a docker exec reload command and chown files to
root:root, since the container reads them through a read-only mount.
- Update the Setup UI copy and docs (README, AGENTS.md).
Also drops the unused EmptyContent import and a stray debug log in the
client route form, and stops passing the unsupported cancel_href prop to
ClientRouteForm from the route add/edit pages.