From bc650153ce6d40e2b6162bdd6048a44b2607c2ca Mon Sep 17 00:00:00 2001 From: rays Date: Mon, 12 Oct 2026 17:06:06 +0000 Subject: [PATCH] The directory is at directory.ipxreader.app (#214) The zone is in Cloudflare and the rays-unraid tunnel routes the name to ipx-directory, as it does ipx-dir.sdf1.net, which keeps answering until every server using it has moved: a redirect to another host would drop the Authorization header. Production ipx shares with the new name. CLAUDE.md, docs/directory.md, the prod-check skill and the dashboard name it; the admin page's placeholder and the settings' hint use directory.example.net. Co-Authored-By: Claude Opus 5.5 --- .claude/skills/ipx-prod-check/SKILL.md | 2 +- CLAUDE.md | 2 +- crates/ipx/src/config.rs | 2 +- crates/ipx/src/web.rs | 2 +- docs/directory.md | 2 +- grafana/dashboard.py | 2 +- web/src/admin.ts | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.claude/skills/ipx-prod-check/SKILL.md b/.claude/skills/ipx-prod-check/SKILL.md index 190eccf..a48cd44 100644 --- a/.claude/skills/ipx-prod-check/SKILL.md +++ b/.claude/skills/ipx-prod-check/SKILL.md @@ -12,7 +12,7 @@ Production is three containers in the Arcane project `ipx` on Tower |---|---|---|---|---| | `ipx-web` | Caddy: serves the page, passes `/api` and `/media` to ipx (#203). Port 8099, the LAN and the tunnel | `{container="ipx-web"}`, JSON: a line a request (`http.log.access`), its own errors | service `ipx-web`: a span a request, passing `traceparent` on to ipx (#213) | none | | `iPX` | the daemon: API, scans, downloads, DeadAir | `{container="iPX"}`, JSON (`IPX_LOG_FORMAT=json`) | service `ipx`; passes `traceparent` to the directory | `job="ipx"`, its `/metrics` | -| `ipx-directory` | the directory of public podcasts, `ipx-dir.sdf1.net` (#204) | `{container="ipx-directory"}`, JSON (`DIRECTORY_LOG_FORMAT=json`) | service `ipx-directory`: a span a request, joining ipx's trace when ipx called; a trace a refresher round (#213) | none | +| `ipx-directory` | the directory of public podcasts, `directory.ipxreader.app` (#204, #214) | `{container="ipx-directory"}`, JSON (`DIRECTORY_LOG_FORMAT=json`) | service `ipx-directory`: a span a request, joining ipx's trace when ipx called; a trace a refresher round (#213) | none | Under them, Tower itself: `job="node"` (the node exporter: load, CPU, memory, disks). The Grafana dashboard `iPX` draws all of it in that order (`grafana/dashboard.py`). A trace without the diff --git a/CLAUDE.md b/CLAUDE.md index 21e650a..3bb1a0f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -19,7 +19,7 @@ service of the `content` project, beside audiobookshelf, immich and Plex (#208). | Database | Postgres 18, database `ipodderx`, login `ipodderx`, on the `postgres` container of the Arcane project `databases` (`192.168.1.130:5433`). The URL is in `ipx.env` beside the compose file (`/mnt/fast/arcane/projects/ipx/ipx.env`, mode 600), passed to the container as `IPX_DATABASE_URL`. A relative `env_file`: Arcane runs compose in its own container, where `/mnt/fast/appdata` does not exist | | | 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, and entered in ipx's Admin, Directory, which keeps it in the database's `settings`), 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` | +| Directory | `ipx-directory` in the same project, `192.168.1.130:8100`, public at `directory.ipxreader.app` through the tunnel (`ipx-dir.sdf1.net` also answers until #214 retires it) 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, and entered in ipx's Admin, Directory, which keeps it in the database's `settings`), 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 | `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`) | diff --git a/crates/ipx/src/config.rs b/crates/ipx/src/config.rs index 430271d..0993ca5 100644 --- a/crates/ipx/src/config.rs +++ b/crates/ipx/src/config.rs @@ -42,7 +42,7 @@ pub struct General { /// How much artwork iPX keeps on disk, in MB, so the page loads it from iPX rather than from /// every publisher; the least recently shown goes first. 0 keeps none. pub art_cache_mb: u64, - /// The directory service the Directory shows (#205), as `https://ipx-dir.sdf1.net`. Empty + /// The directory service the Directory shows (#205), as `https://directory.ipxreader.app`. Empty /// for none: then the Directory says so, and feeds are added by their address. pub directory_url: String, /// The token the directory gave this server. Never sent to the page: it says only whether diff --git a/crates/ipx/src/web.rs b/crates/ipx/src/web.rs index 193e376..6f0a6e4 100644 --- a/crates/ipx/src/web.rs +++ b/crates/ipx/src/web.rs @@ -2177,7 +2177,7 @@ async fn patch_settings( if let Some(v) = body.directory_url { let v = v.trim().trim_end_matches('/').to_owned(); if !v.is_empty() && !url::Url::parse(&v).is_ok_and(|u| matches!(u.scheme(), "http" | "https")) { - return Err(ApiError::bad_request(format!("{v:?} is not a web address; try https://ipx-dir.example.net"))); + return Err(ApiError::bad_request(format!("{v:?} is not a web address; try https://directory.example.net"))); } cfg.general.directory_url = v; } diff --git a/docs/directory.md b/docs/directory.md index bc3bd21..04429e2 100644 --- a/docs/directory.md +++ b/docs/directory.md @@ -6,7 +6,7 @@ fetches each feed's title, artwork, category, description and latest twenty item and any server holding a token can browse it. It never downloads a file, and it never stores one's address: every ipx server still fetches its own feeds. -This server's is at `https://ipx-dir.sdf1.net`, the `ipx-directory` service of the Arcane project +This server's is at `https://directory.ipxreader.app` (moved from `ipx-dir.sdf1.net`, which answers as well until every server using it has moved, #214), the `ipx-directory` service of the Arcane project `ipx`, with its database `ipx_directory` on the `databases` project's Postgres. ## In ipx diff --git a/grafana/dashboard.py b/grafana/dashboard.py index 254bfff..a67a01a 100644 --- a/grafana/dashboard.py +++ b/grafana/dashboard.py @@ -270,7 +270,7 @@ ts("Artwork", [prom('max(ipx_art_cache_bytes{job="ipx"}) / max(ipx_art_cache_lim "limit: many at every sweep, with a falling hit rate, means the limit is too small.")["fieldConfig"]["overrides"] = bar_overrides("images evicted") y += 8 -# ---- ipx-directory: public at ipx-dir.sdf1.net, shared by ipx servers (#204) +# ---- ipx-directory: public at directory.ipxreader.app, shared by ipx servers (#204) row("ipx-directory") stat("Snapshots", loki(f'sum(count_over_time({DIR} | message="snapshot" [$__range])) or vector(0)', instant=True), 0, desc="ipx sends one when what it shares changes, and every half hour (#211).") diff --git a/web/src/admin.ts b/web/src/admin.ts index 57618b5..d725a01 100644 --- a/web/src/admin.ts +++ b/web/src/admin.ts @@ -82,7 +82,7 @@ async function drawDirectorySettings(){

The Directory shows podcasts from a directory service that iPX servers share. Without one, people add feeds by their address.

-
+