docs: plex and tautulli runtime pages reflect the quadlet migration

- runtime rows: podman quadlet under the systemd user generator, pinned
  image digests, in-place bind mounts, identity model, appnet aliases
- cutover/rollback section on Plex.md (mask-native-unit lever, decommission
  gate); drop the false 'updates are apt-only' and 'snap refresh' gotchas
- update path is now deploy.sh dankserver --service plex|tautulli
This commit is contained in:
Frank committed 2026-09-01 22:31:38 -07:00
1 parent eebf2f6c7d
commit 592a0baa35
2 files changed
+67 -43

No files matched your search

+41 -25
View File
@@ -1,42 +1,56 @@
# Plex # Plex
Plex Media Server is the **native (non-container) media server running on Plex Media Server is the **containerized media server on Dankserver**: a
Dankserver**. It is the only media server actually listening on this host: podman quadlet (`plex.service`) under the systemd **user** generator,
`plexmediaserver.service` is an OS-package systemd unit generated from `dankserver/plex/quadlet/plex.container`. It is the only media
(`/usr/lib/systemd/system/plexmediaserver.service`), enabled and server actually listening on this host. Jellyfin, by contrast, is a research
running — verified live 2026-08-29. Jellyfin, by contrast, is a research
brief on this host, not a running service (see [[Jellyfin]]). brief on this host, not a running service (see [[Jellyfin]]).
**Host:** Dankserver — **Ports:** 32400/tcp (PMS web + API), 32400 is the **Host:** Dankserver — **Ports:** 32400/tcp (PMS web + API), 32400 is the
only port PMS needs for client streaming; LAN clients connect directly, only port PMS needs for client streaming; LAN clients connect directly,
public traffic can be fronted by Caddy like every other vhost. public traffic can be fronted by Caddy like every other vhost.
## Facts (live-verified 2026-08-29) ## Facts
| Item | Value | | Item | Value |
|------|-------| |------|-------|
| Runtime | native systemd service (`plexmediaserver.service`), **not** a podman quadlet | | Runtime | podman quadlet, `plex.service` (user manager) — migrated from the native `plexmediaserver.service` OS-package unit (2026-09) |
| State | enabled + running (up since 2026-08-21) | | Image | `lscr.io/linuxserver/plex:1.43.3.10896-cb3ebc72d-ls322` (pinned; verified == the ghcr `latest` manifest digest at pin time) |
| Port | `32400/tcp` on `0.0.0.0` | | Data root | `/var/lib/plexmediaserver` bind-mounted **in place** as `/config` (RW) — the migration moved zero bytes |
| Updates | OS package manager (`apt`) — **not** `scripts/deploy.sh`; the deploy flow never touches this service | | Media | `/mnt/entropy` mounted at the same absolute path **read-only** — every library path in the PMS database stayed valid, zero re-scan |
| GPU | RTX 3090 present; NVENC hardware transcode needs the NVIDIA driver + Plex Pass (PMS gates HW transcoding behind the paid tier) | | Identity | `UsernsMode=host` + `PUID=997 PGID=984` — container writes land owned 997:984, byte-compatible with the former native unit |
| Port | `32400/tcp` published on `0.0.0.0` — zero client reconfiguration |
| Network | `dankserver_appnet`, alias `plex`; Tautulli reaches it at `http://plex:32400` |
| GPU | none by decision — CPU decode only; the RTX 3090 stays dedicated to `frank-default-small` |
| Deploy | `./scripts/deploy.sh dankserver --service plex` |
| Docs | https://support.plex.tv | | Docs | https://support.plex.tv |
## Why it is not a quadlet ## Why in-place bind mounts
Plex ships as a distro package with its own systemd unit and update The migration moved zero bytes: the container bind-mounts the native data
channel; the repo's boot-persistence rule is satisfied by the native unit root where it already lived, and the media archive re-mounts at
(it is `enabled`, so it survives reboot — verify with `/mnt/entropy` inside the container, so every absolute library path in the
`systemctl is-enabled plexmediaserver`). Converting it to a container later PMS database keeps resolving. `UsernsMode=host` + `PUID=997/PGID=984` makes
is a migration, not a config edit: the PMS database (`/var/lib/plexmediaserver`) the container's file identity indistinguishable from the old service's —
and its claim-token identity would move with it. no chown, no re-scan. Rollback is byte-safe at any time before decommission.
## Cutover & rollback
- First deploy stops and **masks** `plexmediaserver.service` (never
`disable` — on these hosts `disable` deletes the unit file), then starts
the quadlet; the deployer blocks until `/identity` answers on 32400.
- Rollback lever while masked: `systemctl --user stop plex.service && sudo
systemctl unmask plexmediaserver.service && sudo systemctl start
plexmediaserver.service`.
- Decommission (`sudo apt-get -y purge plexmediaserver`) only after explicit
operator sign-off.
## Integration points ## Integration points
- **Caddy:** Plex is exempt from the Anubis bot challenge - **Caddy:** Plex is exempt from the Anubis bot challenge
(plain-HTTP legacy clients cannot solve JS challenges) — see (plain-HTTP legacy clients cannot solve JS challenges) — see
[[Anubis]] "Exempt by construction". [[Anubis]] "Exempt by construction".
- **Tautulli** ([[Tautulli]]) is the companion: it polls PMS on `:32400` - **Tautulli** ([[Tautulli]]) is the companion: it polls PMS on the appnet
for statistics and notifications and makes no sense without Plex. for statistics and notifications and makes no sense without Plex.
- **Auth wall:** if a public vhost is ever pointed at Plex, put the - **Auth wall:** if a public vhost is ever pointed at Plex, put the
Authentik outpost + Anubis chain in front of it like every other guarded Authentik outpost + Anubis chain in front of it like every other guarded
@@ -45,10 +59,12 @@ and its claim-token identity would move with it.
## Gotchas ## Gotchas
1. **Do not benchmark on it blind.** PMS transcodes contend with the LLM 1. **Do not benchmark on it blind.** Transcoding is CPU-only now but still
fleet for the same GPU; stop the service (or pin it to CPU contends with the LLM fleet's host-RAM expert streaming; stop the service
transcoding) before benchmark runs, per the Benchmarking Policy. before benchmark runs, per the Benchmarking Policy.
2. **Updates are OS-level** — `apt`/`aptly`, not `deploy.sh`; a deploy 2. **Updates are commit-driven, not apt.** The OS package is retired at
plan that names `plex` is a bug in the plan. cutover; upgrading PMS means pinning a new `-ls` tag in the unit file and
redeploying — never run `:latest`.
3. The claim token is the identity of this server; document it in the host 3. The claim token is the identity of this server; document it in the host
`.env`, never in this repo (secret rules apply). `.env`, never in this repo (secret rules apply). The token lives in
`Preferences.xml` inside the RW data bind, preserved by the migration.
+26 -18
View File
@@ -1,29 +1,34 @@
# Tautulli # Tautulli
Tautulli is the statistics, monitoring, and notification companion for Tautulli is the statistics, monitoring, and notification companion for
Plex Media Server. On Dankserver it runs as a **snap** Plex Media Server. On Dankserver it runs as a **podman quadlet**
(`snap.tautulli.tautulli.service`, verified live 2026-08-29) — a third (`tautulli.service`) under the systemd **user** generator, generated from
runtime style on this host alongside podman quadlets and the native Plex `dankserver/tautulli/quadlet/tautulli.container` — migrated from the snap
unit. It listens on `8181/tcp` on all interfaces. (2026-09; the snap carried zero config, so the cutover was a fresh install).
**Host:** Dankserver — **Depends on:** [[Plex]] (it is pointless without **Host:** Dankserver — **Depends on:** [[Plex]] (it is pointless without
it; it talks to PMS over `:32400` using the same claim token clients use). it; it talks to PMS over the appnet at `http://plex:32400`).
## Facts (live-verified 2026-08-29) ## Facts
| Item | Value | | Item | Value |
|------|-------| |------|-------|
| Runtime | snap (`snap.tautulli.tautulli.service`) — not a quadlet, not an OS package | | Runtime | podman quadlet, `tautulli.service` (user manager) — migrated from snap `snap.tautulli.tautulli.service` |
| State | running; snaps self-start at boot (no unit to enable) | | Image | `lscr.io/linuxserver/tautulli:v2.18.1-ls242` (pinned; verified == the ghcr `latest` manifest digest at pin time) |
| Port | `8181/tcp` on `0.0.0.0` | | Data root | `/home/dank/Containers/tautulli` bind-mounted as `/config` (fresh at cutover — the snap's `/var/snap/tautulli/common` was empty) |
| Updates | `snap refresh tautulli` — the snap store channel is the update path, not `deploy.sh` | | Identity | `UsernsMode=host` + `PUID=1000 PGID=1000` |
| Port | `8181/tcp` published on `0.0.0.0` |
| Network | `dankserver_appnet`, alias `tautulli` |
| PMS URL | `http://plex:32400` — seeded into `config.ini` by the deployer on first start |
| Health | in-container `python3` probe of `http://localhost:8181/home`, 30 s interval / 3 retries |
| Deploy | `./scripts/deploy.sh dankserver --service tautulli` |
| Docs | https://github.com/Tautulli/Tautulli/wiki | | Docs | https://github.com/Tautulli/Tautulli/wiki |
## What it buys this fleet ## What it buys this fleet
- Concurrent-stream dashboard and history: who is watching what, right now, - Concurrent-stream dashboard and history: who is watching what, right now,
on which client — the only tool that answers "is the 3090 busy on which client — the only tool that answers "is the CPU busy transcoding
transcoding for someone?" without SSHing in. for someone?" without SSHing in.
- Notifications: library updates, download completions, player watch - Notifications: library updates, download completions, player watch
sessions — wire them to whatever notifier the fleet standardizes on sessions — wire them to whatever notifier the fleet standardizes on
(Discord/ntfy/Telegram are all one dropdown away). (Discord/ntfy/Telegram are all one dropdown away).
@@ -37,9 +42,12 @@ it; it talks to PMS over `:32400` using the same claim token clients use).
anyone on the LAN can read the whole watch history. Fine while LAN-only; anyone on the LAN can read the whole watch history. Fine while LAN-only;
if a public vhost is ever pointed at it, put the Authentik + Anubis if a public vhost is ever pointed at it, put the Authentik + Anubis
chain in front first ([[Authentik]], [[Anubis]]). chain in front first ([[Authentik]], [[Anubis]]).
2. **Snap confinement.** Logs live under `/var/snap/tautulli/common`, not 2. **First boot shows the setup wizard** — expected pre-token behavior; the
the conventional `/config` path quadlet services use — Grafana/Loki wizard also answers 200 on `/home`, so the health gate stays green before
log-shipping paths must account for it ([[Loki]], [[Alloy]]). any token exists. Enter the PMS claim token through the web UI after
3. If Plex is ever containerized or migrated, Tautulli's claim-token cutover; it is stored inside the config bind, never in this repo.
handling survives (it stores its own copy) but re-verify the PMS URL 3. **Snap-era paths are gone.** Logs and config live under the config bind
and port in its settings immediately after the migration. (`/home/dank/Containers/tautulli/...`), not `/var/snap/tautulli/common` —
Grafana/Loki log-shipping paths must account for it ([[Loki]], [[Alloy]]).
4. **Updates are commit-driven** — pin a new `-ls` tag in the unit file and
redeploy; never run `:latest`.