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 <noreply@anthropic.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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`) |
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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).")
|
||||
|
||||
@@ -82,7 +82,7 @@ async function drawDirectorySettings(){
|
||||
<p class="hint">The Directory shows podcasts from a directory service that iPX servers share.
|
||||
Without one, people add feeds by their address.</p>
|
||||
<div class="field"><label for="durl">Directory address</label>
|
||||
<input type="text" inputmode="url" id="durl" value="${esc(g.directory_url)}" placeholder="https://ipx-dir.example.net" spellcheck="false"></div>
|
||||
<input type="text" inputmode="url" id="durl" value="${esc(g.directory_url)}" placeholder="https://directory.example.net" spellcheck="false"></div>
|
||||
<div class="field"><label for="dtoken">Access token</label>
|
||||
<div class="inline"><input type="password" id="dtoken" autocomplete="off" spellcheck="false"
|
||||
placeholder="${g.directory_token_set ? 'Set. Paste a new one to replace it' : 'Paste the token the directory gave this server'}">
|
||||
|
||||
Reference in New Issue
Block a user