Files
Obsidian-Vault/Personal/Areas/Servers/TrueNAS/Integrating Servarr Stack with Traefik.md
2025-10-25 20:11:21 +02:00

8.8 KiB

Integrating Servarr Stack with Traefik

Your Current Setup

You have a Servarr media automation stack (servarr.yaml) with:

  • Gluetun - VPN container (ProtonVPN)
  • qBittorrent - Torrent client
  • Sonarr/Radarr/Lidarr - Media management
  • Prowlarr - Indexer manager
  • Bazarr - Subtitle downloader
  • Recyclarr - Configuration sync
  • Dozzle - Log viewer
  • Watchtower - Auto-updater

Special consideration: Most services use network_mode: service:gluetun, meaning they share gluetun's network namespace for VPN routing.


Challenge: VPN Network Mode

Services using network_mode: service:gluetun cannot directly connect to the traefik_proxy network. They're locked into gluetun's network namespace for VPN routing.

Options for External Access

Option 1: Don't Expose VPN Services Externally (Recommended)

  • Keep VPN-routed services local-only
  • Access via local network or Tailscale/Wireguard
  • Most secure approach
  • Expose only Dozzle (log viewer) via Traefik for monitoring

Option 2: Expose Gluetun to Traefik

  • Connect gluetun container to Traefik network
  • Route to services through gluetun's exposed ports
  • More complex configuration
  • Potential security considerations

Option 3: Split the Stack

  • Keep VPN services in current stack (local-only)
  • Move non-VPN services (Dozzle) to separate stack for Traefik access

Keep VPN Services Local, Expose Dozzle via Traefik

This gives you:

  • Secure VPN routing for download/automation apps (local access only)
  • External access to Dozzle for log monitoring
  • Simple configuration
  • No VPN security compromise

Implementation

Current Directory Structure

/mnt/tank/
├── configs/
│   ├── gluetun/
│   ├── qbittorrent/
│   ├── sonarr/
│   ├── radarr/
│   ├── lidarr/
│   ├── prowlarr/
│   ├── bazarr/
│   ├── recyclarr/
│   └── dozzle/
└── media/

Modified servarr.yaml

Keep the current file mostly as-is, but extract Dozzle to a separate stack:

Step 1: Deploy Traefik (if not done)

See: Traefik Multi-Stack Setup#Step 1

Step 2: Split Dozzle to Separate Stack

Remove Dozzle from servarr.yaml:

# Remove this section from servarr.yaml:
  dozzle:
    image: amir20/dozzle:latest
    container_name: dozzle
    ports:
      - 9999:8080
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    restart: unless-stopped

Create /mnt/tank/stacks/dozzle/docker-compose.yml:

version: '3.8'

networks:
  traefik_proxy:
    external: true

services:
  dozzle:
    image: amir20/dozzle:latest
    container_name: dozzle
    restart: unless-stopped
    networks:
      - traefik_proxy
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    environment:
      - TZ=Europe/Amsterdam
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=traefik_proxy"
      - "traefik.http.routers.dozzle.rule=Host(`logs.yourdomain.com`)"
      - "traefik.http.routers.dozzle.entrypoints=websecure"
      - "traefik.http.routers.dozzle.tls.certresolver=cloudflare"
      - "traefik.http.services.dozzle.loadbalancer.server.port=8080"
      # Optional: Add authentication
      - "traefik.http.routers.dozzle.middlewares=dozzle-auth"
      - "traefik.http.middlewares.dozzle-auth.basicauth.users=admin:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/"

Deploy Dozzle:

mkdir -p /mnt/tank/stacks/dozzle
cd /mnt/tank/stacks/dozzle
# Create docker-compose.yml with content above, then:
docker compose up -d

Now accessible at: https://logs.yourdomain.com

Step 3: Keep Servarr Stack As-Is

Your VPN-routed services remain accessible on local network:

  • qBittorrent: http://truenas-ip:8080
  • Sonarr: http://truenas-ip:8989
  • Radarr: http://truenas-ip:7878
  • Prowlarr: http://truenas-ip:9696
  • Lidarr: http://truenas-ip:8686
  • Bazarr: http://truenas-ip:6767

Access these via:

  • Local network (current method)
  • VPN (Tailscale/Wireguard) for remote access
  • SSH tunnel for secure remote access

Alternative: Expose Select Services via Traefik

If you want some *arr services accessible externally (e.g., Sonarr/Radarr for mobile apps):

Option: Duplicate Ports in Gluetun

Add gluetun to Traefik network and route through it:

Modified servarr.yaml:

services:
  gluetun:
    image: qmcgaw/gluetun:latest
    container_name: gluetun
    cap_add:
      - NET_ADMIN
    environment:
      - VPN_SERVICE_PROVIDER=protonvpn
      - VPN_TYPE=wireguard
      - WIREGUARD_PRIVATE_KEY=${WIREGUARD_PRIVATE_KEY}
      - SERVER_COUNTRIES=Netherlands
      - TZ=Europe/Amsterdam
    volumes:
      - /mnt/tank/configs/gluetun:/gluetun
      - /mnt/tank/configs/gluetun-tmp:/tmp/gluetun
    ports:
      - 8080:8080 # qBittorrent
      - 7878:7878 # Radarr
      - 8686:8686 # Lidarr
      - 8989:8989 # Sonarr
      - 9696:9696 # Prowlarr
      - 6767:6767 # Bazarr
    networks:
      - traefik_proxy  # Add this
    restart: unless-stopped
    labels:
      # Sonarr via Traefik
      - "traefik.enable=true"
      - "traefik.docker.network=traefik_proxy"
      - "traefik.http.routers.sonarr.rule=Host(`sonarr.yourdomain.com`)"
      - "traefik.http.routers.sonarr.entrypoints=websecure"
      - "traefik.http.routers.sonarr.tls.certresolver=cloudflare"
      - "traefik.http.routers.sonarr.service=sonarr"
      - "traefik.http.services.sonarr.loadbalancer.server.port=8989"
      # Radarr via Traefik
      - "traefik.http.routers.radarr.rule=Host(`radarr.yourdomain.com`)"
      - "traefik.http.routers.radarr.entrypoints=websecure"
      - "traefik.http.routers.radarr.tls.certresolver=cloudflare"
      - "traefik.http.routers.radarr.service=radarr"
      - "traefik.http.services.radarr.loadbalancer.server.port=7878"
      # Add more services as needed...

networks:
  traefik_proxy:
    external: true

  # ... rest of services remain the same

Security Note: This exposes your download apps to the internet. Consider:

  • Strong authentication in each app
  • Traefik basic auth middleware
  • Firewall rules limiting access to your IP
  • Or stick with VPN-only access

Internet (Port 80/443)
    ↓
Traefik
    ├── Gitea (https://git.yourdomain.com)
    ├── Dozzle (https://logs.yourdomain.com)
    └── [Future Services]

Local Network Only:
    ↓
Servarr Stack (VPN-routed)
    ├── Sonarr (http://truenas-ip:8989)
    ├── Radarr (http://truenas-ip:7878)
    ├── qBittorrent (http://truenas-ip:8080)
    └── [Other *arr apps]

Access Servarr remotely via:

  • Tailscale/Wireguard VPN
  • SSH tunnel: ssh -L 8989:localhost:8989 user@truenas-ip

Stack Management

Servarr Stack

# Start/stop Servarr stack
cd /mnt/tank/stacks/servarr
docker compose up -d
docker compose down

# Update containers (Watchtower handles this automatically)
docker compose pull
docker compose up -d

Dozzle (Traefik-routed)

cd /mnt/tank/stacks/dozzle
docker compose up -d
docker compose down

Gitea (Traefik-routed)

cd /mnt/tank/stacks/gitea
docker compose up -d
docker compose down

All stacks are independent!


DNS Records for Cloudflare

Add A records:

Name Target Proxy
git Your-Public-IP DNS only
logs Your-Public-IP DNS only
traefik Your-Public-IP DNS only

Environment Variables

Create .env file in servarr directory for sensitive data:

# /mnt/tank/stacks/servarr/.env
WIREGUARD_PRIVATE_KEY=your-wireguard-key

Reference in docker-compose:

environment:
  - WIREGUARD_PRIVATE_KEY=${WIREGUARD_PRIVATE_KEY}

Security Best Practices

  1. Don't expose VPN-routed services directly to internet

    • Use Tailscale/Wireguard for remote access
    • Or use SSH tunnels
  2. Enable authentication on all services

    • Each *arr app has built-in auth
    • Configure strong passwords
  3. Use Traefik middlewares for additional security

    • Basic auth
    • IP whitelisting
    • Rate limiting
  4. Keep Watchtower for auto-updates

    • Already configured in your stack
    • Keeps containers patched

Next Steps

  • Deploy Traefik (if not already done)
  • Move Dozzle to separate stack with Traefik labels
  • Deploy Dozzle with external access
  • Keep Servarr services local-only (current setup)
  • Set up Tailscale/Wireguard for secure remote access to Servarr
  • Add DNS records for exposed services
  • Test accessing Dozzle externally
  • Configure authentication for all services

Additional Notes

Your directory structure:

/mnt/tank/stacks/
├── traefik/
├── gitea/
├── servarr/  (your existing stack)
└── dozzle/   (optional split from servarr)