From 3bab6210c599dc797ff27995617ee81c30813069 Mon Sep 17 00:00:00 2001 From: rays Date: Mon, 12 Oct 2026 14:21:53 +0000 Subject: [PATCH] CLAUDE.md and prod-check: ipx-web is what serves port 8099 now (#203) Co-Authored-By: Claude Opus 5.5 --- .claude/skills/ipx-prod-check/SKILL.md | 13 ++++++++++++- CLAUDE.md | 16 ++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/.claude/skills/ipx-prod-check/SKILL.md b/.claude/skills/ipx-prod-check/SKILL.md index 5350b79..77ee5f0 100644 --- a/.claude/skills/ipx-prod-check/SKILL.md +++ b/.claude/skills/ipx-prod-check/SKILL.md @@ -1,6 +1,6 @@ --- name: ipx-prod-check -description: Look for problems in production ipx (the iPX and ipx-directory containers on Tower) from its logs in Loki, its traces in Tempo and its metrics in Prometheus, and file what is found as Gitea issues. Use when asked to check on production, look for issues or errors in ipx, see why something is slow or failing in production, review the logs, or investigate a report about the live site. +description: Look for problems in production ipx (the iPX, ipx-web and ipx-directory containers on Tower) from its logs in Loki, its traces in Tempo and its metrics in Prometheus, and file what is found as Gitea issues. Use when asked to check on production, look for issues or errors in ipx, see why something is slow or failing in production, review the logs, or investigate a report about the live site. --- # Checking production ipx @@ -225,6 +225,17 @@ it. A snapshot whose `refused_private` is not 0 means an ipx server tried to sen private: find which in that server's log, since the directory refuses it but the sender should not have sent it. Many `feed check failed` lines for one feed are the publisher's, not the directory's. +## The page + +`ipx-web` (Caddy) serves the page and passes the API to ipx (#203). It logs only its own start and +errors, not requests: ipx's access log still has every API call, and a page that fails to load +shows there as `/api/page-check` answering something other than 204, 303 or 302. + +```sh +docker ps --filter name=ipx-web --format '{{.Status}}' +docker logs --since 24h ipx-web 2>&1 | grep -v '"level":"info"' | tail +``` + `docker logs` and `docker exec iPX ipx ...` are fine. Do not query production's Postgres directly: ask the user if a question needs the database. diff --git a/CLAUDE.md b/CLAUDE.md index 743dbec..f43c625 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -20,8 +20,8 @@ service of the `content` project, beside audiobookshelf, immich and Plex (#208). | Old database | `/mnt/user/ipx/state.db`, SQLite, used until the move to Postgres on 2026-09-18 and kept for rollback | `/data/state.db` | | Downloads | `/mnt/user/ipx/downloads` | `/downloads` | | Directory | `ipx-directory` in the same project, `192.168.1.130:8100`, public at `ipx-dir.sdf1.net` through the tunnel with no Access in front: tokens are its gate. Config `/mnt/fast/appdata/ipx-directory/directory.toml` (token hashes; Tower's own token in `tower.token` beside it), database `ipx_directory` on the same Postgres, URL in `directory.env` beside the compose file. See [docs/directory.md](docs/directory.md) | `/config/directory.toml` | -| Web UI | `192.168.1.130:8099`, also `ipodderx.sdf1.net` via a Cloudflare tunnel. Once #203 is deployed, that port is `ipx-web`'s (Caddy), and ipx's own is reached only by it | `0.0.0.0:8099` | -| Sign-in via the tunnel | Cloudflare Access app `ipodderx`, with Authentik as its identity provider; see [docs/sso.md](docs/sso.md) | trusts `Cf-Access-Authenticated-User-Email` from `192.168.64.1`, the `ipx_default` gateway (its subnet pinned in the compose file), and only with a valid `Cf-Access-Jwt-Assertion` (`access_team`, `access_aud`) | +| Web UI | `ipx-web` (Caddy) in the same project, at `192.168.1.130:8099`, also `ipodderx.sdf1.net` via a Cloudflare tunnel. It serves the page and passes `/api` and `/media` to ipx, whose own port is published nowhere; its address on `ipx_default` is pinned to `192.168.64.10` (#203) | ipx `0.0.0.0:8099`, Caddy `:8080` | +| Sign-in via the tunnel | Cloudflare Access app `ipodderx`, with Authentik as its identity provider; see [docs/sso.md](docs/sso.md) | Caddy passes `Cf-Access-*` only from `192.168.64.1`, the `ipx_default` gateway cloudflared arrives from (`TUNNEL_PEER`; the subnet is pinned in the compose file); ipx trusts them only from Caddy, `192.168.64.10`, and only with a valid `Cf-Access-Jwt-Assertion` (`access_team`, `access_aud`) | Work to do lives in the Gitea issues at https://git.sdf1.net/rays/ipx/issues, not in a `TODO.md`. `/src/tea` is logged in: `/src/tea issues list --login git.sdf1.net --repo rays/ipx`. @@ -63,6 +63,18 @@ docker compose -f /mnt/fast/arcane/projects/ipx/compose.yaml pull ipx-directory docker compose -f /mnt/fast/arcane/projects/ipx/compose.yaml up -d ipx-directory ``` +And the page, `ipx-web`, the same again; a change to `web/` alone needs only this one: + +```sh +docker buildx build -f Dockerfile.web --tag 192.168.1.130:5000/ipx-web:latest . --push +docker compose -f /mnt/fast/arcane/projects/ipx/compose.yaml pull ipx-web +docker compose -f /mnt/fast/arcane/projects/ipx/compose.yaml up -d ipx-web +``` + +Testing sign-in from Tower itself proves nothing about the tunnel: Tower's own requests reach the +published port as `192.168.1.130`, and Caddy rightly strips their `Cf-Access-*`. Send them from a +container on another network, as cloudflared's are (#209). + **Name the service.** A bare `up -d` recreates every container in the project, which once the split lands means the frontend and directory too. Run `pull` before `up`, because `up` reuses whatever `latest` the host already has.