Jellyseerr Multimedia Stack
Yes I have tested it and it works just fine, however it can be complicated to setup beyond just the stack. There is considerable work required that cant be automated with each service as it flows down the chain.
This stack is not for a novice but its not rocket science either, but yes it is a pain in the arse to configure as you have numerous services to get running and bug free for that "click" to work seamlessly.
Purpose
Find a movie or a series via Jelllyseer. Click on the appropriate icon. Watch a trailer, read the breakdown, request the movie. The rest should just happen. Simple.
This is your own multimedia server with a request function, and index function and it talks directly to Jellyfin. Nice, neat and tidy.
Yeah right.
Notes
- The stack is self explanatory
- You will need to setup your reverse proxy and your cname entries in your DNS server - do this first.
- You will need to setup Jellyseer via settings, adding Jellyfin, users, services, and so on.
- The qbittorrent server will require a new admin username and password. Sort this once the stack comes up, and dont forget the password. It requires hacking to reset it.
- The API Keys you will need to change and I cant remember how I did it. Sorry this is not my day job (I do this for fun to exercise my mind).
- Mine is CUDA enabled. You may need to remove this part.
- I built my stack for Podman not Docker but you should be able to figure it out.
The Multimedia Stack
As per below.
# =============================================================================
# Multimedia Media Stack — baden.braedach.com
# =============================================================================
# Services: Jellyfin, Jellyseerr, Sonarr, Radarr, Prowlarr, Bazarr,
# Flaresolverr, qBittorrent
# Host: baden — Proxmox LXC, NVIDIA RTX 3070 (CDI)
# Runtime: Podman (rootful) with Docker Compose compatibility
# Network: jellyfin-net (internal, defined in this file)
# UID/GID: 1000:1000 — set via PUID/PGID (linuxserver) or entrypoint env
# Proxy: Zoraxy reverse proxy via Cloudflare tunnel (braedach.com)
# CNAME: All CNAMEs point to proxy, not container IPs
#
# Reviewed: 10-05-2026
# Version: 1.0.0
# =============================================================================
#
# Volume layout expected on host (create before first run):
# sudo mkdir -p \
# /srv/jellyfin/{cache,config,media/movies,media/series,music} \
# /srv/jellyseerr/config \
# /srv/sonarr/config \
# /srv/radarr/config \
# /srv/prowlarr/config \
# /srv/bazarr/config \
# /srv/qbittorrent/{config,downloads,downloads/incomplete,plugins}
# sudo chown -R 1000:1000 /srv/jellyfin /srv/jellyseerr /srv/sonarr \
# /srv/radarr /srv/prowlarr /srv/bazarr /srv/qbittorrent
#
# GPU passthrough:
# CDI configured via setup-lxc-gpu.sh on pxe/baden.
# Jellyfin uses NVENC/NVDEC for hardware transcoding — enable in:
# Dashboard > Playback > Transcoding > NVIDIA NVENC
#
# Podman notes:
# - Do NOT add a 'user:' directive to linuxserver images — it conflicts
# with s6-overlay init which handles UID/GID internally via PUID/PGID.
# - Jellyfin uses its own entrypoint; pre-chown volumes as shown above.
# - No :U flag needed — redundant in rootful Podman without user: set.
# - FlareSolverr runs as root internally; PUID/PGID not supported.
# - Watchtower disabled on all services — update manually or via script.
# =============================================================================
name: multimedia-stack
services:
# ---------------------------------------------------------------------------
# Jellyfin — Media Server
# ---------------------------------------------------------------------------
jellyfin:
container_name: jellyfin
hostname: jellyfin
image: jellyfin/jellyfin:latest
restart: always
labels:
- com.docker.compose.project=jellyfin-stack
- com.docker.compose.service=jellyfin
- homepage.group=Media
- homepage.name=Jellyfin
- homepage.href=https://jellyfin.baden.braedach.com
- homepage.icon=jellyfin.png
- com.centurylinklabs.watchtower.enable=false
ports:M Media
- "8096:8096" # HTTP — primary UI / API
- "8920:8920" # HTTPS (TLS terminated at Zoraxy)
- "7359:7359/udp" # LAN client auto-discovery
- "1900:1900/udp" # DLNA SSDP multicast
environment:
- TZ=Australia/Perth
- JELLYFIN_PublishedServerUrl=https://jellyfin.baden.braedach.com
volumes:
- /srv/jellyfin/cache:/cache
- /srv/jellyfin/config:/config
- /srv/jellyfin/media/movies:/movies
- /srv/jellyfin/media/series:/series
- /srv/jellyfin/music:/music
- /etc/localtime:/etc/localtime:ro
devices:
# Podman CDI — NVIDIA RTX 3070 passthrough (configured via setup-lxc-gpu.sh)
- nvidia.com/gpu=all
cap_add:
- SYS_TIME
security_opt:
- no-new-privileges:true
healthcheck:
test: ["CMD-SHELL", "curl -sf http://localhost:8096/health || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
networks:
- jellyfin-net
# ---------------------------------------------------------------------------
# Jellyseerr — Media Request Management
# ---------------------------------------------------------------------------
jellyseerr:
container_name: jellyseerr
hostname: jellyseerr
image: ghcr.io/seerr-team/seerr:latest
restart: always
labels:
- com.docker.compose.project=jellyfin-stack
- com.docker.compose.service=jellyseerr
- homepage.group=Media
- homepage.name=Jellyseerr
- homepage.href=https://jellyseerr.baden.braedach.com
- homepage.icon=jellyseerr.png
- com.centurylinklabs.watchtower.enable=false
ports:
- "5055:5055"
environment:
- TZ=Australia/Perth
- LOG_LEVEL=info
# Pre-seeds Jellyfin connection on first run (ignored if config already exists)
- JELLYFIN_URL=http://jellyfin:8096
- RADARR_URL=http://radarr:7878
- RADARR_API_KEY=[your-radarr-api-key]
- SONARR_URL=http://sonarr:8989
- SONARR_API_KEY=[your-sonarr-api-key]
volumes:
- /srv/jellyseerr/config:/app/config
- /etc/localtime:/etc/localtime:ro
depends_on:
jellyfin:
condition: service_healthy
security_opt:
- no-new-privileges:true
healthcheck:
test: wget --no-verbose --tries=1 --spider http://localhost:5055/api/v1/settings/public || exit 1
start_period: 20s
timeout: 3s
interval: 15s
retries: 3
networks:
- jellyfin-net
# ---------------------------------------------------------------------------
# Sonarr — TV Series Automation
# ---------------------------------------------------------------------------
sonarr:
container_name: sonarr
hostname: sonarr
image: lscr.io/linuxserver/sonarr:latest
restart: always
labels:
- com.docker.compose.project=jellyfin-stack
- com.docker.compose.service=sonarr
- com.centurylinklabs.watchtower.enable=false
ports:
- "8989:8989"
environment:
- TZ=Australia/Perth
- PUID=1000
- PGID=1000
- SONARR__LOG__LEVEL=info
- SONARR__ANALYTICS__ENABLED=false
# External auth — Zoraxy handles access control; disable Sonarr's own login
- SONARR__AUTH__METHOD=External
- SONARR__AUTH__REQUIRED=DisabledForLocalAddresses
volumes:
- /srv/sonarr/config:/config
- /srv/jellyfin/media/series:/series
- /srv/qbittorrent/downloads:/downloads
- /etc/localtime:/etc/localtime:ro
depends_on:
- prowlarr
- qbittorrent
security_opt:
- no-new-privileges:true
healthcheck:
test: ["CMD-SHELL", "curl -sf http://localhost:8989/ping || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
networks:
- jellyfin-net
# ---------------------------------------------------------------------------
# Radarr — Movie Automation
# ---------------------------------------------------------------------------
radarr:
container_name: radarr
hostname: radarr
image: lscr.io/linuxserver/radarr:latest
restart: always
labels:
- com.docker.compose.project=jellyfin-stack
- com.docker.compose.service=radarr
- com.centurylinklabs.watchtower.enable=false
ports:
- "7878:7878"
environment:
- TZ=Australia/Perth
- PUID=1000
- PGID=1000
- RADARR__LOG__LEVEL=info
- RADARR__ANALYTICS__ENABLED=false
# External auth — Zoraxy handles access control; disable Radarr's own login
- RADARR__AUTH__METHOD=External
- RADARR__AUTH__REQUIRED=DisabledForLocalAddresses
volumes:
- /srv/radarr/config:/config
- /srv/jellyfin/media/movies:/movies
- /srv/qbittorrent/downloads:/downloads
- /etc/localtime:/etc/localtime:ro
depends_on:
- prowlarr
- qbittorrent
security_opt:
- no-new-privileges:true
healthcheck:
test: ["CMD-SHELL", "curl -sf http://localhost:7878/ping || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
networks:
- jellyfin-net
# ---------------------------------------------------------------------------
# Prowlarr — Indexer Management (feeds Sonarr + Radarr)
# ---------------------------------------------------------------------------
prowlarr:
container_name: prowlarr
hostname: prowlarr
image: lscr.io/linuxserver/prowlarr:latest
restart: always
labels:
- com.docker.compose.project=jellyfin-stack
- com.docker.compose.service=prowlarr
- com.centurylinklabs.watchtower.enable=false
ports:
- "9696:9696"
environment:
- TZ=Australia/Perth
- PUID=1000
- PGID=1000
- PROWLARR__LOG__LEVEL=info
- PROWLARR__ANALYTICS__ENABLED=false
# External auth — Zoraxy handles access control; disable Prowlarr's own login
- PROWLARR__AUTH__METHOD=External
- PROWLARR__AUTH__REQUIRED=DisabledForLocalAddresses
volumes:
- /srv/prowlarr/config:/config
- /etc/localtime:/etc/localtime:ro
depends_on:
flaresolverr:
condition: service_healthy
security_opt:
- no-new-privileges:true
healthcheck:
test: ["CMD-SHELL", "curl -sf http://localhost:9696/ping || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
networks:
- jellyfin-net
# ---------------------------------------------------------------------------
# Bazarr — Subtitle Automation (linked to Sonarr + Radarr)
# ---------------------------------------------------------------------------
bazarr:
container_name: bazarr
hostname: bazarr
image: lscr.io/linuxserver/bazarr:latest
restart: always
labels:
- com.docker.compose.project=jellyfin-stack
- com.docker.compose.service=bazarr
- com.centurylinklabs.watchtower.enable=false
ports:
- "6767:6767"
environment:
- TZ=Australia/Perth
- PUID=1000
- PGID=1000
- BAZARR__LOG__LEVEL=info
volumes:
- /srv/bazarr/config:/config
- /srv/jellyfin/media/movies:/movies
- /srv/jellyfin/media/series:/series
- /etc/localtime:/etc/localtime:ro
depends_on:
sonarr:
condition: service_healthy
radarr:
condition: service_healthy
security_opt:
- no-new-privileges:true
healthcheck:
test: ["CMD-SHELL", "curl -sf http://localhost:6767/api/v1/status || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
networks:
- jellyfin-net
# ---------------------------------------------------------------------------
# FlareSolverr — Cloudflare Challenge Bypass (used by Prowlarr)
# ---------------------------------------------------------------------------
flaresolverr:
container_name: flaresolverr
hostname: flaresolverr
image: ghcr.io/flaresolverr/flaresolverr:latest
restart: always
labels:
- com.docker.compose.project=jellyfin-stack
- com.docker.compose.service=flaresolverr
- com.centurylinklabs.watchtower.enable=false
ports:
- "8191:8191"
environment:
- TZ=Australia/Perth
- LOG_LEVEL=info
- LOG_HTML=false
- CAPTCHA_SOLVER=none
# FlareSolverr runs as root internally; PUID/PGID not supported
security_opt:
- no-new-privileges:true
healthcheck:
test: ["CMD-SHELL", "curl -sf http://localhost:8191/ || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 20s
networks:
- jellyfin-net
# ---------------------------------------------------------------------------
# qBittorrent — Download Client
# ---------------------------------------------------------------------------
# Plugin notes:
# Search plugins are Python scripts installed at:
# /config/data/nova3/engines/ (linuxserver image path)
# The /plugins bind-mount maps /srv/qbittorrent/plugins on the host to
# that path, making plugin installation/removal host-manageable.
# Python 3 is required for search plugins — provided by the
# linuxserver/mods:qbittorrent-search-plugins docker mod below.
#
# Incomplete downloads land in /downloads/incomplete and are moved to
# /downloads on completion. Configure both paths in:
# Tools > Options > Downloads > Save files to / Keep incomplete in
# ---------------------------------------------------------------------------
qbittorrent:
container_name: qbittorrent
hostname: qbittorrent
image: lscr.io/linuxserver/qbittorrent:latest
restart: always
labels:
- com.docker.compose.project=jellyfin-stack
- com.docker.compose.service=qbittorrent
- homepage.group=Media Automation
- homepage.name=qBittorrent
- homepage.href=https://qbittorrent.baden.braedach.com
- homepage.icon=qbittorrent.png
- com.centurylinklabs.watchtower.enable=false
ports:
- "8980:8980" # Web UI
- "6881:6881" # BitTorrent TCP
- "6881:6881/udp" # BitTorrent UDP
environment:
- TZ=Australia/Perth
- PUID=1000
- PGID=1000
- WEBUI_PORT=8980
# Linuxserver mod — installs Python 3 + search plugin support
- DOCKER_MODS=linuxserver/mods:qbittorrent-search-plugins
volumes:
- /srv/qbittorrent/config:/config
- /srv/qbittorrent/downloads:/downloads
- /srv/qbittorrent/downloads/incomplete:/downloads/incomplete
- /srv/qbittorrent/plugins:/config/data/nova3/engines
- /etc/localtime:/etc/localtime:ro
security_opt:
- no-new-privileges:true
healthcheck:
test: ["CMD-SHELL", "curl -sf http://localhost:8980/ || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 45s
networks:
- jellyfin-net
networks:
jellyfin-net:
name: jellyfin-net
driver: bridge
Prerequisites
- You need some serious storage - this is local in this configuration
- CUDA support for Jellyfin is not standard - refer to their documentation
- FIrewall exemptions - depending on your firewall it can get rather annoying
- Geoblocking can greatly affect the performance of your P2P server. Consideration is required.
I will not expand on this post. It is simply an example of some of the stuff that I like playing with, and its pushing my dated server rather hard, when fully employed.
Anyway - have fun.
#enoughsaid