Building a VPN-Isolated Media Automation Stack on TrueNAS SCALE
Homelab case study · April 2026
Building a VPN-Isolated Media Automation Stack on TrueNAS SCALE
A containerized homelab design using Gluetun, qBittorrent, Sonarr, Radarr, Prowlarr, FlareSolverr, and Jellyfin to separate download traffic from the rest of the NAS and automate media-library workflows.
Separate network concerns instead of letting every container talk directly to the internet.
The objective of this homelab project was to create a clean media-automation stack on TrueNAS SCALE while keeping selected outbound traffic behind a dedicated VPN network layer. Rather than giving each service its own independent network path, the design uses Gluetun as the shared network namespace for the containers that need that path.
Sonarr and Radarr handle media-library automation, Prowlarr centralizes indexer configuration, qBittorrent performs downloads, and Jellyfin consumes the completed media files from persistent datasets. The focus of the design is service separation, predictable storage paths, and controlled network behavior.
Each service has a narrow role.
Provides the VPN client and network namespace used by selected containers.
Download client whose network traffic is routed through the Gluetun service.
TV-library automation and file organization.
Movie-library automation and file organization.
Centralized indexer configuration and synchronization with supported automation tools.
Consumes the organized media library from the TrueNAS datasets and serves it to approved clients.
Get storage, permissions, and remote access decisions right first.
Compose keeps the network dependency explicit.
The important Compose pattern is that selected containers use Gluetun's network namespace. This keeps the VPN routing decision centralized instead of duplicating VPN configuration across every application.
services:
gluetun:
image: qmcgaw/gluetun
cap_add:
- NET_ADMIN
environment:
- VPN_SERVICE_PROVIDER=<provider>
- VPN_TYPE=wireguard
- WIREGUARD_PRIVATE_KEY=<secret>
ports:
- "8081:8080" # qBittorrent
- "8989:8989" # Sonarr
- "7878:7878" # Radarr
- "9696:9696" # Prowlarr
qbittorrent:
image: lscr.io/linuxserver/qbittorrent:latest
network_mode: service:gluetun
volumes:
- /mnt/Pool/config/qbittorrent:/config
- /mnt/Pool/media:/downloads
sonarr:
image: lscr.io/linuxserver/sonarr:latest
network_mode: service:gluetun
radarr:
image: lscr.io/linuxserver/radarr:latest
network_mode: service:gluetun
prowlarr:
image: lscr.io/linuxserver/prowlarr:latest
network_mode: service:gluetun
Separate configuration, download, and media storage before launching the stack.
Confirm the VPN service can establish its tunnel before depending applications are started.
Use `network_mode: service:gluetun` only where that network path is actually required.
Expose the web interfaces through Gluetun's port mappings rather than duplicating mappings on each dependent service.
Confirm application reachability, DNS, storage access, and VPN routing before connecting the services together.
WireGuard keeps the network layer lightweight.
I used WireGuard for this build because it is efficient and well suited to a low-power homelab host. The exact VPN-provider variables depend on the provider and may change over time, so the current provider and Gluetun documentation should be treated as authoritative.
| Setting | Purpose |
|---|---|
| VPN service provider | Selects the provider-specific connection logic used by Gluetun. |
| VPN type | Chooses WireGuard or another supported protocol. |
| WireGuard private key | Authentication secret. Never publish it. |
| WireGuard address | Address assigned to the tunnel interface by the provider. |
| Outbound LAN subnet | Allows only the required local-network communication where the design needs it. |
Connect the services only after each one works independently.
Use each application's API key and the internal service address available within the shared network namespace.
Use sources you are legally permitted to access and that comply with the relevant service terms.
Point Sonarr and Radarr to the qBittorrent WebUI endpoint exposed through Gluetun.
Make sure the same physical dataset is mapped consistently across downloader, automation, and media-server containers.
Path consistency matters more than the application names.
The downloader, automation tools, and Jellyfin all need to agree on where completed media is stored. Inconsistent host/container path mappings are a common source of failed imports and duplicate copies.
| Purpose | Example host path | Example container path |
|---|---|---|
| Downloads | /mnt/Pool/media/downloads | /downloads |
| Movies | /mnt/Pool/media/Movies | /media/Movies |
| TV | /mnt/Pool/media/TV | /media/TV |
| Jellyfin library | /mnt/Pool/media | /media |
The stack is safer when secrets, routing, and exposure are explicit.
The architecture is easier to troubleshoot when every dependency is visible.
One VPN container is easier to reason about than independent VPN configuration in every application.
Most automation failures become easier to diagnose when every service sees the same underlying dataset in a predictable way.
Stop the VPN service, restart containers, break DNS intentionally in the lab, and verify that the resulting behavior matches your security expectations.
A good case study explains the architecture without exposing keys, internal credentials, or unnecessary administrative endpoints.
No comments:
Please Don't Spam Comment Box !!!!