I didn't need a VPN or separate compose stack as my docker (Portainer) server is reachable via tailscale. I also have way too many other containers to use common ports like 8080. That said, the config needed a lot of other changes to run today (a few days before 2026) so in case it helps someone else, this is what finally worked:
services:
# Jellyfin - Media Server
jellyfin:
image: ghcr.io/linuxserver/jellyfin:latest
container_name: jellyfin
environment:
- JELLYFIN_PublishedServerUrl=${JELLYFIN_URL}
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
ports:
- 11000:8096
- 11001:8920
devices:
- /dev/dri:/dev/dri
volumes:
- ${BASE_PATH}/jellyfin/config:/config
- ${MEDIA_SHARE}/media:/media
restart: unless-stopped
networks:
- proxy
- starr
# Radarr - Movies
radarr:
image: ghcr.io/linuxserver/radarr:latest
container_name: radarr
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
volumes:
- ${BASE_PATH}/radarr/config:/config
- ${MEDIA_SHARE}:/data
ports:
- 11002:7878
networks:
- proxy
- starr
restart: unless-stopped
# Sonarr - TV Shows
sonarr:
image: ghcr.io/linuxserver/sonarr:latest
container_name: sonarr
environment:
- PUID=${PUID}
- PGID=${PGID}
volumes:
- ${BASE_PATH}/sonarr/config:/config
- ${MEDIA_SHARE}:/data
ports:
- 11003:8989
networks:
- proxy
- starr
restart: unless-stopped
# Readarr - Books (Pinned to last working version due to project retirement)
readarr:
image: ghcr.io/linuxserver/readarr:0.4.18-develop
container_name: readarr
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
volumes:
- ${BASE_PATH}/readarr/config:/config
- ${MEDIA_SHARE}:/data
ports:
- 11004:8787
networks:
- proxy
- starr
restart: unless-stopped
# Lidarr - Music
lidarr:
image: ghcr.io/linuxserver/lidarr:latest
container_name: lidarr
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
volumes:
- ${BASE_PATH}/lidarr/config:/config
- ${MEDIA_SHARE}:/data
ports:
- 11005:8686
networks:
- proxy
- starr
restart: unless-stopped
# Kapowarr - Comics
kapowarr:
image: mrcas/kapowarr:latest
container_name: kapowarr
environment:
- PUID=${PUID}
- PGID=${PGID}
ports:
- 11006:5757
volumes:
- ${BASE_PATH}/kapowarr/config:/app/db
- ${MEDIA_SHARE}/temp_downloads:/app/temp_downloads
- ${MEDIA_SHARE}:/data
restart: unless-stopped
networks:
- starr
# Prowlarr - Indexer Manager
prowlarr:
image: ghcr.io/linuxserver/prowlarr:latest
container_name: prowlarr
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
ports:
- 11007:9696
volumes:
- ${BASE_PATH}/prowlarr/config:/config
networks:
- starr
restart: unless-stopped
# Autobrr - IRC Torrent Grabber
autobrr:
image: ghcr.io/autobrr/autobrr:latest
container_name: autobrr
environment:
- TZ=${TZ}
- PUID=${PUID}
- PGID=${PGID}
ports:
- 11008:7474
volumes:
- ${BASE_PATH}/autobrr/config:/config
networks:
- starr
restart: unless-stopped
# Jellyseerr - Requests
jellyseerr:
image: fallenbagel/jellyseerr:latest
container_name: jellyseerr
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
volumes:
- ${BASE_PATH}/jellyseerr/config:/app/config
- ${MEDIA_SHARE}:/data
networks:
- proxy
- starr
ports:
- 11009:5055
restart: unless-stopped
# FlareSolverr (Pinned to stable release)
flaresolverr:
image: ghcr.io/flaresolverr/flaresolverr:v3.3.21
container_name: flaresolverr
environment:
- LOG_LEVEL=info
- TZ=${TZ}
ports:
- 11010:8191
networks:
- starr
restart: unless-stopped
# qBittorrent - Download Client
qbittorrent:
image: ghcr.io/linuxserver/qbittorrent:latest
container_name: qbittorrent
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
- WEBUI_PORT=8080
ports:
- 11011:8080
- 11012:8694
- 11012:8694/udp
volumes:
- ${BASE_PATH}/qbittorent/config:/config
- ${MEDIA_SHARE}:/data
networks:
- starr
- proxy
restart: unless-stopped
# Tdarr - Transcoding
tdarr:
image: ghcr.io/haveagitgat/tdarr:latest
container_name: tdarr
ports:
- 11013:8265
- 11014:8266
environment:
- TZ=${TZ}
- PUID=${PUID}
- PGID=${PGID}
- nodeName=ServerNode
- serverIP=0.0.0.0
- internalNode=true
- ffmpegVersion=6
volumes:
- ${BASE_PATH}/tdarr/server:/app/server
- ${BASE_PATH}/tdarr/configs:/app/configs
- ${BASE_PATH}/tdarr/logs:/app/logs
- ${MEDIA_SHARE}:/data
- ${TRANSCODE_PATH:-/transcode_cache}:/temp
devices:
- /dev/dri:/dev/dri
networks:
- proxy
- starr
restart: unless-stopped
# Bazarr - Subtitles
bazarr:
image: ghcr.io/linuxserver/bazarr:latest
container_name: bazarr
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
ports:
- 11015:6767
volumes:
- ${BASE_PATH}/bazarr/config:/config
- ${MEDIA_SHARE}:/data
networks:
- starr
restart: unless-stopped
# Homarr - Dashboard
homarr:
image: ghcr.io/homarr-labs/homarr:latest
container_name: homarr
environment:
- SECRET_ENCRYPTION_KEY=${HOMARR_KEY}
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ${BASE_PATH}/homarr:/appdata
ports:
- 11016:7575
networks:
- proxy
- starr
restart: unless-stopped
# Jellystat DB
jellystat-db:
image: postgres:15-alpine
container_name: jellystat-db
environment:
- POSTGRES_DB=jfstat
- POSTGRES_USER=${JELLYSTATDB_USER:-postgres}
- POSTGRES_PASSWORD=${JELLYSTATDB_PASS:-password}
volumes:
- ${BASE_PATH}/jellystat/postgres-data:/var/lib/postgresql/data
networks:
- starr
restart: unless-stopped
# Jellystat (Corrected image path)
jellystat:
image: cyfershepard/jellystat:latest
container_name: jellystat
environment:
- POSTGRES_USER=${JELLYSTATDB_USER:-postgres}
- POSTGRES_PASSWORD=${JELLYSTATDB_PASS:-password}
- POSTGRES_IP=jellystat-db
- POSTGRES_PORT=5432
- JWT_SECRET=${JWT_SECRET:-'my-secret-jwt-key'}
ports:
- 11017:3000
volumes:
- ${BASE_PATH}/jellystat/postgres-backup:/app/backend/backup-data
depends_on:
- jellystat-db
networks:
- proxy
- starr
restart: unless-stopped
networks:
proxy:
driver: bridge
starr:
driver: bridge
env:
PUID=1000
PGID=1000
TZ=America/Chicago
BASE_PATH=/home/user/appdata
MEDIA_SHARE=/mnt/media
TRANSCODE_PATH=/dev/shm
JELLYFIN_URL=https://jellyfin.example.com
WIZARR_URL=https://wizarr.example.com
SONARR_KEY=your_sonarr_api_key_here
RADARR_KEY=your_radarr_api_key_here
LIDARR_KEY=your_lidarr_api_key_here
READARR_KEY=your_readarr_api_key_here
HOMARR_KEY=your_secret_encryption_key_here
QBIT_USER=admin
QBIT_PASS=adminadmin
JELLYSTATDB_USER=postgres
JELLYSTATDB_PASS=password
JWT_SECRET=generate_a_random_string_here
I didn't need a VPN or separate compose stack as my docker (Portainer) server is reachable via tailscale. I also have way too many other containers to use common ports like 8080. That said, the config needed a lot of other changes to run today (a few days before 2026) so in case it helps someone else, this is what finally worked:
env: