326 lines
11 KiB
Markdown
326 lines
11 KiB
Markdown
# Media Server on Netcup RS 8000
|
|
|
|
A self-hosted media server stack with automated request management, running on Netcup RS 8000 with Jellyfin for streaming.
|
|
|
|
## Architecture
|
|
|
|
```
|
|
Users
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ Cloudflare Tunnel → Traefik │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
│
|
|
┌─────────────┼─────────────┐
|
|
▼ ▼ ▼
|
|
┌───────────┐ ┌───────────┐ ┌───────────┐
|
|
│ Jellyfin │ │Jellyseerr │ │ Navidrome │
|
|
│ (Stream) │ │(Requests) │ │ (Music) │
|
|
└─────┬─────┘ └─────┬─────┘ └───────────┘
|
|
│ │
|
|
│ ▼
|
|
│ ┌─────────────────────┐
|
|
│ │ Request Flow │
|
|
│ │ ┌───────────────┐ │
|
|
│ │ │ Sonarr │ │ ← TV Shows
|
|
│ │ │ Radarr │ │ ← Movies
|
|
│ │ │ Lidarr │ │ ← Music
|
|
│ │ └───────┬───────┘ │
|
|
│ │ │ │
|
|
│ │ ┌───────▼───────┐ │
|
|
│ │ │ Prowlarr │ │ ← Indexer Management
|
|
│ │ └───────┬───────┘ │
|
|
│ │ │ │
|
|
│ │ ┌───────▼───────┐ │
|
|
│ │ │ qBittorrent │ │ ← Downloads (optional VPN)
|
|
│ │ └───────┬───────┘ │
|
|
│ └──────────┼──────────┘
|
|
│ │
|
|
▼ ▼
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ Local NVMe Storage (3TB) │
|
|
│ /media/movies /media/shows /media/music │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
## How It Works
|
|
|
|
1. **Users request media** via Jellyseerr (`requests.jeffemmett.com`)
|
|
2. **Jellyseerr forwards** requests to Sonarr/Radarr/Lidarr
|
|
3. **Prowlarr searches** configured indexers for the content
|
|
4. **qBittorrent downloads** the files (optionally through VPN)
|
|
5. **\*arr apps organize** files into proper folders
|
|
6. **Jellyfin detects** new media and makes it available for streaming
|
|
|
|
## Server Specs
|
|
|
|
- **Netcup RS 8000 G12 Pro**: €45/month
|
|
- **20 CPU cores** for transcoding
|
|
- **64GB RAM** for caching
|
|
- **3TB NVMe storage** for media
|
|
- **1Gbps bandwidth** included
|
|
|
|
## Quick Start
|
|
|
|
### 1. Clone and Configure
|
|
|
|
```bash
|
|
git clone https://gitea.jeffemmett.com/jeffemmett/jellyfin-media.git
|
|
cd jellyfin-media
|
|
cp .env.example .env
|
|
```
|
|
|
|
### 2. Deploy to Netcup
|
|
|
|
```bash
|
|
./scripts/deploy-to-netcup.sh
|
|
```
|
|
|
|
### 3. Add Cloudflare Tunnel Hostnames
|
|
|
|
Add these hostnames to your Cloudflare tunnel config (`/root/cloudflared/config.yml`):
|
|
|
|
```yaml
|
|
# Media Request System
|
|
- hostname: requests.jeffemmett.com
|
|
service: http://localhost:80
|
|
- hostname: invite.jeffemmett.com
|
|
service: http://localhost:80
|
|
- hostname: sonarr.jeffemmett.com
|
|
service: http://localhost:80
|
|
- hostname: radarr.jeffemmett.com
|
|
service: http://localhost:80
|
|
- hostname: prowlarr.jeffemmett.com
|
|
service: http://localhost:80
|
|
- hostname: lidarr.jeffemmett.com
|
|
service: http://localhost:80
|
|
- hostname: downloads.jeffemmett.com
|
|
service: http://localhost:80
|
|
```
|
|
|
|
Then restart cloudflared: `docker restart cloudflared`
|
|
|
|
### 4. Configure Services (First Time Setup)
|
|
|
|
#### Step 1: Configure Prowlarr (Indexers)
|
|
1. Go to `https://prowlarr.jeffemmett.com`
|
|
2. Add indexers (torrent sites you have access to)
|
|
3. Go to Settings → Apps → Add Radarr, Sonarr, Lidarr
|
|
|
|
#### Step 2: Configure Download Client
|
|
1. Go to `https://downloads.jeffemmett.com`
|
|
2. Default login: `admin` / `adminadmin` (change immediately!)
|
|
3. Settings → Downloads → Default Save Path: `/downloads`
|
|
|
|
#### Step 3: Configure Radarr (Movies)
|
|
1. Go to `https://radarr.jeffemmett.com`
|
|
2. Settings → Media Management → Root Folder: `/movies`
|
|
3. Settings → Download Clients → Add qBittorrent:
|
|
- Host: `qbittorrent`
|
|
- Port: `8080`
|
|
|
|
#### Step 4: Configure Sonarr (TV Shows)
|
|
1. Go to `https://sonarr.jeffemmett.com`
|
|
2. Settings → Media Management → Root Folder: `/tv`
|
|
3. Settings → Download Clients → Add qBittorrent (same as above)
|
|
|
|
#### Step 5: Configure Lidarr (Music)
|
|
1. Go to `https://lidarr.jeffemmett.com`
|
|
2. Settings → Media Management → Root Folder: `/music`
|
|
3. Settings → Download Clients → Add qBittorrent (same as above)
|
|
|
|
#### Step 6: Configure Jellyseerr (Requests)
|
|
1. Go to `https://requests.jeffemmett.com`
|
|
2. Sign in with Jellyfin (use your Jellyfin server URL: `http://jellyfin:8096`)
|
|
3. Add Radarr/Sonarr servers:
|
|
- Hostname: `radarr` or `sonarr` (internal Docker hostname)
|
|
- Port: `7878` (Radarr) or `8989` (Sonarr)
|
|
- API Key: Get from Radarr/Sonarr Settings → General
|
|
|
|
#### Step 7: Configure Wizarr (User Invitations)
|
|
1. Go to `https://invite.jeffemmett.com`
|
|
2. Create your admin account on first visit
|
|
3. Connect to Jellyfin:
|
|
- Server URL: `http://jellyfin:8096`
|
|
- API Key: Get from Jellyfin → Dashboard → API Keys → Create
|
|
4. Create invite links:
|
|
- Set expiration (1 day, 1 week, never, etc.)
|
|
- Set usage limit (1 use, unlimited, etc.)
|
|
- Share the generated link with friends
|
|
5. When friends use the link, they'll be guided through:
|
|
- Creating their Jellyfin account
|
|
- Downloading mobile apps
|
|
- Connecting to your server
|
|
|
|
## Services
|
|
|
|
| Service | URL | Description |
|
|
|---------|-----|-------------|
|
|
| Jellyfin | https://movies.jeffemmett.com | Video streaming (movies & TV) |
|
|
| Navidrome | https://music.jeffemmett.com | Music streaming server |
|
|
| Jellyseerr | https://requests.jeffemmett.com | Media request interface |
|
|
| Wizarr | https://invite.jeffemmett.com | User invitation system |
|
|
| Sonarr | https://sonarr.jeffemmett.com | TV show management |
|
|
| Radarr | https://radarr.jeffemmett.com | Movie management |
|
|
| Lidarr | https://lidarr.jeffemmett.com | Music management |
|
|
| Prowlarr | https://prowlarr.jeffemmett.com | Indexer management |
|
|
| qBittorrent | https://downloads.jeffemmett.com | Download client |
|
|
|
|
## Security Recommendations
|
|
|
|
**Important:** The \*arr admin interfaces should be protected. Options:
|
|
|
|
1. **Cloudflare Access** (Recommended): Add authentication via Zero Trust dashboard
|
|
2. **SSH Tunnel**: Access admin UIs only via `ssh -L 8989:localhost:8989 netcup`
|
|
3. **Basic Auth**: Add Traefik middleware for HTTP basic auth
|
|
|
|
To add Cloudflare Access protection:
|
|
1. Go to Cloudflare Zero Trust → Access → Applications
|
|
2. Create application for each admin subdomain
|
|
3. Add authentication policy (email, one-time PIN, etc.)
|
|
|
|
## VPN Support
|
|
|
|
For download privacy, enable the VPN profile:
|
|
|
|
```bash
|
|
# Add to .env:
|
|
VPN_PROVIDER=mullvad
|
|
VPN_WIREGUARD_PRIVATE_KEY=your_private_key
|
|
VPN_WIREGUARD_ADDRESS=10.x.x.x/32
|
|
|
|
# Start with VPN:
|
|
docker compose --profile vpn up -d
|
|
```
|
|
|
|
Then modify qBittorrent to route through gluetun:
|
|
```yaml
|
|
# In docker-compose-server.yml, uncomment:
|
|
network_mode: "service:gluetun"
|
|
# And comment out the networks/labels sections
|
|
```
|
|
|
|
## Folder Structure
|
|
|
|
```
|
|
/opt/media-server/
|
|
├── media/
|
|
│ ├── movies/ # Movie files
|
|
│ ├── shows/ # TV show files
|
|
│ └── music/ # Music files
|
|
├── config/
|
|
│ ├── jellyfin/ # Jellyfin config
|
|
│ ├── jellyseerr/ # Jellyseerr config
|
|
│ ├── sonarr/ # Sonarr config
|
|
│ ├── radarr/ # Radarr config
|
|
│ ├── lidarr/ # Lidarr config
|
|
│ ├── prowlarr/ # Prowlarr config
|
|
│ └── qbittorrent/ # qBittorrent config
|
|
├── downloads/
|
|
│ └── complete/ # Completed downloads
|
|
└── cache/
|
|
└── jellyfin/ # Transcoding cache
|
|
```
|
|
|
|
## Upload Script Usage
|
|
|
|
```bash
|
|
# From local machine
|
|
./scripts/upload-to-netcup.sh <local-path> <media-type>
|
|
|
|
# Examples:
|
|
./scripts/upload-to-netcup.sh /home/jeffe/Shows shows
|
|
./scripts/upload-to-netcup.sh /home/jeffe/Movies movies
|
|
./scripts/upload-to-netcup.sh /home/jeffe/Music music
|
|
```
|
|
|
|
The script uses rsync for efficient incremental uploads.
|
|
|
|
## Mobile Apps
|
|
|
|
### Jellyfin (Video)
|
|
- **Android**: Jellyfin for Android
|
|
- **iOS**: Swiftfin, Jellyfin Mobile
|
|
|
|
### Navidrome (Music)
|
|
|
|
Navidrome is Subsonic-compatible and provides a Spotify-like self-hosted music experience.
|
|
|
|
#### Recommended: Symfonium (Android - ~$5)
|
|
|
|
The best mobile experience for Navidrome. Features:
|
|
- Spotify-like UI with gapless playback
|
|
- Offline downloads with smart caching
|
|
- Android Auto, Chromecast, Wear OS support
|
|
- Synced lyrics display
|
|
- Multiple server support
|
|
|
|
**Setup:**
|
|
1. Install Symfonium from Google Play (~$5 one-time)
|
|
2. Add Server → Subsonic/Navidrome
|
|
3. Server URL: `https://music.jeffemmett.com`
|
|
4. Enter your Navidrome username/password
|
|
|
|
#### Other Clients
|
|
|
|
| Platform | App | Cost | Notes |
|
|
|----------|-----|------|-------|
|
|
| Android | Symfonium | ~$5 | Best experience, recommended |
|
|
| Android | Ultrasonic | Free | Solid open-source alternative |
|
|
| iOS | Amperfy | Free | Clean UI, CarPlay support |
|
|
| iOS | play:Sub | ~$5 | Polished experience |
|
|
| Desktop | Sonixd | Free | Electron, cross-platform |
|
|
| Desktop | Sublime Music | Free | GTK-based, Linux-native |
|
|
| Web | Built-in | Free | `https://music.jeffemmett.com` |
|
|
|
|
## Music Features
|
|
|
|
### Sharing
|
|
Share tracks/albums with anyone (no account needed):
|
|
1. In Navidrome web UI, click any track/album
|
|
2. Click ⋮ menu → **Share**
|
|
3. Set expiration (or never)
|
|
4. Copy the public link
|
|
|
|
### Lyrics
|
|
Lyrics are automatically fetched from LRCLIB and displayed in Symfonium during playback.
|
|
|
|
### Spotify Playlist Import
|
|
Lidarr syncs with your Spotify playlists:
|
|
1. Go to `https://lidarr.jeffemmett.com`
|
|
2. Settings → Import Lists → Add → Spotify Playlists
|
|
3. Authenticate with Spotify
|
|
4. Select playlists to monitor
|
|
5. Lidarr downloads albums from artists in your playlists
|
|
|
|
### Scrobbling (Optional)
|
|
Track your listening history with Last.fm or ListenBrainz:
|
|
1. In Navidrome: Settings → Personal → Link account
|
|
2. All plays from web UI and Symfonium will scrobble
|
|
|
|
## Troubleshooting
|
|
|
|
### Downloads not starting
|
|
1. Check Prowlarr has working indexers
|
|
2. Verify qBittorrent is accessible: `docker logs qbittorrent`
|
|
3. Check Radarr/Sonarr logs for errors
|
|
|
|
### Media not appearing in Jellyfin
|
|
1. Verify files are in correct folder (`/media/movies`, `/media/shows`)
|
|
2. Trigger library scan in Jellyfin → Dashboard → Libraries
|
|
3. Check file permissions: should be owned by PUID:PGID (1000:1000)
|
|
|
|
### VPN connection issues
|
|
```bash
|
|
# Check gluetun logs
|
|
docker logs gluetun
|
|
|
|
# Verify VPN is working
|
|
docker exec gluetun curl ifconfig.me
|
|
```
|
|
|
|
## License
|
|
|
|
MIT
|