refactor: split 'compose.yml' into three distinct '.yml' files
This commit is contained in:
@@ -0,0 +1,517 @@
|
||||
# =============================================================================
|
||||
|
||||
# Torrent Stack (media) - VPN, *arr stack & media tooling
|
||||
#
|
||||
# Split from compose.yml on 2026-09-11 - verbatim service blocks.
|
||||
# Shared top-level networks:/volumes: are repeated in each subfile so it also
|
||||
# works standalone (docker compose -f media.yml up -d). Identical copies merge
|
||||
# cleanly under compose.yml's `include:` with no change to the live config.
|
||||
# Keep ./ paths, container names and /mnt data as-is.
|
||||
# =============================================================================
|
||||
|
||||
networks:
|
||||
#caddy_net:
|
||||
# external: true
|
||||
tdarr-net:
|
||||
driver: bridge
|
||||
default:
|
||||
name: portainer_network
|
||||
|
||||
volumes:
|
||||
#caddy_config:
|
||||
#caddy_data:
|
||||
# external: true
|
||||
#myspeed:
|
||||
# external: true
|
||||
portainer_data:
|
||||
name: portainer_data
|
||||
redis-data:
|
||||
driver: local
|
||||
|
||||
services:
|
||||
# ---------------------------------------------------------------------------
|
||||
# VPN & Download
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
gluetun:
|
||||
image: ${GLUETUN_IMAGE}
|
||||
container_name: gluetun
|
||||
env_file:
|
||||
- .env
|
||||
- ./env/.gluetun.env
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
ports:
|
||||
- 8877:8000/tcp
|
||||
- ${QBITTORRENT_PORT}:${QBITTORRENT_PORT}
|
||||
- ${PROWLARR_PORT}:${PROWLARR_PORT}
|
||||
- ${SONARR_PORT}:${SONARR_PORT}
|
||||
- ${RADARR_PORT}:${RADARR_PORT}
|
||||
- ${LIDARR_PORT}:${LIDARR_PORT}
|
||||
- ${BAZARR_PORT}:${BAZARR_PORT}
|
||||
volumes:
|
||||
- ./gluetun-data:/tmp/gluetun:rw
|
||||
#- /etc/localtime:/etc/localtime:ro
|
||||
#- /etc/timezone:/etc/timezone:ro
|
||||
environment:
|
||||
- VPN_SERVICE_PROVIDER=protonvpn
|
||||
- VPN_TYPE=wireguard
|
||||
- HTTP_CONTROL_SERVER=ON
|
||||
- WIREGUARD_MTU=1280
|
||||
- VPN_PORT_FORWARDING=on
|
||||
- VPN_PORT_FORWARDING_PROVIDER=protonvpn
|
||||
- SERVER_COUNTRIES=Netherlands
|
||||
- NETWORK_LOCAL_ADDRESSES=192.168.50.0/24,172.16.0.0/12
|
||||
- FIREWALL_OUTBOUND_SUBNETS=192.168.50.0/24
|
||||
- HEALTH_SERVER_ADDRESS=0.0.0.0:8877
|
||||
- HEALTH_TARGET_ADDRESSES=${EXTERNAL_IPV4}:${PLEX_PFWD_PORT}
|
||||
- TZ=${TIMEZONE}
|
||||
- DNS_UPSTREAM_RESOLVER_TYPE=doh
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD-SHELL",
|
||||
"wget -qO- '${WEB_PROTOCOL}://${EXTERNAL_IPV4}:${PLEX_PFWD_PORT}/identity' | grep -q 'MediaContainer' || exit 1",
|
||||
]
|
||||
interval: 1m30s
|
||||
timeout: 15s
|
||||
retries: 3
|
||||
start_period: 45s
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
mem_limit: 256m
|
||||
cpus: 1.0
|
||||
devices:
|
||||
- /dev/net/tun:/dev/net/tun
|
||||
restart: no
|
||||
|
||||
qbittorrent:
|
||||
image: ${QBITTORRENT_IMAGE}
|
||||
container_name: qbittorrent
|
||||
network_mode: "container:gluetun"
|
||||
depends_on:
|
||||
gluetun:
|
||||
condition: service_healthy
|
||||
volumes:
|
||||
- ./qbittorrent:/config
|
||||
- ${DISK1}:${DISK1}
|
||||
- ${DISK2}:${DISK2}
|
||||
- ./gluetun-data:/tmp/gluetun
|
||||
#- /etc/localtime:/etc/localtime:ro
|
||||
#- /etc/timezone:/etc/timezone:ro
|
||||
environment:
|
||||
- PUID=${HOST_PUID:-1000}
|
||||
- PGID=${HOST_PGID:-1000}
|
||||
- TZ=${TIMEZONE}
|
||||
- WEBUI_PORT=${QBITTORRENT_PORT}
|
||||
labels:
|
||||
- "autoheal=true"
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD-SHELL",
|
||||
"curl -sf '${WEB_PROTOCOL}://${EXTERNAL_IPV4}:${PLEX_PFWD_PORT}/identity' | grep -q 'MediaContainer' || exit 1",
|
||||
]
|
||||
interval: 1m
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
mem_limit: 512m
|
||||
cpus: 1.0
|
||||
restart: unless-stopped
|
||||
|
||||
port-updater:
|
||||
image: curlimages/curl:8.21.0
|
||||
container_name: port-updater
|
||||
network_mode: "container:gluetun"
|
||||
depends_on:
|
||||
gluetun:
|
||||
condition: service_healthy
|
||||
volumes:
|
||||
- ./gluetun-data:/tmp/gluetun:ro
|
||||
entrypoint: ["/bin/sh", "-c"]
|
||||
command:
|
||||
- |
|
||||
trap 'exit 0' SIGTERM;
|
||||
while true; do
|
||||
while [ ! -s /tmp/gluetun/forwarded_port ]; do
|
||||
echo "Waiting for Gluetun to provide a port..."
|
||||
sleep 5
|
||||
done
|
||||
|
||||
read -r PORT_VAL < /tmp/gluetun/forwarded_port;
|
||||
CLEAN_PORT=$$(echo "$$PORT_VAL" | tr -d '\r\n ');
|
||||
|
||||
if [ -n "$$CLEAN_PORT" ]; then
|
||||
echo "Updating qBit to port: $$CLEAN_PORT";
|
||||
sleep 10;
|
||||
curl -s -X POST -d "json={\"listen_port\":$$CLEAN_PORT}" http://localhost:${QBITTORRENT_PORT}/api/v2/app/setPreferences;
|
||||
sleep 3600 & wait $$!;
|
||||
else
|
||||
sleep 10
|
||||
fi
|
||||
done
|
||||
labels:
|
||||
- "autoheal=true"
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD-SHELL",
|
||||
"curl -sf '${WEB_PROTOCOL}://${EXTERNAL_IPV4}:${PLEX_PFWD_PORT}/identity' | grep -q 'MediaContainer' || exit 1",
|
||||
]
|
||||
interval: 1m
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
read_only: true
|
||||
tmpfs:
|
||||
- /tmp
|
||||
mem_limit: 64m
|
||||
cpus: 0.25
|
||||
restart: unless-stopped
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# *arr Stack
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
prowlarr:
|
||||
image: ${PROWLARR_IMAGE}
|
||||
container_name: prowlarr
|
||||
network_mode: "container:gluetun"
|
||||
depends_on:
|
||||
gluetun:
|
||||
condition: service_healthy
|
||||
volumes:
|
||||
- ./prowlarr:/config
|
||||
- ./notify.sh:/notify.sh:ro
|
||||
#- /etc/localtime:/etc/localtime:ro
|
||||
#- /etc/timezone:/etc/timezone:ro
|
||||
environment:
|
||||
- PUID=${HOST_PUID:-1000}
|
||||
- PGID=${HOST_PGID:-1000}
|
||||
- TZ=${TIMEZONE}
|
||||
labels:
|
||||
- "autoheal=true"
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD-SHELL",
|
||||
"curl -sf '${WEB_PROTOCOL}://${EXTERNAL_IPV4}:${PLEX_PFWD_PORT}/identity' | grep -q 'MediaContainer' || exit 1",
|
||||
]
|
||||
interval: 1m
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
mem_limit: 256m
|
||||
cpus: 1.0
|
||||
restart: unless-stopped
|
||||
|
||||
sonarr:
|
||||
image: ${SONARR_IMAGE}
|
||||
container_name: sonarr
|
||||
network_mode: "container:gluetun"
|
||||
depends_on:
|
||||
gluetun:
|
||||
condition: service_healthy
|
||||
volumes:
|
||||
- ./sonarr:/config
|
||||
- ${DISK1}:${DISK1}
|
||||
- ${DISK2}:${DISK2}
|
||||
#- /etc/localtime:/etc/localtime:ro
|
||||
#- /etc/timezone:/etc/timezone:ro
|
||||
environment:
|
||||
- PUID=${HOST_PUID:-1000}
|
||||
- PGID=${HOST_PGID:-1000}
|
||||
- TZ=${TIMEZONE}
|
||||
labels:
|
||||
- "autoheal=true"
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD-SHELL",
|
||||
"curl -sf '${WEB_PROTOCOL}://${EXTERNAL_IPV4}:${PLEX_PFWD_PORT}/identity' | grep -q 'MediaContainer' || exit 1",
|
||||
]
|
||||
interval: 1m
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 60s
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
mem_limit: 256m
|
||||
cpus: 1.0
|
||||
restart: unless-stopped
|
||||
|
||||
radarr:
|
||||
image: ${RADARR_IMAGE}
|
||||
container_name: radarr
|
||||
network_mode: "container:gluetun"
|
||||
depends_on:
|
||||
gluetun:
|
||||
condition: service_healthy
|
||||
volumes:
|
||||
- ./radarr:/config
|
||||
- ${DISK1}:${DISK1}
|
||||
- ${DISK2}:${DISK2}
|
||||
#- /etc/localtime:/etc/localtime:ro
|
||||
#- /etc/timezone:/etc/timezone:ro
|
||||
environment:
|
||||
- PUID=${HOST_PUID:-1000}
|
||||
- PGID=${HOST_PGID:-1000}
|
||||
- TZ=${TIMEZONE}
|
||||
labels:
|
||||
- "autoheal=true"
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD-SHELL",
|
||||
"curl -sf '${WEB_PROTOCOL}://${EXTERNAL_IPV4}:${PLEX_PFWD_PORT}/identity' | grep -q 'MediaContainer' || exit 1",
|
||||
]
|
||||
interval: 1m
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
mem_limit: 256m
|
||||
cpus: 1.0
|
||||
restart: unless-stopped
|
||||
|
||||
lidarr:
|
||||
image: ${LIDARR_IMAGE}
|
||||
container_name: lidarr
|
||||
network_mode: "container:gluetun"
|
||||
depends_on:
|
||||
gluetun:
|
||||
condition: service_healthy
|
||||
volumes:
|
||||
- ./lidarr:/music
|
||||
- ./lidarr:/config
|
||||
- ${DISK1}:${DISK1}
|
||||
- ${DISK2}:${DISK2}
|
||||
#- /etc/localtime:/etc/localtime:ro
|
||||
#- /etc/timezone:/etc/timezone:ro
|
||||
environment:
|
||||
- PUID=${HOST_PUID:-1000}
|
||||
- PGID=${HOST_PGID:-1000}
|
||||
- TZ=${TIMEZONE}
|
||||
labels:
|
||||
- "autoheal=true"
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD-SHELL",
|
||||
"curl -sf '${WEB_PROTOCOL}://${EXTERNAL_IPV4}:${PLEX_PFWD_PORT}/identity' | grep -q 'MediaContainer' || exit 1",
|
||||
]
|
||||
interval: 1m
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
mem_limit: 256m
|
||||
cpus: 1.0
|
||||
restart: unless-stopped
|
||||
|
||||
bazarr:
|
||||
image: ${BAZARR_IMAGE}
|
||||
container_name: bazarr
|
||||
network_mode: "container:gluetun"
|
||||
depends_on:
|
||||
gluetun:
|
||||
condition: service_healthy
|
||||
volumes:
|
||||
- ./bazarr:/config
|
||||
- ${DISK1}:${DISK1}
|
||||
- ${DISK2}:${DISK2}
|
||||
#- /etc/localtime:/etc/localtime:ro
|
||||
#- /etc/timezone:/etc/timezone:ro
|
||||
environment:
|
||||
- PUID=${HOST_PUID:-1000}
|
||||
- PGID=${HOST_PGID:-1000}
|
||||
- TZ=${TIMEZONE}
|
||||
labels:
|
||||
- "autoheal=true"
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD-SHELL",
|
||||
"curl -sf '${WEB_PROTOCOL}://${EXTERNAL_IPV4}:${PLEX_PFWD_PORT}/identity' | grep -q 'MediaContainer' || exit 1",
|
||||
]
|
||||
interval: 1m
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
mem_limit: 256m
|
||||
cpus: 1.0
|
||||
restart: unless-stopped
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Media
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
tautulli:
|
||||
image: ${TAUTULLI_IMAGE}
|
||||
container_name: tautulli
|
||||
#networks:
|
||||
# - caddy_net
|
||||
ports:
|
||||
- ${TAUTULLI_PORT}:${TAUTULLI_PORT}
|
||||
volumes:
|
||||
- ./tautulli:/config
|
||||
#- /etc/localtime:/etc/localtime:ro
|
||||
#- /etc/timezone:/etc/timezone:ro
|
||||
environment:
|
||||
- PUID=${HOST_PUID:-1000}
|
||||
- PGID=${HOST_PGID:-1000}
|
||||
- TZ=${TIMEZONE}
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
mem_limit: 256m
|
||||
cpus: 1.0
|
||||
restart: unless-stopped
|
||||
|
||||
tdarr:
|
||||
image: ${TDARR_IMAGE}
|
||||
container_name: tdarr
|
||||
networks:
|
||||
- tdarr-net
|
||||
ports:
|
||||
- ${TDARR_PORT}:${TDARR_PORT}
|
||||
- ${TDARR_NODE_PORT}:${TDARR_NODE_PORT}
|
||||
volumes:
|
||||
- ./tdarr/server:/app/server
|
||||
- ./tdarr/configs:/app/configs
|
||||
- ./tdarr/temp:/temp
|
||||
- ${DISK1}:${DISK1}
|
||||
- ${DISK2}:${DISK2}
|
||||
#- /etc/localtime:/etc/localtime:ro
|
||||
#- /etc/timezone:/etc/timezone:ro
|
||||
environment:
|
||||
- TZ=${TIMEZONE}
|
||||
- PUID=${HOST_PUID:-1000}
|
||||
- PGID=${HOST_PGID:-1000}
|
||||
- UMASK_SET=002
|
||||
- serverIP=0.0.0.0
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
mem_limit: 512m
|
||||
cpus: 2.0
|
||||
restart: unless-stopped
|
||||
|
||||
tdarr-node:
|
||||
image: ${TDARR_NODE_IMAGE}
|
||||
container_name: tdarr-node
|
||||
networks:
|
||||
- tdarr-net
|
||||
volumes:
|
||||
- ./tdarr/configs:/app/configs
|
||||
- ./tdarr/logs:/app/logs
|
||||
- ./tdarr/temp:/temp
|
||||
- ${DISK1}:${DISK1}
|
||||
- ${DISK2}:${DISK2}
|
||||
#- /etc/localtime:/etc/localtime:ro
|
||||
#- /etc/timezone:/etc/timezone:ro
|
||||
environment:
|
||||
- TZ=${TIMEZONE}
|
||||
- PUID=${HOST_PUID:-1000}
|
||||
- PGID=${HOST_PGID:-1000}
|
||||
- nodeID=${TDARR_NODE_ID}
|
||||
- nodeIP=0.0.0.0
|
||||
- serverIP=tdarr
|
||||
- serverPort=${TDARR_NODE_PORT}
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
mem_limit: 4g
|
||||
cpus: 4.0
|
||||
devices:
|
||||
- /dev/dri:/dev/dri
|
||||
restart: unless-stopped
|
||||
|
||||
seerr:
|
||||
image: ${SEERR_IMAGE}
|
||||
container_name: seerr
|
||||
# networks:
|
||||
# - caddy_net
|
||||
ports:
|
||||
- ${SEERR_PORT}:${SEERR_PORT}
|
||||
volumes:
|
||||
- ./seerr:/app/config
|
||||
#- /etc/localtime:/etc/localtime:ro
|
||||
#- /etc/timezone:/etc/timezone:ro
|
||||
environment:
|
||||
- LOG_LEVEL=info
|
||||
- TZ=${TIMEZONE}
|
||||
- PUID=${HOST_PUID:-1000}
|
||||
- PGID=${HOST_PGID:-1000}
|
||||
labels:
|
||||
- "autoheal=true"
|
||||
init: true
|
||||
working_dir: "/app"
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD-SHELL",
|
||||
"wget -qO- '${WEB_PROTOCOL}://${EXTERNAL_IPV4}:${PLEX_PFWD_PORT}/identity' | grep -q 'MediaContainer' || exit 1",
|
||||
]
|
||||
interval: 1m
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 60s
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
mem_limit: 256m
|
||||
cpus: 1.0
|
||||
restart: unless-stopped
|
||||
|
||||
spotizerr:
|
||||
image: spotizerrphoenix/spotizerr
|
||||
user: "1000:1000" # Spotizerr user:group ids
|
||||
volumes:
|
||||
# Ensure these directories and the .cache file exist and are writable by the container user
|
||||
- ./spotizerr:/app/data # data directory, contains config, creds, watch, history
|
||||
- ${DISK1}/media/Music/spotizerr:/app/downloads # downloads directory, contains downloaded files
|
||||
- ./spotizerr/logs:/app/logs # logs directory, contains logs
|
||||
- ./spotizerr/.cache:/app/.cache # cache file
|
||||
ports:
|
||||
# Port to expose the app on
|
||||
- 7171:7171
|
||||
container_name: spotizerr
|
||||
restart: unless-stopped
|
||||
env_file:
|
||||
# Ensure you have a .env file in the root of the project, with the correct values
|
||||
- ./.env
|
||||
depends_on:
|
||||
- redis
|
||||
|
||||
redis:
|
||||
image: redis:alpine
|
||||
container_name: spotizerr-redis
|
||||
restart: unless-stopped
|
||||
env_file:
|
||||
- .env
|
||||
volumes:
|
||||
- redis-data:/data
|
||||
command: sh -c 'redis-server --requirepass "$REDIS_PASSWORD" --appendonly yes'
|
||||
|
||||
# Anubis anti-bot proxy for Seerr (uncomment to enable):
|
||||
#seerr-anubis:
|
||||
# image: ghcr.io/techarohq/anubis:latest
|
||||
# container_name: seerr-anubis
|
||||
# networks:
|
||||
# - caddy_net
|
||||
# environment:
|
||||
# - BIND=:55055
|
||||
# - TARGET=http://seerr:${SEERR_PORT}
|
||||
# security_opt:
|
||||
# - no-new-privileges:true
|
||||
# mem_limit: 128m
|
||||
# cpus: 0.5
|
||||
# restart: unless-stopped
|
||||
Reference in New Issue
Block a user