250 lines
6.5 KiB
Markdown
250 lines
6.5 KiB
Markdown
# 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
|
|
```
|