ipx-play's metrics on 9191: 9189 is hnopml's (#458)
5d0ff1a put ipx-play's /metrics on 9189, but hnopml, in the same
compose project, has published 192.168.1.130:9189 since 2026-11-12 and
Prometheus scrapes it there as job="hnopml". Deployed as written,
ipx-play's port would have clashed with it. 9187 to 9190 are ipx, the
directory, hnopml and ipx-web; 9191 is free.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -13,7 +13,7 @@ Production is four 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) | `job="ipx-web"`: Caddy's own `caddy_http_*`, from `METRICS_BIND`, published as `192.168.1.130:9190` (#371) |
|
| `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) | `job="ipx-web"`: Caddy's own `caddy_http_*`, from `METRICS_BIND`, published as `192.168.1.130:9190` (#371) |
|
||||||
| `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` | 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, `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) | `job="ipx-directory"`, its `/metrics` |
|
| `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) | `job="ipx-directory"`, its `/metrics` |
|
||||||
| `ipx-play` | the page a shared episode opens, `play.ipxreader.app` (#447); ipx sends it the episodes shared | `{container="ipx-play"}`, JSON (`PLAY_LOG_FORMAT=json`): a line a request (`ipx_play::http`), one a share | service `ipx-play`: a span a request, joining ipx's trace on a share | `job="ipx-play"`, its `/metrics` on `metrics_bind` (production `192.168.1.130:9189`, LAN only, #458) |
|
| `ipx-play` | the page a shared episode opens, `play.ipxreader.app` (#447); ipx sends it the episodes shared | `{container="ipx-play"}`, JSON (`PLAY_LOG_FORMAT=json`): a line a request (`ipx_play::http`), one a share | service `ipx-play`: a span a request, joining ipx's trace on a share | `job="ipx-play"`, its `/metrics` on `metrics_bind` (production `192.168.1.130:9191`, LAN only, #458) |
|
||||||
|
|
||||||
Grafana's alert rules (`grafana/alerts.py`, #365) watch all of it between checks: start by asking
|
Grafana's alert rules (`grafana/alerts.py`, #365) watch all of it between checks: start by asking
|
||||||
which are firing (the monitoring section). Under them, Tower itself: `job="node"` (the node exporter: load, CPU, memory, disks). The Grafana
|
which are firing (the monitoring section). Under them, Tower itself: `job="node"` (the node exporter: load, CPU, memory, disks). The Grafana
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ 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` |
|
| 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` |
|
| Downloads | `/mnt/user/ipx/downloads` | `/downloads` |
|
||||||
| Directory | `ipx-directory` in the same project, `192.168.1.130:8100`, public at `directory.ipxreader.app` through the tunnel with no Access in front: its pages are anyone's to browse, read only (#215), and its API (`/v1`) takes a token for everything. Until 2026-10-12 it was `ipx-dir.sdf1.net` (#214). 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`, with the address ipx reaches it at: `http://ipx-directory:8100`, inside Docker, not the public address, which went out through Cloudflare and the tunnel, 170-340 ms a call where the directory answers in 16 ms), 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 with no Access in front: its pages are anyone's to browse, read only (#215), and its API (`/v1`) takes a token for everything. Until 2026-10-12 it was `ipx-dir.sdf1.net` (#214). 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`, with the address ipx reaches it at: `http://ipx-directory:8100`, inside Docker, not the public address, which went out through Cloudflare and the tunnel, 170-340 ms a call where the directory answers in 16 ms), 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` |
|
||||||
| Shared episodes | `ipx-play` in the same project, `192.168.1.130:8102`, public at `play.ipxreader.app` through the tunnel with no Access in front: the page a shared episode opens, anyone's to see (#447). `/v1` takes a token. Config `/mnt/fast/appdata/ipx-play/play.toml` (token hashes; Tower's token entered in ipx's Admin, Directory, Sharing episodes, with the address `http://ipx-play:8102`), database `ipx_play` on the same Postgres, URL in `play.env` beside the compose file. Metrics for Prometheus on `192.168.1.130:9189`, LAN only, as `job="ipx-play"` (#458). See [docs/play.md](docs/play.md) | `/config/play.toml` |
|
| Shared episodes | `ipx-play` in the same project, `192.168.1.130:8102`, public at `play.ipxreader.app` through the tunnel with no Access in front: the page a shared episode opens, anyone's to see (#447). `/v1` takes a token. Config `/mnt/fast/appdata/ipx-play/play.toml` (token hashes; Tower's token entered in ipx's Admin, Directory, Sharing episodes, with the address `http://ipx-play:8102`), database `ipx_play` on the same Postgres, URL in `play.env` beside the compose file. Metrics for Prometheus on `192.168.1.130:9191`, LAN only, as `job="ipx-play"` (#458). See [docs/play.md](docs/play.md) | `/config/play.toml` |
|
||||||
| Home page | `ipxreader.app` (and `www`): a static page from `site/`, on the Cloudflare Pages project `ipxreader`, not on Tower. See below | |
|
| Home page | `ipxreader.app` (and `www`): a static page from `site/`, on the Cloudflare Pages project `ipxreader`, not on Tower. See below | |
|
||||||
| 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` |
|
| 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`) |
|
| 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`) |
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ pub struct Config {
|
|||||||
#[serde(default = "default_database_url_env")]
|
#[serde(default = "default_database_url_env")]
|
||||||
pub database_url_env: String,
|
pub database_url_env: String,
|
||||||
/// Where to serve /metrics for Prometheus (#458), apart from `bind`, which the tunnel
|
/// Where to serve /metrics for Prometheus (#458), apart from `bind`, which the tunnel
|
||||||
/// publishes: `0.0.0.0:9189`. Empty serves none.
|
/// publishes: `0.0.0.0:9191`. Empty serves none.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub metrics_bind: String,
|
pub metrics_bind: String,
|
||||||
/// The address people open, which the links ipx is handed begin with.
|
/// The address people open, which the links ipx is handed begin with.
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ The compose service, beside `ipx-directory`:
|
|||||||
- /mnt/fast/appdata/ipx-play:/config
|
- /mnt/fast/appdata/ipx-play:/config
|
||||||
ports:
|
ports:
|
||||||
- "8102:8102"
|
- "8102:8102"
|
||||||
- "9189:9189" # /metrics, for Prometheus on the LAN; not in the tunnel
|
- "9191:9191" # /metrics, for Prometheus on the LAN; not in the tunnel
|
||||||
```
|
```
|
||||||
|
|
||||||
Its config, `/mnt/fast/appdata/ipx-play/play.toml`:
|
Its config, `/mnt/fast/appdata/ipx-play/play.toml`:
|
||||||
@@ -48,7 +48,7 @@ bind = "0.0.0.0:8102"
|
|||||||
public_url = "https://play.ipxreader.app"
|
public_url = "https://play.ipxreader.app"
|
||||||
# Prometheus metrics, on a port of their own and not the one the tunnel publishes. Empty, or
|
# Prometheus metrics, on a port of their own and not the one the tunnel publishes. Empty, or
|
||||||
# left out, serves none.
|
# left out, serves none.
|
||||||
metrics_bind = "0.0.0.0:9189"
|
metrics_bind = "0.0.0.0:9191"
|
||||||
|
|
||||||
# One for each ipx server allowed to make links; `ipx-play token <name>` prints the lines.
|
# One for each ipx server allowed to make links; `ipx-play token <name>` prints the lines.
|
||||||
[[tokens]]
|
[[tokens]]
|
||||||
@@ -79,7 +79,7 @@ Prometheus's config:
|
|||||||
```yaml
|
```yaml
|
||||||
- job_name: ipx-play
|
- job_name: ipx-play
|
||||||
static_configs:
|
static_configs:
|
||||||
- targets: ["192.168.1.130:9189"]
|
- targets: ["192.168.1.130:9191"]
|
||||||
```
|
```
|
||||||
|
|
||||||
`play_http_request_duration_seconds{method,route,status}` (a page opened is `route="/e/{id}"`, an
|
`play_http_request_duration_seconds{method,route,status}` (a page opened is `route="/e/{id}"`, an
|
||||||
|
|||||||
Reference in New Issue
Block a user