--- type: reference description: "Plex Media Server is a **containerized media server on Dankserver**: a podman" tags: - dankserver - plex timestamp: 2026-09-15 --- # Plex Plex Media Server is a **containerized media server on Dankserver**: a podman quadlet (`plex.service`) under the systemd **user** generator, generated from `dankserver/plex/quadlet/plex.container`. It shares the host with a second live media server, [[Jellyfin]] (`jellyfin.service`, listening on 8096); both serve from the same read-only Entropy Volume mount. **Host:** Dankserver — **Ports:** 32400/tcp (PMS web + API), 32400 is the only port PMS needs for client streaming; LAN clients connect directly, public traffic can be fronted by Caddy like every other vhost. ## Facts | Item | Value | |------|-------| | Runtime | podman quadlet, `plex.service` (user manager) — migrated from the native `plexmediaserver.service` OS-package unit (2026-09) | | Image | `lscr.io/linuxserver/plex:1.43.4.10903-e5521bd8c-ls325` (pinned; verified == the ghcr `latest` manifest digest at pin time) | | Data root | `/var/lib/plexmediaserver` bind-mounted **in place** as `/config` (RW) — the migration moved zero bytes | | Media | `/mnt/entropy` mounted at the same absolute path **read-only** — every library path in the PMS database stayed valid, zero re-scan | | Identity | fleet rootless model — container root maps to the `dank` user (1000:1000); the deployer chowns the data root on first cutover | | 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 two R9700s stay dedicated to [[frank-archon]] | | Deploy | `./scripts/deploy.sh dankserver --service plex` | | Docs | https://support.plex.tv | ## Why in-place bind mounts The migration moved zero bytes: the container bind-mounts the native data root where it already lived, and the media archive re-mounts at `/mnt/entropy` inside the container, so every absolute library path in the PMS database keeps resolving. The one metadata change: rootless podman cannot map the real host uid 997, so the fleet model applies — container root runs as the `dank` user, and the deployer adopts the data root with `chown -R 1000:1000` on first cutover (rollback chowns it back). ## Cutover & rollback - First deploy stops and **masks** `plexmediaserver.service` (never `disable` — on these hosts `disable` deletes the unit file), chowns `/var/lib/plexmediaserver` to `1000:1000`, then starts the quadlet; the deployer blocks until `/identity` answers on 32400. - Rollback lever while masked: `systemctl --user stop plex.service && sudo chown -R 997:984 /var/lib/plexmediaserver && sudo systemctl unmask plexmediaserver.service && sudo systemctl start plexmediaserver.service` (ownership-only churn — zero bytes ever moved). - Decommission (`sudo apt-get -y purge plexmediaserver`) only after explicit operator sign-off. ## Integration points - **Caddy:** Plex is exempt from the Anubis bot challenge (plain-HTTP legacy clients cannot solve JS challenges) — [[Anubis]] "Exempt by construction". - **Tautulli** ([[Tautulli]]) is the companion: it polls PMS on the appnet for statistics and notifications and makes no sense without Plex. - **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 vhost ([[Authentik]], [[Caddy]]); direct `:32400` exposure to the LAN is unauthenticated by design (Plex owns its own auth via claim tokens). ## Gotchas 1. **Do not benchmark on it blind.** Transcoding is CPU-only now but still contends with the LLM fleet's host-RAM expert streaming; stop the service before benchmark runs, per the Benchmarking Policy. 2. **Updates are commit-driven, not apt.** The OS package is retired at 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 `.env`, never in this repo (secret rules apply). The token lives in `Preferences.xml` inside the RW data bind, preserved by the migration. 4. **Cold container boot is slow.** PMS pre-binds 32400 and empty-replies while the HTTP layer finishes loading; the first boot of a years-old library took ~10 minutes (2026-09 cutover). The deployer gate now allows 600 s before failing; later boots are much faster (warm page cache).