gateway: serve the dashboard at wild-pc.<domain>, 404 unrouted subdomains

The dashboard's deployment kept the pre-rename name `wildpc`, so it was
published at wildpc.<domain> while everything else had moved to Wild PC
naming. Rename the deployment and its program to `wild-pc` (the subdomain
is the deployment name) and follow the `_DASHBOARD` constant in both the
Caddyfile generator and doctor — that constant also drives the `:9000`
redirect and doctor's `wildpc program build` hint, which is why the
program is renamed alongside the deployment.

Browsing the old name exposed a second problem: in acme mode every route
lives inside one `*.<domain>` wildcard site, so an unrouted host still
matches the site and completes its TLS handshake. Caddy then ran off the
end of the block and returned a bare 200 with an empty body — a typo'd or
renamed subdomain looked *up* in a browser while rendering nothing. Each
wildcard site now ends with an unmatched `handle` that responds 404.

The API subdomain is untouched: the dashboard derives its API origin by
stripping the first label, so wild-pc.<domain> still resolves to
wildpc-api.<domain>, and the WebSocket origin gate matches on
gateway.domain rather than a hostname.

Also seed the bootstrap dashboard deployment with the `requires:
wildpc-api` block the live deployment already carried, so a fresh install
declares the dependency.
This commit is contained in:
2026-08-02 16:37:04 -07:00
parent b48535745b
commit 15957677ff
9 changed files with 49 additions and 11 deletions

View File

@@ -404,14 +404,21 @@ route — differing only in whether the target is files on disk or a live proces
The table is shown by `wildpc gateway status`, the dashboard Gateway panel, and
`GET /gateway`; the Caddyfile is generated from it.
**The dashboard and its API.** `wildpc` (the dashboard frontend) and `wildpc-api`
are just two such subdomains (`wildpc.<domain>`, `wildpc-api.<domain>`); the
**The dashboard and its API.** `wild-pc` (the dashboard frontend) and `wildpc-api`
are just two such subdomains (`wild-pc.<domain>`, `wildpc-api.<domain>`); the
dashboard calls the API **cross-origin** (wildpc-api allows CORS `*`). The bare
gateway port (`:9000`) redirects to the dashboard subdomain. On a node with **no
domain** (`gateway.tls: off`), there are no subdomains, so `:9000` serves just the
control plane — the dashboard at `/` plus a `/api` reverse-proxy to wildpc-api —
and other services stay port-only.
**Unrouted subdomains 404.** In `acme` mode every route lives inside one
`*.<domain>` wildcard site, so a host that resolves but has no route still matches
the site and completes its TLS handshake. Each wildcard site therefore ends with an
unmatched `handle` that responds `404` — without it Caddy runs off the end of the
block and returns a bare `200` with an empty body, which makes a typo'd or renamed
subdomain look **up** in a browser while rendering nothing.
#### Host routes need DNS, and the gateway is HTTP-only
A host route only does something once `<host>` resolves **to this node**. For a