From 9bbd01a74ded91feaf8bf24a4865fe604d6cf8f7 Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Sun, 22 Mar 2026 15:53:48 -0700 Subject: [PATCH] Route Navidrome through soulsync-player, add music-net network - Navidrome: traefik.enable=false (no longer directly exposed) - Navidrome: joins music-net external network for proxy access - Added music-net as external network declaration - Traffic to music.jefflix.lol now routed through soulsync-player PWA Co-Authored-By: Claude Opus 4.6 --- docker-compose.yml | 313 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 313 insertions(+) create mode 100644 docker-compose.yml diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..3623c11 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,313 @@ +services: + jellyfin: + image: jellyfin/jellyfin:latest + container_name: jellyfin + restart: unless-stopped + environment: + - PUID=1000 + - PGID=1000 + - TZ=Europe/Berlin + volumes: + - ./config/jellyfin:/config + - ./cache/jellyfin:/cache + # Hetzner Storage Box - all media served from here + - /mnt/hetzner-media/media:/media + networks: + - media-network + - traefik-public + labels: + - "traefik.enable=true" + - "traefik.http.routers.jellyfin.rule=Host(`movies.jeffemmett.com`) || Host(`movies.jefflix.lol`)" + - "traefik.http.routers.jellyfin.entrypoints=web" + - "traefik.http.routers.jellyfin.middlewares=jellyfin-headers" + - "traefik.http.services.jellyfin.loadbalancer.server.port=8096" + - "traefik.http.middlewares.jellyfin-headers.headers.customRequestHeaders.X-Forwarded-Proto=https" + - "traefik.docker.network=traefik-public" + + # Request Management - User-facing interface for media requests + jellyseerr: + image: fallenbagel/jellyseerr:latest + container_name: jellyseerr + restart: unless-stopped + environment: + - LOG_LEVEL=debug + - TZ=Europe/Berlin + volumes: + - ./config/jellyseerr:/app/config + networks: + - media-network + - traefik-public + labels: + - "traefik.enable=true" + - "traefik.http.routers.jellyseerr.rule=Host(`requests.jefflix.lol`)" + - "traefik.http.routers.jellyseerr.entrypoints=web" + - "traefik.http.routers.jellyseerr.middlewares=jellyseerr-headers" + - "traefik.http.services.jellyseerr.loadbalancer.server.port=5055" + - "traefik.http.middlewares.jellyseerr-headers.headers.customRequestHeaders.X-Forwarded-Proto=https" + - "traefik.docker.network=traefik-public" + + navidrome: + image: deluan/navidrome:latest + container_name: navidrome + restart: unless-stopped + user: 1000:1000 + environment: + - ND_SCANSCHEDULE=1h + - ND_LOGLEVEL=info + - ND_SESSIONTIMEOUT=24h + - ND_BASEURL= + - ND_ENABLETRANSCODINGCONFIG=true + - ND_TRANSCODINGCACHESIZE=1GB + - ND_IMAGECACHESIZE=500MB + volumes: + - ./config/navidrome:/data + # Hetzner Storage Box - music library + - /mnt/hetzner-media/media/music:/music:ro + networks: + - media-network + - music-net + labels: + # Traefik disabled — traffic routed through soulsync-player container + - "traefik.enable=false" + + sonarr: + image: linuxserver/sonarr:latest + container_name: sonarr + restart: unless-stopped + environment: + - PUID=1000 + - PGID=1000 + - TZ=Europe/Berlin + volumes: + - ./config/sonarr:/config + # Hetzner Storage Box - TV shows and downloads + - /mnt/hetzner-media/media/shows:/tv + - /mnt/hetzner-media/downloads:/downloads + networks: + - media-network + - traefik-public + labels: + - "traefik.enable=true" + - "traefik.http.routers.sonarr.rule=Host(`sonarr.jefflix.lol`)" + - "traefik.http.routers.sonarr.entrypoints=web" + - "traefik.http.services.sonarr.loadbalancer.server.port=8989" + - "traefik.docker.network=traefik-public" + + radarr: + image: linuxserver/radarr:latest + container_name: radarr + restart: unless-stopped + environment: + - PUID=1000 + - PGID=1000 + - TZ=Europe/Berlin + volumes: + - ./config/radarr:/config + # Hetzner Storage Box - movies and downloads + - /mnt/hetzner-media/media/movies:/movies + - /mnt/hetzner-media/downloads:/downloads + networks: + - media-network + - traefik-public + labels: + - "traefik.enable=true" + - "traefik.http.routers.radarr.rule=Host(`radarr.jefflix.lol`)" + - "traefik.http.routers.radarr.entrypoints=web" + - "traefik.http.services.radarr.loadbalancer.server.port=7878" + - "traefik.docker.network=traefik-public" + + prowlarr: + image: linuxserver/prowlarr:latest + container_name: prowlarr + restart: unless-stopped + environment: + - PUID=1000 + - PGID=1000 + - TZ=Europe/Berlin + volumes: + - ./config/prowlarr:/config + networks: + - media-network + - traefik-public + labels: + - "traefik.enable=true" + - "traefik.http.routers.prowlarr.rule=Host(`prowlarr.jefflix.lol`)" + - "traefik.http.routers.prowlarr.entrypoints=web" + - "traefik.http.services.prowlarr.loadbalancer.server.port=9696" + - "traefik.docker.network=traefik-public" + + lidarr: + image: linuxserver/lidarr:latest + container_name: lidarr + restart: unless-stopped + environment: + - PUID=1000 + - PGID=1000 + - TZ=Europe/Berlin + volumes: + - ./config/lidarr:/config + # Hetzner Storage Box - music and downloads + - /mnt/hetzner-media/media/music:/music + - /mnt/hetzner-media/downloads:/downloads + networks: + - media-network + - traefik-public + labels: + - "traefik.enable=true" + - "traefik.http.routers.lidarr.rule=Host(`lidarr.jefflix.lol`)" + - "traefik.http.routers.lidarr.entrypoints=web" + - "traefik.http.services.lidarr.loadbalancer.server.port=8686" + - "traefik.docker.network=traefik-public" + + # VPN for download privacy (optional - enable in .env) + gluetun: + image: qmcgaw/gluetun:latest + container_name: gluetun + restart: unless-stopped + cap_add: + - NET_ADMIN + devices: + - /dev/net/tun:/dev/net/tun + environment: + - VPN_SERVICE_PROVIDER=${VPN_PROVIDER:-mullvad} + - VPN_TYPE=wireguard + - WIREGUARD_PRIVATE_KEY=${VPN_WIREGUARD_PRIVATE_KEY:-} + - WIREGUARD_ADDRESSES=${VPN_WIREGUARD_ADDRESS:-} + - SERVER_COUNTRIES=${VPN_COUNTRY:-Germany} + - TZ=Europe/Berlin + volumes: + - ./config/gluetun:/gluetun + ports: + # qBittorrent WebUI + - 8080:8080 + # BitTorrent ports + - 6881:6881 + - 6881:6881/udp + networks: + - media-network + profiles: + - vpn + + # Download client - downloads directly to Hetzner Storage Box + qbittorrent: + image: linuxserver/qbittorrent:latest + container_name: qbittorrent + restart: unless-stopped + environment: + - PUID=1000 + - PGID=1000 + - TZ=Europe/Berlin + - WEBUI_PORT=8080 + volumes: + - ./config/qbittorrent:/config + # Hetzner Storage Box - all downloads go here + - /mnt/hetzner-media/downloads:/downloads + # When VPN enabled, use gluetun network + # network_mode: "service:gluetun" + networks: + - media-network + - traefik-public + labels: + - "traefik.enable=true" + - "traefik.http.routers.qbittorrent.rule=Host(`downloads.jefflix.lol`)" + - "traefik.http.routers.qbittorrent.entrypoints=web" + - "traefik.http.services.qbittorrent.loadbalancer.server.port=8080" + - "traefik.docker.network=traefik-public" + + # User Invitation System - Generate invite links for friends + wizarr: + image: ghcr.io/wizarrrr/wizarr:latest + container_name: wizarr + restart: unless-stopped + environment: + - APP_URL=https://invite.jefflix.lol + - TZ=Europe/Berlin + volumes: + - ./config/wizarr:/data/database + networks: + - media-network + - traefik-public + labels: + - "traefik.enable=true" + - "traefik.http.routers.wizarr.rule=Host(`invite.jeffemmett.com`) || Host(`invite.jefflix.lol`)" + - "traefik.http.routers.wizarr.entrypoints=web" + - "traefik.http.routers.wizarr.middlewares=wizarr-headers" + - "traefik.http.routers.wizarr.priority=1" + - "traefik.http.services.wizarr.loadbalancer.server.port=5690" + - "traefik.http.middlewares.wizarr-headers.headers.customRequestHeaders.X-Forwarded-Proto=https" + - "traefik.http.routers.wizarr-root.rule=(Host(`invite.jefflix.lol`) && Path(`/`))" + - "traefik.http.routers.wizarr-root.entrypoints=web" + - "traefik.http.routers.wizarr-root.middlewares=wizarr-root-redirect" + - "traefik.http.routers.wizarr-root.priority=10" + - "traefik.http.middlewares.wizarr-root-redirect.redirectregex.regex=^https?://invite.jefflix.lol/?$" + - "traefik.http.middlewares.wizarr-root-redirect.redirectregex.replacement=https://invite.jefflix.lol/j/RA05YZFRGD" + - "traefik.http.middlewares.wizarr-root-redirect.redirectregex.permanent=false" + - "traefik.docker.network=traefik-public" + + # Legacy Transmission (kept for compatibility, prefer qBittorrent) + transmission: + image: linuxserver/transmission:latest + container_name: transmission + restart: unless-stopped + environment: + - PUID=1000 + - PGID=1000 + - TZ=Europe/Berlin + - TRANSMISSION_WEB_HOME=/web + volumes: + - ./config/transmission:/config + - /mnt/hetzner-media/downloads:/downloads + - ./watch:/watch + ports: + - 9091:9091 + - 51413:51413 + - 51413:51413/udp + networks: + - media-network + profiles: + - legacy + + # File Browser - Web upload interface for community contributions + filebrowser: + image: filebrowser/filebrowser:latest + container_name: filebrowser + restart: unless-stopped + user: "0:0" + environment: + - TZ=Europe/Berlin + - FB_PORT=8080 + - FB_ADDRESS=0.0.0.0 + volumes: + - /mnt/hetzner-media/uploads:/srv/uploads + - ./config/filebrowser:/database + - ./config/filebrowser/settings.json:/config/settings.json:ro + command: + - --root=/srv/uploads + - --database=/database/filebrowser.db + - --address=0.0.0.0 + - --port=8080 + healthcheck: + test: ["CMD", "wget", "-q", "--spider", "http://127.0.0.1:8080/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 10s + labels: + - "traefik.enable=true" + - "traefik.http.routers.filebrowser.rule=Host(`upload.jefflix.lol`)" + - "traefik.http.routers.filebrowser.entrypoints=web" + - "traefik.http.routers.filebrowser.middlewares=filebrowser-headers" + - "traefik.http.services.filebrowser.loadbalancer.server.port=8080" + - "traefik.http.middlewares.filebrowser-headers.headers.customRequestHeaders.X-Forwarded-Proto=https" + - "traefik.docker.network=traefik-public" + networks: + - media-network + - traefik-public + +networks: + media-network: + driver: bridge + music-net: + external: true + traefik-public: + external: true