A self-hosted stack for media management and streaming, with AI-powered movie and show recommendations. Includes Sonarr, Radarr, qBitTorrent, Prowlarr, Jellyfin, Seerr, Recommendarr, and VPN support.
1,249
171 commits
updated Oct 10, 2026
A self-hosted media ecosystem that combines media management, streaming, AI-powered recommendations, and VPN.
This stack includes:
⚠️ Jellyfin v12 Upgrade Notice: This stack now ships Jellyfin 12.1. Upgrading from
10.11.xis a major upgrade that cannot be rolled back without a full restore.Before upgrading:
- Take a full backup of your Jellyfin data and config directories. The release includes database changes that prevent rolling back without a full restore.
- Remove third-party plugins first. Plugins built for 10.11 will not load on 12.x and must be updated by their authors before being re-added.
After upgrading:
- A full library scan is required.
See the Jellyfin 12.0 release notes for full details.
There are three ways to deploy this stack:
NOTE: If you are installing this stack without a VPN, you must use the
no-vpnprofile.
This requirement prevents accidental or unintentional deployment of media-stack without VPN.Running the
docker composecommand without a profile will not deploy anything.Check the installation steps below.
Before deploying the stack, you must first create a Docker network:
docker network create --subnet 172.20.0.0/16 mynetwork
# Update the CIDR range based on your available IP range
When VPN is enabled, qBittorrent and Prowlarr will run behind the VPN for added privacy.
By default, NordVPN is used in docker-compose.yml, but you can switch to:
All providers use the OpenVPN protocol.
➡️ Full list of supported VPN providers: VPN Providers
Refer to your VPN provider's documentation to generate an OpenVPN username and password.
For setup instructions, check:
➡️ Gluetun VPN Setup Guide
docker-compose.ymlBy default, VPN is disabled in docker-compose.yml. To enable it, simply comment/uncomment the required lines in the file.
The docker-compose.yml file includes clear instructions in the comments to guide you through the process.
Once updated, follow the steps below to deploy the stack with VPN.
VPN_SERVICE_PROVIDER=nordvpn OPENVPN_USER=openvpn-username OPENVPN_PASSWORD=openvpn-password SERVER_COUNTRIES=Switzerland RADARR_STATIC_CONTAINER_IP=radarr-container-static-ip SONARR_STATIC_CONTAINER_IP=sonarr-container-static-ip docker compose --profile vpn up -d
# OPTIONAL: Use Nginx as a reverse proxy
# docker compose -f docker-compose-nginx.yml up -d
A static container IP address is needed when Prowlarr is behind a VPN.
Since Prowlarr can only communicate with Radarr and Sonarr using their container IP addresses,
these must be manually assigned to avoid connection issues when containers restart.
Use the following environment variables to set static IPs:
RADARR_STATIC_CONTAINER_IPSONARR_STATIC_CONTAINER_IP🚨 Warning: Deploying without a VPN is highly discouraged as it may expose your IP address when torrenting media.
To proceed without VPN, run the following command:
docker compose --profile no-vpn up -d
# OPTIONAL: Use Nginx as a reverse proxy
# docker compose -f docker-compose-nginx.yml up -d
Recommendarr is a web application that uses AI to generate personalized TV show and movie recommendations based on your:
Run the following command based on your setup:
COMPOSE_PROFILES=vpn,recommendarr docker compose up -d # With VPN
# COMPOSE_PROFILES=no-vpn,recommendarr docker compose up -d # Without VPN
admin. Temporary password can be collected from container log docker logs qbittorrentdocker exec -it qbittorrent bash # Get inside qBittorrent container
# Above command will get you inside qBittorrent interactive terminal, Run below command in qbt terminal
mkdir /downloads/movies /downloads/tvshows
chown 1000:1000 /downloads/movies /downloads/tvshows
vpn in Host field.Sonarr can also be configured in similar way.
Add a movie (After Prowlarr is configured)
Note: If VPN is enabled, then Prowlarr will not be able to reach radarr and sonarr with localhost or container service name. In that case use static IP for sonarr and radarr in radarr/sonarr server field (for e.g. http://172.19.0.5:8989). Prowlar will also be not reachable with its container/service name. Use http://vpn:9696 instead in prowlar server field.
Recommendarr is an AI based movies/tvshows recommendation tool. To use this you will need any OpenAI API URL and API key with atleast one LLM model running. You can host your own OpenAI server with AI model using ollama or LM Studio. Or you can check https://openrouter.ai for limited-free LLMs.
admin and password 1234cd /etc/nginx/conf.ddocker cp nginx.conf nginx:/etc/nginx/conf.d/default.conf && docker exec -it nginx nginx -s reload
apk add certbot certbot-nginxserver_name localhost mediastack.example.com; in /etc/nginx/conf.d/default.confcertbot --nginx and provide details asked.location /radarr {
proxy_pass http://radarr:7878;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
}
location /sonarr {
proxy_pass http://sonarr:8989;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
}
This may need to change configurations in indexers and base in URL.
location /prowlarr {
proxy_pass http://prowlarr:9696; # Comment this line if VPN is enabled.
# proxy_pass http://vpn:9696; # Uncomment this line if VPN is enabled.
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
}
Note: If VPN is enabled, then Prowlarr is reachable on vpn's service name
location /qbt/ {
proxy_pass http://qbittorrent:5080/; # Comment this line if VPN is enabled.
# proxy_pass http://vpn:5080/; # Uncomment this line if VPN is enabled.
proxy_http_version 1.1;
proxy_set_header Host http://qbittorrent:5080; # Comment this line if VPN is enabled.
# proxy_set_header Host http://vpn:5080; # Uncomment this line if VPN is enabled.
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_cookie_path / "/; Secure";
}
Note: If VPN is enabled, then qbittorrent is reachable on vpn's service name
location /jellyfin {
return 302 $scheme://$host/jellyfin/;
}
location /jellyfin/ {
proxy_pass http://jellyfin:8096/jellyfin/;
proxy_pass_request_headers on;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
# Disable buffering when the nginx proxy gets very resource heavy upon streaming
proxy_buffering off;
}
Currently Seerr doesnot officially support the subfolder/path reverse proxy. They have a workaround documented here without an official support. Find it here
location / {
proxy_pass http://127.0.0.1:5055;
proxy_set_header Referer $http_referer;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-Port $remote_port;
proxy_set_header X-Forwarded-Host $host:$remote_port;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Port $remote_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Ssl on;
}
Neither the author nor the developers of the code in this repository condone or encourage downloading, sharing, seeding, or peering of copyrighted material.
Such activities are illegal under international laws.This project is intended for educational purposes only.
111 followers · starred May 2024
94 followers · starred Jul 2023
9 followers · starred Jan 2024
6 followers · starred Mar 2024
A self-hosted stack for media management and streaming, with AI-powered movie and show recommendations. Includes Sonarr, Radarr, qBitTorrent, Prowlarr, Jellyfin, Seerr, Recommendarr, and VPN support.
1,249
171 commits
updated Oct 10, 2026
A self-hosted media ecosystem that combines media management, streaming, AI-powered recommendations, and VPN.
This stack includes:
⚠️ Jellyfin v12 Upgrade Notice: This stack now ships Jellyfin 12.1. Upgrading from
10.11.xis a major upgrade that cannot be rolled back without a full restore.Before upgrading:
- Take a full backup of your Jellyfin data and config directories. The release includes database changes that prevent rolling back without a full restore.
- Remove third-party plugins first. Plugins built for 10.11 will not load on 12.x and must be updated by their authors before being re-added.
After upgrading:
- A full library scan is required.
See the Jellyfin 12.0 release notes for full details.
There are three ways to deploy this stack:
NOTE: If you are installing this stack without a VPN, you must use the
no-vpnprofile.
This requirement prevents accidental or unintentional deployment of media-stack without VPN.Running the
docker composecommand without a profile will not deploy anything.Check the installation steps below.
Before deploying the stack, you must first create a Docker network:
docker network create --subnet 172.20.0.0/16 mynetwork
# Update the CIDR range based on your available IP range
When VPN is enabled, qBittorrent and Prowlarr will run behind the VPN for added privacy.
By default, NordVPN is used in docker-compose.yml, but you can switch to:
All providers use the OpenVPN protocol.
➡️ Full list of supported VPN providers: VPN Providers
Refer to your VPN provider's documentation to generate an OpenVPN username and password.
For setup instructions, check:
➡️ Gluetun VPN Setup Guide
docker-compose.ymlBy default, VPN is disabled in docker-compose.yml. To enable it, simply comment/uncomment the required lines in the file.
The docker-compose.yml file includes clear instructions in the comments to guide you through the process.
Once updated, follow the steps below to deploy the stack with VPN.
VPN_SERVICE_PROVIDER=nordvpn OPENVPN_USER=openvpn-username OPENVPN_PASSWORD=openvpn-password SERVER_COUNTRIES=Switzerland RADARR_STATIC_CONTAINER_IP=radarr-container-static-ip SONARR_STATIC_CONTAINER_IP=sonarr-container-static-ip docker compose --profile vpn up -d
# OPTIONAL: Use Nginx as a reverse proxy
# docker compose -f docker-compose-nginx.yml up -d
A static container IP address is needed when Prowlarr is behind a VPN.
Since Prowlarr can only communicate with Radarr and Sonarr using their container IP addresses,
these must be manually assigned to avoid connection issues when containers restart.
Use the following environment variables to set static IPs:
RADARR_STATIC_CONTAINER_IPSONARR_STATIC_CONTAINER_IP🚨 Warning: Deploying without a VPN is highly discouraged as it may expose your IP address when torrenting media.
To proceed without VPN, run the following command:
docker compose --profile no-vpn up -d
# OPTIONAL: Use Nginx as a reverse proxy
# docker compose -f docker-compose-nginx.yml up -d
Recommendarr is a web application that uses AI to generate personalized TV show and movie recommendations based on your:
Run the following command based on your setup:
COMPOSE_PROFILES=vpn,recommendarr docker compose up -d # With VPN
# COMPOSE_PROFILES=no-vpn,recommendarr docker compose up -d # Without VPN
admin. Temporary password can be collected from container log docker logs qbittorrentdocker exec -it qbittorrent bash # Get inside qBittorrent container
# Above command will get you inside qBittorrent interactive terminal, Run below command in qbt terminal
mkdir /downloads/movies /downloads/tvshows
chown 1000:1000 /downloads/movies /downloads/tvshows
vpn in Host field.Sonarr can also be configured in similar way.
Add a movie (After Prowlarr is configured)
Note: If VPN is enabled, then Prowlarr will not be able to reach radarr and sonarr with localhost or container service name. In that case use static IP for sonarr and radarr in radarr/sonarr server field (for e.g. http://172.19.0.5:8989). Prowlar will also be not reachable with its container/service name. Use http://vpn:9696 instead in prowlar server field.
Recommendarr is an AI based movies/tvshows recommendation tool. To use this you will need any OpenAI API URL and API key with atleast one LLM model running. You can host your own OpenAI server with AI model using ollama or LM Studio. Or you can check https://openrouter.ai for limited-free LLMs.
admin and password 1234cd /etc/nginx/conf.ddocker cp nginx.conf nginx:/etc/nginx/conf.d/default.conf && docker exec -it nginx nginx -s reload
apk add certbot certbot-nginxserver_name localhost mediastack.example.com; in /etc/nginx/conf.d/default.confcertbot --nginx and provide details asked.location /radarr {
proxy_pass http://radarr:7878;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
}
location /sonarr {
proxy_pass http://sonarr:8989;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
}
This may need to change configurations in indexers and base in URL.
location /prowlarr {
proxy_pass http://prowlarr:9696; # Comment this line if VPN is enabled.
# proxy_pass http://vpn:9696; # Uncomment this line if VPN is enabled.
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
}
Note: If VPN is enabled, then Prowlarr is reachable on vpn's service name
location /qbt/ {
proxy_pass http://qbittorrent:5080/; # Comment this line if VPN is enabled.
# proxy_pass http://vpn:5080/; # Uncomment this line if VPN is enabled.
proxy_http_version 1.1;
proxy_set_header Host http://qbittorrent:5080; # Comment this line if VPN is enabled.
# proxy_set_header Host http://vpn:5080; # Uncomment this line if VPN is enabled.
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_cookie_path / "/; Secure";
}
Note: If VPN is enabled, then qbittorrent is reachable on vpn's service name
location /jellyfin {
return 302 $scheme://$host/jellyfin/;
}
location /jellyfin/ {
proxy_pass http://jellyfin:8096/jellyfin/;
proxy_pass_request_headers on;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
# Disable buffering when the nginx proxy gets very resource heavy upon streaming
proxy_buffering off;
}
Currently Seerr doesnot officially support the subfolder/path reverse proxy. They have a workaround documented here without an official support. Find it here
location / {
proxy_pass http://127.0.0.1:5055;
proxy_set_header Referer $http_referer;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-Port $remote_port;
proxy_set_header X-Forwarded-Host $host:$remote_port;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Port $remote_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Ssl on;
}
Neither the author nor the developers of the code in this repository condone or encourage downloading, sharing, seeding, or peering of copyrighted material.
Such activities are illegal under international laws.This project is intended for educational purposes only.
111 followers · starred May 2024
94 followers · starred Jul 2023
9 followers · starred Jan 2024
6 followers · starred Mar 2024