A modular, Docker-based media center solution optimized for Single Board Computers like Raspberry Pi 5 (8GB+) and x86 SBCs.
- Native: Kodi (with Elementum), Samba.
- Minimal: Radarr, Sonarr, Transmission (+ Gluetun VPN).
- Extended: Minimal + Audiobookshelf, Lidarr, Prowlarr, FlareSolverr, Watchtower.
- Full: Extended + Home Assistant, Portainer, Jellyfin.
- Optimized Storage: Uses "Unified Root" architecture (
/data) to enable Hardlinks. Downloads are instantly imported to the library without taking up double space. - VPN Protected: All torrent traffic is routed through an encrypted VPN tunnel (Gluetun), keeping your activity private from your ISP. Built-in kill switch ensures torrents stop immediately if the VPN drops — no leaks, ever.
- Fully Configurable: All secrets, paths, ports, and API keys are read from a single
.envfile. Clone, configure, and go.
- A Debian-based Linux distribution (Ubuntu, Raspberry Pi OS, etc.).
sudoaccess.
git clone https://github.com/VenomekPL/MediaCenter.git
cd MediaCentercp .env.example .env
nano .envFill in at minimum:
- VPN credentials —
WIREGUARD_PRIVATE_KEY,WIREGUARD_ADDRESSES,WIREGUARD_PUBLIC_KEY,WIREGUARD_ENDPOINT_IP(see VPN Setup Guide) - Passwords —
TRANSMISSION_PASS,SAMBA_PASS - Network —
LOCAL_IP(your machine's LAN IP, e.g.192.168.1.100)
Optional but recommended:
API_KEY— Shared API key for all *arr apps. Default works out of the box; for production, generate one withopenssl rand -hex 16.TRAKT_USERNAME— Enables automatic watchlist sync in Radarr/Sonarr.JELLYFIN_DRM_DEVICE— Hardware acceleration device path (e.g./dev/dri/renderD128).
All available variables are documented in .env.example with comments.
Choose a profile: minimal, extended, or full.
./start.sh fullOn the first run, this will:
- Check VPN credentials (warns if missing, asks to confirm).
- Run
scripts/setup_configs.sh— creates config directories and pre-seeds all app configs from templates using your.envvalues. - Run
scripts/install_native.sh— installs Docker, Kodi, Samba, and dependencies (first run only, creates.native_installedmarker). - Start all Docker containers with the chosen profile.
- Run
scripts/link_services.sh— connects Transmission to all *arr apps, adds indexers to Prowlarr, configures quality limits, sets up Trakt watchlists.
After startup, check that all services are healthy:
docker compose ps| Service | URL | Profile |
|---|---|---|
| Transmission | http://<ip>:8020 |
minimal |
| Radarr (Movies) | http://<ip>:8021 |
minimal |
| Sonarr (TV) | http://<ip>:8022 |
minimal |
| Lidarr (Music) | http://<ip>:8023 |
extended |
| Prowlarr (Indexers) | http://<ip>:8024 |
extended |
| Audiobookshelf | http://<ip>:8025 |
extended |
| Jellyfin | http://<ip>:8026 |
full |
| Home Assistant | http://<ip>:8027 |
full |
| Portainer | https://<ip>:9443 |
full |
All ports are configurable via .env.
- Kodi: Open Kodi and install the Elementum plugin from
~/Downloads/repository.elementum.zip. - Samba: Shares for
Videos,Music,Books, andAudiobooksare configured automatically. Connect using your system username and theSAMBA_PASSfrom.env. - Trakt: If
TRAKT_USERNAMEis set in.env, watchlists are synced to Radarr/Sonarr automatically. Open Radarr/Sonarr → Settings → Import Lists → Trakt Watchlist and click "Authenticate with Trakt" to authorize.
For detailed configuration (quality profiles, Trakt integration, download logic), see the Configuration Guide.
Stop all services:
./stop.shUpdate containers:
./update.sh fullCleanup finished torrents & dangling downloads:
./scripts/cleanup.shLibrary audit (find duplicates, fix hardlinks, check Sonarr/Radarr tracking):
python3 scripts/library_audit.py --dry-run # preview changes
python3 scripts/library_audit.py # apply fixes + trigger rescansFind space wasters:
python3 scripts/find_space_wasters.py~/ ← DATA_ROOT_PATH (mounted as /data in containers)
├── Downloads/ ← Transmission downloads here
│ ├── radarr/ ← Movies (category set by Radarr)
│ │ └── Movie.Name.2024/
│ │ └── movie.mkv
│ ├── sonarr/ ← TV (category set by Sonarr)
│ └── lidarr/ ← Music (category set by Lidarr)
└── Videos/
├── Movies/ ← Radarr library (hardlinked from Downloads)
│ └── Movie Name (2024)/
│ └── Movie Name (2024).mkv ← Same inode as Downloads copy
└── TvSeries/ ← Sonarr library (hardlinked from Downloads)
└── Show Name/
└── Season 1/
└── Show Name - S01E01.mkv
Hardlinks mean the movie file in Videos/ and the one in Downloads/ are the same file on disk — zero extra space. When cleanup.sh removes finished torrents, the library copy remains.
VPN routing: Transmission runs inside Gluetun's network (network_mode: service:gluetun). All *arr apps connect to Transmission at gluetun:9091 (not transmission:9091). The kill switch blocks all traffic if the VPN tunnel drops.
Download categories: Each *arr app uses a dedicated Transmission category (radarr, sonarr, lidarr). This creates subdirectories under Downloads/ (e.g. Downloads/radarr/) so each app only sees its own downloads. Without categories, every app sees all Transmission torrents in its queue, causing phantom "stuck" items and cross-contamination. Categories are set automatically by link_services.sh.
├── .env.example ← Template — copy to .env and fill in
├── docker-compose.yml ← Includes all modules
├── start.sh / stop.sh / update.sh ← Lifecycle scripts
├── modules/ ← One compose.yaml per service
│ ├── gluetun/ ← VPN tunnel (WireGuard/OpenVPN)
│ ├── transmission/ ← Torrent client (routes through gluetun)
│ ├── radarr/ ← Movie management
│ ├── sonarr/ ← TV series management
│ ├── lidarr/ ← Music management
│ ├── prowlarr/ ← Indexer manager
│ ├── flaresolverr/ ← Cloudflare CAPTCHA solver
│ ├── jellyfin/ ← Media streaming server
│ ├── audiobookshelf/ ← Audiobook/podcast server
│ ├── home-assistant/ ← Home automation
│ ├── portainer/ ← Docker management UI
│ └── watchtower/ ← Auto-update containers
├── configs/ ← Template configs (pre-seeded on first run)
├── config/ ← Live container configs (gitignored)
├── scripts/ ← Helper scripts
│ ├── setup_configs.sh ← Pre-seeds configs from .env
│ ├── link_services.sh ← Auto-connects all services via API
│ ├── install_native.sh ← Installs Docker, Kodi, Samba
│ ├── cleanup.sh ← Removes finished torrents
│ ├── discover_hardware.sh ← Detects HW accel devices for .env
│ ├── library_audit.py ← Library health: dupes, orphans, tracking
│ ├── deduplicate.py ← Hardlink deduplication
│ └── find_space_wasters.py ← Space usage analysis
├── docs/ ← Guides and documentation
└── .github/skills/ ← AI agent skills for library cleanup
- Configuration Guide — Detailed setup and automation.
- VPN Setup Guide — VPN tunnel and kill switch.
- Copilot Context — Project rules and architectural decisions.
config/: (Created on run) Persistent configuration data for containers.