# /opt/stacks/plex/docker-compose.yml services: # ───────────────────────────────────────── # PLEX # ───────────────────────────────────────── plex: image: lscr.io/linuxserver/plex:latest container_name: plex restart: unless-stopped network_mode: host # Necessari per a Plex discovery (mDNS/DLNA) group_add: - "${VIDEO_GID:-44}" # grup 'video' per a GPU - "${RENDER_GID:-992}" # grup 'render' per a /dev/dri environment: PUID: ${PUID} PGID: ${PGID} TZ: ${TZ} VERSION: docker PLEX_CLAIM: ${PLEX_CLAIM} devices: - /dev/dri/renderD128:/dev/dri/renderD128 - /dev/dri/card0:/dev/dri/card0 volumes: - ${DATA_DIR}/plex/config:/config - ${RIVEN_MOUNT}:/mnt/riven:rslave - ${PD_ZURG_MOUNT}:/mnt/pd_zurg:rslave - ${TORBOX_MOUNT}:/mnt/torbox_zurg:rslave - ${MEDIA_SERIES}:/mnt/media/series:ro - ${MEDIA_MOVIES}:/mnt/media/pelis:ro depends_on: - pd_zurg - torbox_mount # ───────────────────────────────────────── # PD_ZURG — Real-Debrid + Zurg + rclone # ───────────────────────────────────────── pd_zurg: image: iampuid0/pd_zurg:latest container_name: pd_zurg restart: unless-stopped stdin_open: true tty: true devices: - /dev/fuse:/dev/fuse:rwm cap_add: - SYS_ADMIN security_opt: - apparmor:unconfined environment: TZ: ${TZ} ZURG_ENABLED: "true" RD_API_KEY: ${RD_API_KEY} RCLONE_MOUNT_NAME: pd_zurg PD_ENABLED: "true" PLEX_USER: ${PLEX_USER} PLEX_TOKEN: ${PLEX_TOKEN} PLEX_ADDRESS: ${PLEX_ADDRESS} volumes: - ${DATA_DIR}/pd_zurg/config:/config - ${DATA_DIR}/pd_zurg/log:/log - ${DATA_DIR}/pd_zurg/cache:/cache - ${DATA_DIR}/pd_zurg/RD:/zurg/RD - ${PD_ZURG_MOUNT}:/data:shared # ───────────────────────────────────────── # TORBOX MOUNT — Torbox WebDAV via rclone # ───────────────────────────────────────── torbox_mount: image: rclone/rclone:latest container_name: torbox_mount restart: unless-stopped devices: - /dev/fuse:/dev/fuse:rwm cap_add: - SYS_ADMIN security_opt: - apparmor:unconfined environment: TZ: ${TZ} command: > mount torbox: /data --config /config/rclone.conf --allow-other --allow-non-empty --dir-cache-time 10s --vfs-cache-mode full --vfs-cache-max-size 512M --no-modtime --log-level INFO volumes: - ${DATA_DIR}/torbox_mount/config:/config - ${TORBOX_MOUNT}:/data:shared # ───────────────────────────────────────── # SEERR — Gestor de peticions # ───────────────────────────────────────── seerr: image: ghcr.io/seerr-team/seerr:latest container_name: seerr restart: unless-stopped environment: TZ: ${TZ} volumes: - ${DATA_DIR}/seerr/config:/app/config ports: - "5055:5055" # Web UI → via Nginx Proxy Manager networks: - shared_net # ───────────────────────────────────────── # RIVEN — PostgreSQL # ───────────────────────────────────────── riven-postgres: image: postgres:17-alpine container_name: riven-postgres restart: unless-stopped environment: TZ: ${TZ} POSTGRES_USER: ${RIVEN_POSTGRES_USER} POSTGRES_PASSWORD: ${RIVEN_POSTGRES_PASSWORD} POSTGRES_DB: ${RIVEN_POSTGRES_DB} volumes: - riven_postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U ${RIVEN_POSTGRES_USER} -d ${RIVEN_POSTGRES_DB}"] interval: 10s timeout: 5s retries: 5 start_period: 30s networks: - riven_net # ───────────────────────────────────────── # RIVEN — Redis # ───────────────────────────────────────── riven-redis: image: redis:7-alpine container_name: riven-redis restart: unless-stopped environment: TZ: ${TZ} volumes: - riven_redis_data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 5s retries: 5 start_period: 10s networks: - riven_net # ───────────────────────────────────────── # RIVEN — Backend API # ───────────────────────────────────────── riven: image: ghcr.io/rivenmedia/riven-ts:sha-a367778 # Pinnat a SHA per estabilitat container_name: riven restart: unless-stopped tty: true cap_add: - SYS_ADMIN security_opt: - apparmor:unconfined devices: - /dev/fuse:/dev/fuse extra_hosts: - "host.docker.internal:host-gateway" environment: TZ: ${TZ} NODE_ENV: production # Era 'development' — canviat a production RIVEN_SETTING__databaseUrl: "postgresql://${RIVEN_POSTGRES_USER}:${RIVEN_POSTGRES_PASSWORD}@riven-postgres:5432/${RIVEN_POSTGRES_DB}" RIVEN_SETTING__redisUrl: "redis://riven-redis:6379" RIVEN_SETTING__gqlHost: "0.0.0.0" RIVEN_SETTING__gqlCorsOrigin: ${RIVEN_CORS_ORIGIN} # ⚠️ CSRF desactivat — només acceptable en xarxa privada/VPN RIVEN_SETTING__csrfPrevention: "false" APOLLO_CSRF_PREVENTION_ENABLED: "false" RIVEN_SETTING__enabledPlugins: '["stremthru","plex","tmdb","tvdb","seerr"]' RIVEN_PLUGIN_SETTING__REPO_PLUGIN_TMDB__apiKey: ${TMDB_API_KEY} RIVEN_PLUGIN_SETTING__REPO_PLUGIN_TVDB__apiKey: ${TVDB_API_KEY} RIVEN_PLUGIN_SETTING__REPO_PLUGIN_STREMTHRU__realdebridApiKey: ${RD_API_KEY} RIVEN_PLUGIN_SETTING__REPO_PLUGIN_STREMTHRU__torboxApiKey: ${TORBOX_API_KEY} RIVEN_PLUGIN_SETTING__REPO_PLUGIN_PLEX__plexServerUrl: ${PLEX_ADDRESS} RIVEN_PLUGIN_SETTING__REPO_PLUGIN_PLEX__plexToken: ${PLEX_TOKEN} RIVEN_PLUGIN_SETTING__REPO_PLUGIN_SEERR__apiKey: ${SEERR_API_KEY} RIVEN_PLUGIN_SETTING__REPO_PLUGIN_SEERR__url: ${SEERR_URL} RIVEN_PLUGIN_SETTING__REPO_PLUGIN_SEERR__autofixMetadataProviders: "true" RIVEN_SETTING__vfsMountPath: /mnt/riven volumes: - riven_data:/riven/data - ${RIVEN_MOUNT}:/mnt/riven:shared depends_on: riven-postgres: condition: service_healthy riven-redis: condition: service_healthy seerr: condition: service_started pd_zurg: condition: service_started networks: - riven_net - shared_net # ───────────────────────────────────────── # RIVEN — Frontend UI # ───────────────────────────────────────── riven-frontend: image: ghcr.io/rivenmedia/riven-frontend:latest container_name: riven-frontend restart: unless-stopped tty: true environment: TZ: ${TZ} ORIGIN: ${RIVEN_ORIGIN} BACKEND_URL: "http://riven:3000" volumes: - riven_frontend_config:/riven/config depends_on: riven: condition: service_started networks: - riven_net - shared_net # ───────────────────────────────────────── # DMM — MySQL Database # ───────────────────────────────────────── dmm-db: image: mysql:8.0 container_name: dmm-db restart: unless-stopped environment: TZ: ${TZ} MYSQL_ROOT_PASSWORD: ${DMM_DB_ROOT_PASSWORD} MYSQL_DATABASE: dmm MYSQL_USER: dmm MYSQL_PASSWORD: ${DMM_DB_PASSWORD} volumes: - dmm_db_data:/var/lib/mysql healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${DMM_DB_ROOT_PASSWORD}"] interval: 10s timeout: 5s retries: 5 start_period: 30s networks: - dmm_net # ───────────────────────────────────────── # DMM — Redis # ───────────────────────────────────────── dmm-redis: image: redis:7-alpine container_name: dmm-redis restart: unless-stopped command: redis-server --appendonly yes --maxmemory 128mb --maxmemory-policy allkeys-lru environment: TZ: ${TZ} volumes: - dmm_redis_data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 5s retries: 5 start_period: 10s networks: - dmm_net # ───────────────────────────────────────── # DMM — Tor proxy # ───────────────────────────────────────── dmm-tor: image: debridmediamanager/tor container_name: dmm-tor restart: unless-stopped environment: TZ: ${TZ} networks: - dmm_net # ───────────────────────────────────────── # DMM — App (built from source) # ───────────────────────────────────────── dmm: build: context: ${DMM_BUILD_CONTEXT} # Era hardcoded /opt/tatsukai/plex/dmm image: dmm-prod:local container_name: dmm restart: unless-stopped environment: TZ: ${TZ} DATABASE_URL: ${DATABASE_URL} DMM_ORIGIN: ${DMM_URL} DMMCAST_SALT: ${DMM_SECRET} REDIS_URL: "redis://dmm-redis:6379" TMDB_KEY: ${TMDB_API_KEY} TRAKT_CLIENT_ID: ${TRAKT_CLIENT_ID} TRAKT_CLIENT_SECRET: ${TRAKT_CLIENT_SECRET} NEXT_PUBLIC_ANALYTICS_ENABLED: "false" MDBLIST_KEY: ${MDBLIST_KEY} TOR_PROXY: "socks5://dmm-tor:9050" ports: - "3000:3000" # Web UI → via Nginx Proxy Manager depends_on: dmm-db: condition: service_healthy dmm-redis: condition: service_healthy # Era service_started — ara espera healthcheck dmm-tor: condition: service_started networks: - dmm_net - shared_net # ───────────────────────────────────────── # XTEVE — Proxy M3U / Virtual HDHomeRun # ───────────────────────────────────────── xteve: image: alturismo/xteve:latest container_name: xteve restart: unless-stopped environment: TZ: ${TZ} XTEVE_TUNER: ${XTEVE_TUNER:-8} ports: - "34400:34400" # Web UI → via Nginx Proxy Manager volumes: - ${DATA_DIR}/xteve/config:/root/.xteve - ${DATA_DIR}/xteve/temp:/tmp/xteve - ${DATA_DIR}/epg/xmltv_master.xml:/root/xmltv.xml:ro - ${DATA_DIR}/epg/master.m3u:/root/playlist.m3u:ro networks: - shared_net volumes: riven_data: riven_postgres_data: riven_redis_data: riven_frontend_config: dmm_db_data: dmm_redis_data: networks: riven_net: driver: bridge dmm_net: driver: bridge shared_net: external: true name: shared_net