Files
portainer-core/stacks/media.yml
T
jpmschweitzerandClaude Opus 4.5 e8021307da feat(stack): create unified agents stack with Tatlock and Webber
Consolidate Tatlock API into new agents stack and add Webber LLM agent
orchestration service. Webber provides autonomous agent execution with
tool use, authenticating via Tatlock API.

Changes:
- Add stacks/agents.yml with Tatlock (port 8000) and Webber (port 8086)
- Remove stacks/tatlock.yml (merged into agents stack)
- Document Webber service in CONTAINERS.md (Redis DB 9)
- Add full Tatlock API documentation to CONTAINERS.md

Config updates (pre-existing):
- core-api: Enable OIDC, add host stats access, simplify model config
- gitea: Migrate from dedicated DB to postgres-shared
- media: Remove GPU reservation from Jellyfin

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 19:27:44 +01:00

255 lines
8.6 KiB
YAML

version: '3.8'
# Media Stack - Unified Media Management & Streaming
# Services: Jellyfin, Sonarr, Radarr, Prowlarr, SABnzbd
# Ports: 8096 (Jellyfin), 8989 (Sonarr), 7878 (Radarr), 9696 (Prowlarr), 8880 (SABnzbd)
# GPU: YES (Jellyfin only) - Requires NVIDIA Container Toolkit
# Storage: SSD (configs), HDD (media, downloads)
# Database: PostgreSQL (postgres-shared) for Sonarr, Radarr, Prowlarr
services:
# ============================================================
# JELLYFIN - Media Server with GPU Transcoding
# ============================================================
jellyfin:
image: jellyfin/jellyfin:latest
container_name: jellyfin
user: 1000:1000
restart: unless-stopped
ports:
- "8096:8096" # HTTP web interface
- "8920:8920" # HTTPS web interface
- "7359:7359/udp" # Auto-discovery
- "1900:1900/udp" # DLNA
volumes:
# Config and cache on SSD (performance-critical)
- /home/jpmschweitzer/docker-data/jellyfin/config:/config
- /home/jpmschweitzer/docker-data/jellyfin/cache:/cache
# Media files on HDD (read-only for safety)
- /mnt/media/jellyfin/movies:/media/movies:ro
- /mnt/media/jellyfin/series:/media/series:ro
environment:
- NVIDIA_VISIBLE_DEVICES=all
- NVIDIA_DRIVER_CAPABILITIES=all
- TZ=Europe/Amsterdam
healthcheck:
test: ["CMD-SHELL", "curl -fSs http://localhost:8096/health || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
networks:
- docker-dataplane
# ============================================================
# SONARR - TV Show Management & Automation
# ============================================================
sonarr:
image: linuxserver/sonarr:latest
container_name: sonarr
restart: unless-stopped
ports:
- "8989:8989"
volumes:
# Config on SSD
- /home/jpmschweitzer/docker-data/sonarr:/config
# Media and downloads on HDD
- /mnt/media/jellyfin/series:/tv
- /mnt/media/downloads:/downloads
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/Amsterdam
# PostgreSQL (postgres-shared)
- SONARR__POSTGRES__HOST=postgres-shared
- SONARR__POSTGRES__PORT=5432
- SONARR__POSTGRES__USER=media_user
- SONARR__POSTGRES__PASSWORD=${MEDIA_DB_PASSWORD}
- SONARR__POSTGRES__MAINDB=sonarr
healthcheck:
test: ["CMD-SHELL", "curl -fSs http://localhost:8989/ping || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
depends_on:
- sabnzbd
- prowlarr
networks:
- docker-dataplane
# ============================================================
# RADARR - Movie Management & Automation
# ============================================================
radarr:
image: linuxserver/radarr:latest
container_name: radarr
restart: unless-stopped
ports:
- "7878:7878"
volumes:
# Config on SSD
- /home/jpmschweitzer/docker-data/radarr:/config
# Media and downloads on HDD
- /mnt/media/jellyfin/movies:/movies
- /mnt/media/downloads:/downloads
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/Amsterdam
# PostgreSQL (postgres-shared)
- RADARR__POSTGRES__HOST=postgres-shared
- RADARR__POSTGRES__PORT=5432
- RADARR__POSTGRES__USER=media_user
- RADARR__POSTGRES__PASSWORD=${MEDIA_DB_PASSWORD}
- RADARR__POSTGRES__MAINDB=radarr
healthcheck:
test: ["CMD-SHELL", "curl -fSs http://localhost:7878/ping || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
depends_on:
- sabnzbd
- prowlarr
networks:
- docker-dataplane
# ============================================================
# PROWLARR - Indexer Management
# ============================================================
prowlarr:
image: linuxserver/prowlarr:latest
container_name: prowlarr
restart: unless-stopped
ports:
- "9696:9696"
volumes:
# Config on SSD
- /home/jpmschweitzer/docker-data/prowlarr:/config
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/Amsterdam
# PostgreSQL (postgres-shared)
- PROWLARR__POSTGRES__HOST=postgres-shared
- PROWLARR__POSTGRES__PORT=5432
- PROWLARR__POSTGRES__USER=media_user
- PROWLARR__POSTGRES__PASSWORD=${MEDIA_DB_PASSWORD}
- PROWLARR__POSTGRES__MAINDB=prowlarr
healthcheck:
test: ["CMD-SHELL", "curl -fSs http://localhost:9696/ping || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
networks:
- docker-dataplane
# ============================================================
# SABNZBD - Usenet Download Client
# ============================================================
sabnzbd:
image: linuxserver/sabnzbd:latest
container_name: sabnzbd
restart: unless-stopped
ports:
- "8880:8080" # Web UI (remapped to avoid Portainer conflict)
volumes:
# Config on SSD
- /home/jpmschweitzer/docker-data/sabnzbd:/config
# Downloads on HDD
- /mnt/media/downloads:/downloads
- /mnt/media/downloads/incomplete:/incomplete-downloads
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/Amsterdam
- HOST_WHITELIST=sabnzbd,localhost,192.168.86.149,tower-of-joy
healthcheck:
test: ["CMD-SHELL", "curl -fSs http://localhost:8080/api?mode=version || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
networks:
- docker-dataplane
networks:
docker-dataplane:
external: true
name: docker-dataplane
# ============================================================
# SETUP GUIDE
# ============================================================
#
# 0. Create PostgreSQL databases (run once):
# docker exec -it postgres-shared psql -U postgres -c "
# CREATE USER media_user WITH PASSWORD '<MEDIA_DB_PASSWORD>';
# CREATE DATABASE sonarr OWNER media_user;
# CREATE DATABASE radarr OWNER media_user;
# CREATE DATABASE prowlarr OWNER media_user;
# GRANT ALL PRIVILEGES ON DATABASE sonarr TO media_user;
# GRANT ALL PRIVILEGES ON DATABASE radarr TO media_user;
# GRANT ALL PRIVILEGES ON DATABASE prowlarr TO media_user;
# "
#
# 1. Create download directories:
# mkdir -p /mnt/media/downloads/complete /mnt/media/downloads/incomplete /mnt/media/downloads/usenet
# chown -R 1000:1000 /mnt/media/downloads
#
# 2. Create config directories:
# mkdir -p ~/docker-data/sonarr ~/docker-data/radarr ~/docker-data/prowlarr ~/docker-data/sabnzbd
# chown -R 1000:1000 ~/docker-data/sonarr ~/docker-data/radarr ~/docker-data/prowlarr ~/docker-data/sabnzbd
#
# 3. Set MEDIA_DB_PASSWORD environment variable in Portainer stack or export before deploy
#
# 4. Deploy the stack via Portainer or:
# docker stack deploy -c media.yml media
#
# 5. Configure services in order:
#
# a) SABnzbd (http://localhost:8880):
# - Complete setup wizard
# - Add Usenet server credentials
# - Configure download categories: tv, movies
# - Note the API key for Sonarr/Radarr
#
# b) Prowlarr (http://localhost:9696):
# - Add indexers (NZBgeek, DrunkenSlug, etc.)
# - Add Sonarr as application: http://sonarr:8989
# - Add Radarr as application: http://radarr:7878
# - Sync indexers to apps
#
# c) Sonarr (http://localhost:8989):
# - Settings → Media Management → Root Folder: /tv
# - Settings → Download Clients → Add SABnzbd:
# Host: sabnzbd, Port: 8080, API Key: <from SABnzbd>
# - Indexers will be synced from Prowlarr
#
# d) Radarr (http://localhost:7878):
# - Settings → Media Management → Root Folder: /movies
# - Settings → Download Clients → Add SABnzbd:
# Host: sabnzbd, Port: 8080, API Key: <from SABnzbd>
# - Indexers will be synced from Prowlarr
#
# e) Jellyfin (http://localhost:8096):
# - Already configured (migrated from previous stack)
# - Libraries should auto-detect new content
#
# 5. Inter-service communication (use container names):
# - SABnzbd from Sonarr/Radarr: http://sabnzbd:8080
# - Prowlarr from Sonarr: http://prowlarr:9696
# - All services on docker-dataplane network
#
# STORAGE LAYOUT:
# /mnt/media/
# ├── downloads/
# │ ├── complete/ # Completed downloads
# │ ├── incomplete/ # In-progress downloads
# │ └── usenet/ # Usenet-specific
# └── jellyfin/
# ├── movies/ # Radarr imports here
# └── series/ # Sonarr imports here