v0.8.0 — media tier (Navidrome / Kavita / Audiobookshelf)
Pre-releaseMedia tier
Three optional, self-hosted media servers — music, comics/ebooks, and audiobooks — all opt-in (ENABLE_*, off by default), loopback-bound, keeping their database/index/cache on ext4 ($HOME/.pocket/<app>) while the bulk library may live on the exFAT SD. Direct-play by default (no on-the-fly transcoding — a phone has no usable hardware transcode path; software transcode is the thermal/LMK heavy path and stays opt-in). Subsonic / OPDS / mobile API paths are reverse-proxied ahead of the optional auth gate and get a Cloudflare Access path exemption (or service token).
Added
- Navidrome (
ENABLE_NAVIDROME) →music.${DOMAIN}— a music-streaming server with its own web player and a Subsonic-compatible API. A single static Go binary (sha256-pinned). ForcesND_ADDRESS=127.0.0.1(Navidrome defaults to0.0.0.0) and asserts it. Subsonic/rest/*+/share/*are exempted from the gate. - Kavita (
ENABLE_KAVITA) →books.${DOMAIN}— a manga/comic/ebook server with an OPDS feed. A self-contained .NET arm64 build (sha256-pinned, needs systemlibicu72). Pre-seedsappsettings.jsonwithIpAddresses=127.0.0.1before first start (defaults to0.0.0.0,::) and asserts it; the JWTTokenKeyis generated off-argv. OPDS (/api/opds/*) is exempted. - Audiobookshelf (
ENABLE_AUDIOBOOKSHELF) →audiobooks.${DOMAIN}— an audiobook/podcast server with progress sync. Built from source from a pinned git tag (no arm64 release binary; first build is 15–40+ min, like Pingvin). ForcesHOST=127.0.0.1and asserts it; pins nativeffmpeg+ the nunicode SQLite extension (SKIP_BINARIES_CHECK=1). The mobile-app API paths are exempted. - docs/MEDIA.md — the three media apps with a per-app Resource & Risk section, the storage-tier and direct-play rules, the per-app Cloudflare Access exemptions, a photo-gallery roadmap note, and an honest "why Jellyfin is docs-only" note.
Roadmap (not in this release)
A photo gallery was scoped for this tier (candidate: Photoview) but is deferred to the roadmap. Its Go server hardcodes a 0.0.0.0 bind, and no userland mechanism available on this stack (proot on unrooted Android) can safely force it to loopback — Go issues bind() as a raw syscall that an LD_PRELOAD shim cannot intercept (verified: it listens on *:port with and without the shim), and ptrace / user-namespace / seccomp-notify rewriting is unavailable or unvalidatable here. Loopback-only binding is a non-negotiable security invariant in this stack, so a gallery ships only once a real loopback path exists. See docs/MEDIA.md.
Pre-release, part of the staged path to 1.0. All new apps are off by default. See the CHANGELOG.