- docker-compose.infra.yml: core infrastructure (portainer, npm, homepage, wud, etc.) - docker-compose.media.yml: media stack (arrs, jellyfin, qbittorrent, scrobbling) - docker-compose.documents.yml: paperless-ngx, onlyoffice, stirling, open-webui - docker-compose.photo-roms.yml: immich, syncthing, retrom - docker-compose.utils.yml: gitea, tandoor, speedtest, linkwarden, rustdesk, etc. Each stack has its own project name (docker-infra, docker-media, etc.) to prevent orphan warnings. Networks defined in infra.yml, referenced as external by others. Original preserved as docker-compose.full.yaml.bak. Updated .gitignore, README, AGENTS.md, and RESTORE.md to reflect new structure.
276 lines
6.6 KiB
YAML
276 lines
6.6 KiB
YAML
# =============================================================================
|
|
# MEDIA STACK - Media management, downloading, and playback services
|
|
# =============================================================================
|
|
# DEPLOYMENT INSTRUCTIONS
|
|
# =============================================================================
|
|
# This is one of multiple compose files in the /docker/ directory.
|
|
#
|
|
# Deploy ALL stacks (from /docker/ directory):
|
|
# Get-ChildItem docker-compose.*.yml | ForEach-Object { docker compose -f $_ up -d }
|
|
#
|
|
# Deploy this stack only:
|
|
# docker compose -f docker-compose.media.yml up -d
|
|
#
|
|
# Stop this stack:
|
|
# docker compose -f docker-compose.media.yml down
|
|
#
|
|
# View logs for this stack:
|
|
# docker compose -f docker-compose.media.yml logs -f
|
|
#
|
|
# IMPORTANT: Requires infra stack to be deployed first (shared networks).
|
|
# =============================================================================
|
|
|
|
name: docker-media
|
|
|
|
# Common configurations for re-use
|
|
x-logging: &default-logging
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
|
|
x-security: &default-security
|
|
security_opt:
|
|
- no-new-privileges:true
|
|
|
|
services:
|
|
prowlarr:
|
|
image: lscr.io/linuxserver/prowlarr:latest
|
|
container_name: prowlarr
|
|
restart: unless-stopped
|
|
networks:
|
|
media_net:
|
|
ports:
|
|
- "9696:9696"
|
|
environment:
|
|
- PUID=${PUID}
|
|
- PGID=${PGID}
|
|
- TZ=${TZ}
|
|
volumes:
|
|
- /docker/Arrs/Prowlarr/config:/config
|
|
logging: *default-logging
|
|
|
|
flaresolverr:
|
|
image: ghcr.io/flaresolverr/flaresolverr:latest
|
|
container_name: flaresolverr
|
|
restart: unless-stopped
|
|
networks:
|
|
media_net:
|
|
ports:
|
|
- "127.0.0.1:8191:8191"
|
|
environment:
|
|
- TZ=${TZ}
|
|
logging: *default-logging
|
|
|
|
qbittorrent:
|
|
image: lscr.io/linuxserver/qbittorrent:latest
|
|
container_name: qbittorrent
|
|
restart: unless-stopped
|
|
networks:
|
|
media_net:
|
|
ports:
|
|
- "56881:6881"
|
|
- "56881:6881/udp"
|
|
- "7070:8080"
|
|
environment:
|
|
- TZ=${TZ}
|
|
- WEBUI_PORT=8080
|
|
- PUID=${PUID}
|
|
- PGID=${PGID}
|
|
volumes:
|
|
- /mnt/nas-storage/data:/data
|
|
- /docker/qBittorrent/config:/config
|
|
logging: *default-logging
|
|
|
|
radarr:
|
|
image: lscr.io/linuxserver/radarr:latest
|
|
container_name: radarr
|
|
restart: unless-stopped
|
|
networks:
|
|
media_net:
|
|
ports:
|
|
- "7878:7878"
|
|
environment:
|
|
- PUID=${PUID}
|
|
- PGID=${PGID}
|
|
- TZ=${TZ}
|
|
volumes:
|
|
- /mnt/nas-storage/data/:/data
|
|
- /docker/Arrs/Radarr/config:/config
|
|
logging: *default-logging
|
|
|
|
sonarr:
|
|
image: lscr.io/linuxserver/sonarr:latest
|
|
container_name: sonarr
|
|
restart: unless-stopped
|
|
networks:
|
|
media_net:
|
|
ports:
|
|
- "8989:8989"
|
|
environment:
|
|
- PUID=${PUID}
|
|
- PGID=${PGID}
|
|
- TZ=${TZ}
|
|
volumes:
|
|
- /mnt/nas-storage/data:/data
|
|
- /docker/Arrs/Sonarr/config:/config
|
|
logging: *default-logging
|
|
|
|
lidarr:
|
|
image: ghcr.io/hotio/lidarr:nightly
|
|
container_name: lidarr
|
|
restart: unless-stopped
|
|
networks:
|
|
media_net:
|
|
ports:
|
|
- "8686:8686"
|
|
environment:
|
|
- TZ=${TZ}
|
|
- PUID=${PUID}
|
|
- PGID=${PGID}
|
|
volumes:
|
|
- /mnt/nas-storage/data:/data
|
|
- /docker/Arrs/Lidarr/config:/config
|
|
logging: *default-logging
|
|
|
|
bazarr:
|
|
image: lscr.io/linuxserver/bazarr:latest
|
|
container_name: bazarr
|
|
restart: unless-stopped
|
|
networks:
|
|
media_net:
|
|
ports:
|
|
- "6767:6767"
|
|
environment:
|
|
- PUID=${PUID}
|
|
- PGID=${PGID}
|
|
- TZ=${TZ}
|
|
volumes:
|
|
- /mnt/nas-storage/data:/data
|
|
- /docker/Arrs/Bazarr/config:/config
|
|
logging: *default-logging
|
|
|
|
seerr:
|
|
image: ghcr.io/seerr-team/seerr:latest
|
|
init: true
|
|
container_name: seerr
|
|
environment:
|
|
- LOG_LEVEL=debug
|
|
- TZ=${TZ}
|
|
networks:
|
|
media_net:
|
|
ports:
|
|
- 5055:5055
|
|
volumes:
|
|
- /docker/Arrs/Seerr/config:/app/config
|
|
healthcheck:
|
|
test: wget --no-verbose --tries=1 --spider http://localhost:5055/api/v1/status || exit 1
|
|
start_period: 20s
|
|
timeout: 3s
|
|
interval: 15s
|
|
retries: 3
|
|
restart: unless-stopped
|
|
|
|
jellyfin:
|
|
image: jellyfin/jellyfin:latest
|
|
container_name: jellyfin
|
|
restart: unless-stopped
|
|
networks:
|
|
- media_net
|
|
- internal_net
|
|
ports:
|
|
- "8096:8096"
|
|
environment:
|
|
- JELLYFIN_PublishedServerUrl=${JELLYFIN_URL}
|
|
- TZ=${TZ}
|
|
- PUID=${PUID}
|
|
- PGID=${PGID}
|
|
group_add:
|
|
- "104"
|
|
devices:
|
|
- /dev/dri/renderD128:/dev/dri/renderD128
|
|
volumes:
|
|
- /mnt/nas-storage/data:/data
|
|
- /docker/Arrs/Jellyfin/cache:/cache
|
|
- /docker/Arrs/Jellyfin/config:/config
|
|
logging: *default-logging
|
|
|
|
slskd:
|
|
image: slskd/slskd:latest
|
|
container_name: slskd
|
|
restart: unless-stopped
|
|
networks:
|
|
media_net:
|
|
ports:
|
|
- "5030:5030"
|
|
- "50300:50300"
|
|
- "5031:5031"
|
|
hostname: slskd
|
|
environment:
|
|
- TZ=${TZ}
|
|
- SLSKD_REMOTE_CONFIGURATION=true
|
|
- SLSKD_USERNAME=${SLSKD_USERNAME}
|
|
- SLSKD_PASSWORD=${SLSKD_PASSWORD}
|
|
volumes:
|
|
- /mnt/nas-storage/data/torrents/soulsync/complete:/data/torrents/soulsync/complete
|
|
- /mnt/nas-storage/data/torrents/soulsync/incomplete:/data/torrents/soulsync/incomplete
|
|
- /docker/slskd:/app
|
|
logging: *default-logging
|
|
|
|
metube:
|
|
image: ghcr.io/alexta69/metube
|
|
container_name: metube
|
|
restart: unless-stopped
|
|
ports:
|
|
- "8081:8081"
|
|
volumes:
|
|
- /mnt/nas-storage/data/torrents/metube:/downloads
|
|
|
|
maloja:
|
|
image: krateng/maloja:latest
|
|
container_name: maloja
|
|
restart: unless-stopped
|
|
environment:
|
|
- MALOJA_FORCE_PASSWORD=${MALOJA_FORCE_PASSWORD}
|
|
networks:
|
|
- internal_net
|
|
- web_net
|
|
ports:
|
|
- "42010:42010"
|
|
volumes:
|
|
- /docker/maloja/config:/etc/maloja
|
|
- /docker/maloja/data:/var/lib/maloja
|
|
logging: *default-logging
|
|
|
|
multi-scrobbler:
|
|
image: foxxmd/multi-scrobbler:latest
|
|
container_name: multi-scrobbler
|
|
restart: unless-stopped
|
|
networks:
|
|
- internal_net
|
|
ports:
|
|
- "9078:9078"
|
|
environment:
|
|
- MALOJA_URL=${MALOJA_URL}
|
|
- MALOJA_API_KEY=${MALOJA_API_KEY}
|
|
- JELLYFIN_URL=${JELLYFIN_URL}
|
|
- JELLYFIN_APIKEY=${JELLYFIN_APIKEY_MS}
|
|
- JELLYFIN_USER=${JELLYFIN_USER}
|
|
- JELLYFIN_TRANSFORMS=musicbrainz
|
|
- MB_CONTACT=${MB_CONTACT}
|
|
- MB_PRESETS=default,sensible,native
|
|
volumes:
|
|
- /docker/scrobble/config:/config
|
|
logging: *default-logging
|
|
|
|
networks:
|
|
media_net:
|
|
name: media_net
|
|
external: true
|
|
internal_net:
|
|
name: internal_net
|
|
external: true
|
|
web_net:
|
|
name: web_net
|
|
external: true
|