Skip to content

Deploying the Media Automation Stack

This guide details how to deploy the ultimate bare-metal home media server using Kubernetes. It demonstrates advanced concepts like dual-storage paradigms, internal vs external DNS, and solving permission mismatches.

The "Arr" Stack Architecture

The stack consists of several interoperating services:

  1. Jellyfin: The media player (like Netflix). Streams your downloaded files to your TV.
  2. Jellyseerr: The request portal. A beautiful UI for non-technical users to request movies and shows.
  3. Radarr: The movie manager. It searches the internet for movies requested via Jellyseerr and sends them to the downloader.
  4. Sonarr: The TV show manager. Operates exactly like Radarr but for episodic content.
  5. Prowlarr: The indexer manager. It holds the configurations for all your torrent sites (e.g., YTS, EZTV) and dynamically injects them into Radarr and Sonarr.
  6. qBittorrent: The download client. It accepts .torrent files from Radarr/Sonarr, downloads them, and saves them to the shared network drive.

The Dual-Storage Paradigm

Because these applications manage massive multi-terabyte media files but also require blazing-fast database queries for their UIs, we use two entirely different Kubernetes storage provisioners simultaneously:

  1. Local-Path Provisioner (SSDs): Used for the /config directory of every pod. This ensures the SQLite databases for Radarr/Sonarr are written directly to the fast physical SSD on the node, preventing UI lag.
  2. NFS Provisioner (HDDs): Used for the /data/media directory. This is a massive, slow spinning disk exported via NFS. Radarr, Sonarr, qBittorrent, and Jellyfin all mount this exact same volume (using ReadWriteMany).

[!WARNING] The root_squash Permission Trap The NFS provisioner creates the media folder as root:root. The linuxserver.io Docker images run as user abc (UID 1000). This will cause a Permission Denied error when the containers try to write files. You must manually SSH into the NFS server and run sudo chown -R 1000:1000 /mnt/media to grant them access!

Deployment Workflow

1. Apply Kubernetes Manifests

Apply the manifests to the media namespace. Each application requires a Deployment, a PVC for config, a PVC for media (shared), a Service, and an Ingress.

kubectl apply -f k8s/apps/media/jellyfin/
kubectl apply -f k8s/apps/media/prowlarr/
kubectl apply -f k8s/apps/media/radarr/
kubectl apply -f k8s/apps/media/sonarr/
kubectl apply -f k8s/apps/media/jellyseerr/
kubectl apply -f k8s/apps/media/qbittorrent/

2. Configure the "Brain" (Prowlarr)

Prowlarr must be configured first, as it provides the search engines to the rest of the stack.

  1. Open http://prowlarr.homelab.local.
  2. Add your preferred Indexers (e.g., YTS for movies, EZTV for shows).
  3. Note: If an indexer fails with Connection Refused, your ISP is likely blocking the DNS. Try an alternate "Base URL" from the dropdown or change your router's DNS to 1.1.1.1.
  4. Go to Settings > Apps and add Radarr and Sonarr.
  5. Crucial Step: When defining the Radarr Server URL inside Prowlarr, you must use the internal Kubernetes DNS name (http://radarr:80), NOT the external Ingress URL.

3. Configure the Downloader (qBittorrent)

qBittorrent must save its files to the shared network drive, not its internal ephemeral container storage.

  1. Open http://qbittorrent.homelab.local.
  2. (Note: Check the pod logs for the temporary admin password if using v4.6.1+).
  3. Go to Settings > Downloads and change the Default Save Path from /downloads/ to /data/media/downloads/.
  1. Open Radarr and Sonarr.
  2. Go to Settings > Download Clients and add qBittorrent.
  3. Host: qbittorrent (Internal K8s DNS)
  4. Port: 80 (The K8s Service Port, which forwards to 8080)
  5. Go to Settings > Media Management, scroll down to Root Folders, and define the base paths:
  6. Radarr: /data/media/movies
  7. Sonarr: /data/media/tv

5. Final Result

When you request a movie in Jellyseerr: 1. Jellyseerr pings Radarr. 2. Radarr asks Prowlarr to search YTS. 3. Radarr finds the torrent and sends it to qbittorrent:80. 4. qBittorrent downloads it to /data/media/downloads/. 5. Radarr detects the finished download, moves it to /data/media/movies/, and renames it. 6. Jellyfin scans the folder and it appears on your TV!