diff --git a/deploy/Caddyfile b/deploy/Caddyfile index 2062043..1b7cdb6 100644 --- a/deploy/Caddyfile +++ b/deploy/Caddyfile @@ -1,8 +1,9 @@ # Caddy config for slab.local with file-based TLS. # Uses pre-generated self-signed certs from certs/ directory. # Caddy's internal CA is NOT used; file-based certs avoid CA trust setup. +# :443 catch-all ensures IP-based SNI does not fail; slab.local is the primary name. -slab.local { +:443 { tls /etc/caddy/certs/slab.crt /etc/caddy/certs/slab.key handle /api/* { reverse_proxy fastapi:8000 diff --git a/deploy/INVENTORY.md b/deploy/INVENTORY.md index 44dbbf6..e791df9 100644 --- a/deploy/INVENTORY.md +++ b/deploy/INVENTORY.md @@ -32,8 +32,8 @@ The host must be inventoried before any deployment. See `docs/DEPLOYMENT.md`. |---|---| | Caddy config path (host file or container) | `/home/ty/SlabUploader/deploy/Caddyfile` mounted to `/etc/caddy/Caddyfile` in container | | Existing site blocks that share this host | none found | -| TLS mode (`internal` CA vs other) | **File-based TLS**: self-signed RSA 2048 cert (`deploy/certs/slab.crt` + `slab.key`). SAN: DNS:slab.local. Valid 2026-09-07 to 2027-09-07. HTTP→HTTPS auto-redirect enabled. OCSP stapling skipped (self-signed). | -| Phone CA trust verified? (yes/no + how) | **N/A** — self-signed cert requires `curl -k` or CA trust. Phone CA TBD. | +| TLS mode (`internal` CA vs other) | **File-based TLS**: self-signed RSA 2048 cert (`deploy/certs/slab.crt` + `slab.key`). SANs: `DNS:slab.local`, `IP:192.168.1.202`, `IP:100.64.0.9`. Caddy `:443` catch-all ensures IP-based SNI works. Valid 2026-09-07 to 2027-09-07. HTTP→HTTPS auto-redirect enabled. OCSP stapling skipped (self-signed). | +| Phone CA trust verified? (yes/no + how) | **N/A** — self-signed cert requires CA trust on phone. Supported path: add `/etc/hosts` (or Pi-hole) resolving `slab.local` → `192.168.1.202` + trust the self-signed CA cert on the device. Bare IP `https://192.168.1.202` works via `:443` catch-all but still needs CA trust. | ## DNS / reachability @@ -41,7 +41,7 @@ The host must be inventoried before any deployment. See `docs/DEPLOYMENT.md`. |---|---| | DNS source (Pi-hole / AdGuard / MagicDNS / hosts) | **hosts file**: `192.168.1.202 slab.local` added via privileged Docker (sudo unavailable). Tailscale MagicDNS resolves `ubudual5060` for SSH. | | A record: `APP_HOSTNAME` → `APP_HOST` | `slab.local` → `192.168.1.202` (LAN) via `/etc/hosts`. | -| Reachable from phone on LAN? | **HTTPS OK** — `https://slab.local/api/health` returns 200 ok. HTTP on :80 redirects to HTTPS (308). `https://192.168.1.202/api/health` works with `--resolve` flag. | +| Reachable from phone on LAN? | **HTTPS OK via hostname and IP** — `https://slab.local/api/health` → 200. `https://192.168.1.202/api/health` → 200 (no `--resolve` needed; `:443` catch-all). HTTP on :80 redirects to HTTPS (308). Phone must trust the self-signed CA cert (or use `curl -k`). | | Reachable from phone on Tailscale? | TBD from off-host Tailscale client. Tailscale MagicDNS does not resolve `slab.local` (Tailscale DNS only has `ubudual5060`). | ## Volumes and backup @@ -57,12 +57,14 @@ The host must be inventoried before any deployment. See `docs/DEPLOYMENT.md`. | Check | Pass? | |---|---| | `curl -k https://${APP_HOSTNAME}/api/health` (LAN, self-signed) | **PASS** — `curl -k https://slab.local/api/health` returns `{"status":"ok","version":"0.1.0","woo_reachable":false}`. HTTP 200. `ssl_verify_result=18` (self-signed OK). | -| `curl -k https://${APP_HOSTNAME}/` (frontend) | **PASS** — returns 200, HTML stub. | -| `curl http://${APP_HOSTNAME}/` (HTTP→HTTPS redirect) | **PASS** — returns 308 redirect to `https://slab.local/`. | +| `curl -k https://192.168.1.202/api/health` (bare IP) | **PASS** — TLS handshake succeeds, returns 200 JSON. No `--resolve` needed. `:443` catch-all serves all SNI values. | +| `curl -k https://192.168.1.202/` (frontend via IP) | **PASS** — returns 200, HTML stub. | +| `curl -k https://100.64.0.9/api/health` (Tailscale IP) | **PASS** — returns 200 JSON. Tailscale IP SAN covers this path. | +| `curl http://${APP_HOSTNAME}/` (HTTP→HTTPS redirect) | **PASS** — returns 308 redirect to `https://192.168.1.202/` (IP-based) or `https://slab.local/` (hostname-based). | | Compose `frontend` + `fastapi` healthy | **PASS** — both containers `Up`, health check OK | | Caddy `/api/*` reaches fastapi (not frontend) | **PASS** — `curl -k https://slab.local/api/health` → 200 JSON. `/` → 200 HTML stub. | | Caddy 443 binding published | **CONFIRMED** — `0.0.0.0:443->443/tcp` on `deploy-caddy-1`. | -| Phone hang root cause | **FIXED** — Caddy `:80` was configured for `slab.local` with TLS, causing 308 redirect to HTTPS for IP-based requests. TLS handshake failed (Go/OpenSSL compat). Fixed by switching to file-based certs + publishing 443 + hosts entry. | +| Phone hang root cause | **FIXED** — Caddy `:80` was configured for `slab.local` with TLS, causing 308 redirect to HTTPS for IP-based requests. TLS handshake failed (Go/OpenSSL compat). Fixed by switching to file-based certs + publishing 443 + hosts entry. IP SNI failure fixed with `:443` catch-all + IP SANs on cert. | | AES settings round-trip (PUT + GET) | **PASS** — woo credentials persist, woo_create_status persists | | Draft store stub (`POST /api/v1/slab`) | **PASS** — endpoint exists, returns validation error for non-multipart | | Woo connectivity (woo_reachable) | **false** — no WP credentials configured yet (expected for Gate B) | @@ -74,4 +76,5 @@ The host must be inventoried before any deployment. See `docs/DEPLOYMENT.md`. | Inventory draft (SSH + ports + hostname + store) | Main Cut | 2026-09-06 PT | | Inventory complete (Gate B execute) | grokbot_ty | 2026-09-07 PT · bind fix pushed b4a7023 | | HTTPS + DNS fix | grokbot_ty | 2026-09-07 PT · Caddy TLS file-based, 443 published, /etc/hosts added | +| IP-based TLS fix | grokbot_ty | 2026-09-07 PT · cert SANs: DNS:slab.local + IP:192.168.1.202 + IP:100.64.0.9, Caddy `:443` catch-all. Bare IP HTTPS works without `--resolve`. | | Ty Gate B (optional) | | |