Files
curs-sobirania-digital/plex/docker-compose.yml
Guillem Hernandez Sola f1fe15d1b5 Tots els compose
2026-06-30 13:12:37 +02:00

431 lines
12 KiB
YAML

# /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