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>
255 lines
8.6 KiB
YAML
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
|