The full compose file is available on GitHub.

Stack overview

  ┌──────────────────────────────────────────────────────────┐
  │                  nginx-proxy-manager                     │
  │                   :80 / :443 / :81                       │
  └──────┬────────────┬──────────────┬───────────────────────┘
         │            │              │        ../website/public
         ▼            ▼              ▼
    ┌────────┐   ┌─────────┐   ┌───────────┐
    │ jfa-go │──►│ jellyfin│◄─►│ jellyseer │
    │  :8056 │   │  :8096  │   │   :5055   │
    └────────┘   └────┬────┘   └─────┬─────┘
                      │              │
                      │              └───┬──────────┐
                      │                  ▼          ▼
                      │   ┌────────┐ ┌────────┐ ┌────────┐
                      ├──►│ bazarr │ │ radarr │ │ sonarr │
                      │   │ :6767  │ │ :7878  │ │ :8989  │
                      │   └───┬────┘ └───┬────┘ └───┬────┘
                      │       │          │          │
  ════════════════════╪═══════╪══════════╪══════════╪═════  ../media
                      │                  │          │
                      │                  └────┬─────┘
                      │                       ▼
                      │                  ┌───────────┐
                      │                  │  prowlarr │
                      │                  │   :9696   │
                      │                  └─────┬─────┘
                      │                        │
  ────────────────────│────────────────────────│──────────  watching vol
                      │                        │
                      │                        ▼
                      │     ┌────────────────────────────┐
                      │     │ transmission :9091         │
                      │     │   network_mode: vpn-router │
                      │     └────────────┬───────────────┘
  ════════════════════╧══════════════════╧════════════════  ../media
                                         │
                                         ▼
                                  ┌─────────────┐
                                  │  vpn-router │
                                  │  (openvpn)  │
                                  └─────────────┘

  ═══  shared media directory    ───  shared docker volume

Services

nginx-proxy-manager

Reverse proxy handling HTTP/HTTPS traffic and SSL termination via Let’s Encrypt. All services are exposed through it rather than directly. Management UI on port 81.

jellyfin

The media server itself. Streams movies, series and music to users. Uses Intel GPU passthrough (/dev/dri/renderD128) for hardware transcoding. Media is mounted from a shared ../media volume.

jellyseer

Request management frontend. Users can browse and request movies/series, which get forwarded to radarr and sonarr for automated downloading. Depends on jellyfin.

jfa-go

User account management for Jellyfin. Handles user invitations, password resets and account creation without needing direct Jellyfin admin access.

radarr

Automated movie management. Monitors requests from jellyseer, searches for releases via prowlarr, and sends downloads to transmission. Media library mounted at /library.

sonarr

Same as radarr but for TV series. Monitors new episodes, season packs and requests from jellyseer, searches via prowlarr and sends downloads to transmission. Media library mounted at /library.

bazarr

Automated subtitle management. Works alongside radarr and sonarr to download and manage subtitles for movies and series.

prowlarr

Indexer manager that centralizes torrent/usenet indexer configuration. Radarr and sonarr query prowlarr instead of managing indexers individually. Supports custom indexer definitions.

transmission

Torrent client. All its network traffic is routed through the vpn-router container via network_mode: service:vpn-router, so downloads are never exposed on the host’s public IP. Port 9091 is exposed on the vpn-router container instead.

vpn-router

OpenVPN client container that acts as a network gateway for transmission. Runs with FIREWALL=1 to kill traffic if the VPN drops.