v1.0.0 · MIT · self-hosted · Docker Compose

Your 4K deserves more than 15 Mbps

uncompressed is a hardened arr stack with VPN namespace isolation, Tailscale-only ingress, and self-healing containers. A Docker Compose config you can actually trust.

bitrate · 2160p HDRmbps
Major stream compressed
15mbps
Standard stream 1080p
8mbps
Blu-ray disc remux
60mbps
delta+4× the data, all the grain, no artifacts
Install

Three commands. ~8 minutes.

Prereqs — Docker + Compose, a Tailscale account, ProtonVPN WireGuard keys, and a domain on Cloudflare DNS.

bash · 8m
# download & run the wizard (no git required)
$curl -L https://github.com/Lackoftactics/uncompressed/archive/main.tar.gz | tar xz
$cd uncompressed-main && ./setup.sh
HEADS UP · Before ./setup.sh, have your proton_wg_private_key, Tailscale hostname, and Cloudflare API token ready. The wizard asks for them interactively.
The pipeline

Request, fetch, serve — untouched.

Family member opens Seerr, taps a poster. Everything after is automatic and auditable.

01 · REQUEST
Seerr
/api/request
02 · SEARCH
Radarr · Sonarr
quality profile
03 · INDEX
Prowlarr
torznab feeds
04 · FETCH
qBittorrent
· VPN namespace
05 · SUBS
Bazarr
en, pl · forced
06 · SERVE
Jellyfin
direct-play / transcode
What's different

Not a tutorial. A production config.

Five opinions baked in, so you don't spend a weekend chasing Reddit threads about WireGuard kill switches.

01 · Leak-proof by construction

qBittorrent lives inside Gluetun's network namespace.

Not a firewall rule — a CLONE_NEWNET kernel boundary. If the tunnel drops, there is no network path. No egress, no DNS, no reconnect race condition.

▲ network-namespace: vpn_ns
qbittorrent:8080
─ eth0 ─
gluetun · wg0
↓ if wg0 dies, qBittorrent loses its only route. No fallback to host. No leak.
02 · Self-healing

Every container reports a heartbeat.

Endpoint-specific health checks (30–60s), ordered depends_on, autoheal restarts on red.

jellyfin● ok
radarr● ok
sonarr● ok
gluetun · wg0● ok
qbittorrent● ok
03 · Tailscale-only ingress

No ports open to the internet.

Traefik binds to the Tailscale IP only. HTTPS via Cloudflare DNS-01. Not on the mesh? No access, not even a login page.

  • 0 ports open on 0.0.0.0
  • traefik bound to 100.x.y.z
  • ACME via DNS, never HTTP
04 · Hardware transcoding

Intel Quick Sync mapped through /dev/dri.

Direct-play on Apple TV, Infuse, Swiftfin. Transcode only when a phone falls off cellular.

Direct play
~0.2% cpu
4K → 1080p QSV
~12% cpu
05 · Network segmentation

Three isolated Docker networks. No service talks to something it shouldn't.

traefik_proxytraefik · jellyfin · seerr · radarr · sonarr · prowlarr · bazarr · qbittorrentingress
arr_internalradarr · sonarr · prowlarr · bazarr · qbittorrent — internal:trueinternal
vpn_networkgluetun · qbittorrent (via network_mode: "service:gluetun")vpn
What you see

Real dashboards. Not dressed-up mocks.

What your library looks like once everything settles. Click through the apps below.

https://jellyfin.100.68.42.7.ts.net● connected via tailscale
Jellyfin library view showing movies, collections, and continue watching

Jellyfin library — movies, collections, continue watching. All served at full Blu-ray quality.

What's in the box

10 containers. One .env file.

Configured across two Compose stacks (infra/ and arr/), sharing a single secrets file.

media

Jellyfin

Media server · hardware transcoding via QSV

requests

Seerr

Request UI for movies & TV, per-user approval

tv

Sonarr

TV show automation, season packs, upgrades

movies

Radarr

Movie automation, quality profiles, renaming

indexers

Prowlarr

Indexer aggregation, one config, all apps

subs

Bazarr

Subtitle management, multi-language, forced

· vpn ns

qBittorrent

Torrent client, isolated inside VPN namespace

· vpn

Gluetun

WireGuard tunnel via ProtonVPN, kill-switch

ingress

Traefik

Reverse proxy, automatic HTTPS via ACME

health

Autoheal

Container health monitor, auto-restart on red

mesh

Tailscale

Host-level, not a container — your only ingress

ssl

Cloudflare

DNS-01 ACME for cert renewal. Control plane only.

Architecture

Cloudflare is control plane only.

Used as the ACME DNS-01 target for cert renewal. Never in the user-traffic path — Tailscale handles that end-to-end.

uncompressed architecture — Tailscale ingress to Traefik, routing to Jellyfin and the arr suite, with qBittorrent isolated inside Gluetun's VPN namespace
Ingress — Tailscale → Traefik Internal bridge (arr_internal) VPN namespace egress Control plane (ACME)
Hardware

Runs on a used NUC.

Not compatible with Raspberry Pi or ARM. Hardware transcoding requires Intel Quick Sync (7th gen+).

ComponentMinimumRecommended
CPUx86_64 quad-coreIntel w/ Quick Sync (7th gen+)
RAM8 GB16 GB
StorageSSD for configs + HDD for mediaNVMe + large HDD array
OSAny Linux with DockerUnraid
NetworkHome LAN + Tailscale node+ Gigabit uplink · IPv6

Stop watching a 15 Mbps imitation of your movie.

Clone the repo, run the wizard, come back in a weekend with a library you own.

Run the installerRead the README