add the media stack

This commit is contained in:
tsvetkov
2026-02-27 00:55:03 +00:00
commit 179dca7339
18 changed files with 1689 additions and 0 deletions

249
README.md Normal file
View File

@@ -0,0 +1,249 @@
# Media Stack Kubernetes Deployment
A complete self-hosted media solution deployed on Kubernetes.
## Stack Components
| Component | Purpose | Port | Image |
|-----------|---------|------|-------|
| **Jellyfin** | Media server + Live TV frontend | 8096 | jellyfin/jellyfin:10.11.5 |
| **Sonarr** | TV show management | 8989 | lscr.io/linuxserver/sonarr:latest |
| **Radarr** | Movie management | 7878 | lscr.io/linuxserver/radarr:latest |
| **Lidarr** | Music management | 8686 | lscr.io/linuxserver/lidarr:latest |
| **Prowlarr** | Indexer management | 9696 | lscr.io/linuxserver/prowlarr:latest |
| **qBittorrent** | Download client | 8080 | lscr.io/linuxserver/qbittorrent:latest |
| **Dispatcharr** | IPTV/M3U proxy for live TV | 9191 | ghcr.io/dispatcharr/dispatcharr:latest |
## Network Configuration
- Network: `10.0.0.0/24`
- K8s Control Plane: `10.0.0.69` (k8scontrol)
- K8s Workers: `10.0.0.70-73` (k8sworker1-3)
- NFS Server: `10.0.0.230`
- Kubernetes Version: 1.35
## NFS Share Structure
Your NFS server (10.0.0.230) should have these directories:
```
/srv/nfs/media/
├── config/
│ ├── jellyfin/
│ ├── sonarr/
│ ├── radarr/
│ ├── lidarr/
│ ├── prowlarr/
│ ├── qbittorrent/
│ └── dispatcharr/
├── downloads/
│ ├── complete/
│ └── incomplete/
├── media/
│ ├── movies/
│ ├── tv/
│ └── music/
└── transcode/
```
## Pre-requisites
### 1. Configure NFS Server (10.0.0.230)
```bash
# On NFS server
sudo mkdir -p /srv/nfs/media/{config/{jellyfin,sonarr,radarr,lidarr,prowlarr,qbittorrent,dispatcharr},downloads/{complete,incomplete},media/{movies,tv,music},transcode}
# Set permissions (adjust UID/GID as needed - 1000:1000 is common)
sudo chown -R 1000:1000 /srv/nfs/media
# Add to /etc/exports
echo "/srv/nfs/media 10.0.0.0/24(rw,sync,no_subtree_check,no_root_squash)" | sudo tee -a /etc/exports
# Apply exports
sudo exportfs -ra
```
### 2. Install NFS Client on K8s Nodes
```bash
# On each worker node (k8sworker1-3)
sudo apt-get update && sudo apt-get install -y nfs-common
```
### 3. Verify NFS Connectivity
```bash
# From any worker node
showmount -e 10.0.0.230
```
## Deployment
### Manual Deployment (in order)
**Without VPN:**
```bash
# Create namespace
kubectl apply -f base/namespace.yaml
# Create storage
kubectl apply -f base/nfs-storage.yaml
# Create config
kubectl apply -f base/configmap.yaml
# Create PVCs
kubectl apply -f base/pvcs.yaml
# Deploy applications
kubectl apply -f base/jellyfin.yaml
kubectl apply -f base/sonarr.yaml
kubectl apply -f base/radarr.yaml
kubectl apply -f base/lidarr.yaml
kubectl apply -f base/prowlarr.yaml
kubectl apply -f base/qbittorrent.yaml
kubectl apply -f base/dispatcharr.yaml
```
**With VPN (after configuring VPN credentials in `base/vpn/mullvad-secret.yaml`):**
Download a .conf file from your Mullvad account and update the private key and wireguard address in `base/vpn/mullvad-secret.yaml`)
```bash
# Create namespace
kubectl apply -f base/namespace.yaml
# Create storage
kubectl apply -f base/nfs-storage.yaml
# Create config
kubectl apply -f base/configmap.yaml
# Create VPN-specific resources
kubectl apply -f base/vpn/gluetun-config.yaml
kubectl apply -f base/vpn/qbittorrent-init-configmap.yaml
kubectl apply -f base/vpn/mullvad-secret.yaml
# Create PVCs
kubectl apply -f base/pvcs.yaml
# Deploy non-VPN applications
kubectl apply -f base/jellyfin.yaml
kubectl apply -f base/sonarr.yaml
kubectl apply -f base/radarr.yaml
kubectl apply -f base/lidarr.yaml
# Deploy VPN-enabled applications
kubectl apply -f base/vpn/prowlarr-vpn.yaml
kubectl apply -f base/vpn/qbittorrent-vpn.yaml
kubectl apply -f base/vpn/dispatcharr-vpn.yaml
```
### Automated deployment
A [deploy.sh](link) script can be used as such:
**Without VPN:**
```bash
./deploy.sh
```
**With VPN (recommended for qBittorrent, Prowlarr, Dispatcharr):**
```bash
./deploy.sh --vpn
```
Optionally to change the VPN location amend `SERVER_CITIES` in the `base/vpn/gluetun-config.yaml` file.
To enable port forwarding:
1. Go to your mullvad.net account and navigate to `account/ports`
2. Add a port for your wireguard key
3. Amend the `FIREWALL_VPN_INPUT_PORTS` value to your port in the `base/vpn/gluetun-config.yaml` file
4. Configure qBittorrent to point to your client
## Accessing Services
After deployment, services are available via NodePort:
| Service | URL |
|---------|-----|
| Jellyfin | http://10.0.0.70:30096 |
| Sonarr | http://10.0.0.70:30989 |
| Radarr | http://10.0.0.70:30878 |
| Lidarr | http://10.0.0.70:30686 |
| Prowlarr | http://10.0.0.70:30696 |
| qBittorrent | http://10.0.0.70:30080 |
| Dispatcharr | http://10.0.0.70:30191 |
*Replace 10.0.0.70 with any worker node IP*
## Post-Deployment Configuration
### 1. qBittorrent
- Check container logs for temporary password: `kubectl logs -n media deployment/qbittorrent`
- Login and change password immediately
- Set download paths to `/downloads/complete` and `/downloads/incomplete`
### 2. Prowlarr
- Add your indexers
- Connect to Sonarr, Radarr, and Lidarr via Settings → Apps
- Use internal service names: `http://sonarr:8989`, `http://radarr:7878`, `http://lidarr:8686`
### 3. Sonarr/Radarr/Lidarr
- Add qBittorrent as download client: `http://qbittorrent:8080`
- Set media library paths: `/media/tv`, `/media/movies`, `/media/music`
- Configure quality profiles and root folders
### 4. Jellyfin
- Run initial setup wizard
- Add media libraries pointing to `/media/movies`, `/media/tv`, `/media/music`
- For Live TV: Settings → Live TV → Add Tuner Device → HDHomeRun
- Use Dispatcharr's HDHomeRun URL: `http://dispatcharr:9191`
### 5. Dispatcharr
- Add your M3U playlist sources
- Configure EPG sources
- Enable channels you want to watch
## Useful Commands
```bash
# Restart a deployment
kubectl rollout restart deployment/jellyfin -n media
# Scale down all (for maintenance)
kubectl scale deployment --all -n media --replicas=0
# Scale back up
kubectl scale deployment --all -n media --replicas=1
```
## Troubleshooting
### Permission Denied Errors
- Ensure PUID/PGID in configmap matches NFS share ownership
- Check that `no_root_squash` is set in NFS exports
## Upgrading
To upgrade images:
```bash
# Update a single deployment
kubectl set image deployment/jellyfin -n media jellyfin=jellyfin/jellyfin:NEW_VERSION
# Or edit the YAML and reapply
kubectl apply -f base/jellyfin.yaml
```
## Cleanup
```bash
# Delete everything
kubectl delete namespace media
# This will remove all deployments, services, and PVCs
# PVs and NFS data will remain
```