An interactive Python installer for a self-hosted media stack using Docker Compose.
This project does more than generate containers. It also waits for first boot, extracts API keys, applies shared credentials, links Prowlarr to Sonarr and Radarr, configures qBittorrent as a download client, and can bootstrap Jellyseerr and Dashy.
- Included Services
- Features
- Prerequisites
- Installation
- Usage
- Generated Layout
- Backup and Restore
- Migration Notes
- Updating or Rebuilding
- Troubleshooting
- License
- qBittorrent - Torrent client
- Prowlarr - Indexer manager
- Radarr - Movie collection manager
- Sonarr - TV series collection manager
- Jellyfin - Media server
- Jellyseerr - Request management for Jellyfin
- FlareSolverr - Cloudflare bypass for indexers
- Dashy - Dashboard for all services
- Interactive CLI built with
questionaryandrich - Service selection during install
- Shared admin credential setup for Jellyfin, Prowlarr, Radarr, and Sonarr
- Password confirmation prompt to avoid credential typos
- Automatic API key extraction and first-boot waiting
- Automatic linking between Prowlarr, Sonarr, and Radarr
- Automatic qBittorrent download-client setup in supported apps
- Optional Jellyseerr bootstrap using Jellyfin, Radarr, and Sonarr
- Optional Dashy config generation using the detected LAN IP
- Live progress table with active-step spinners and status updates
- Log output written to
arr_installer.log
Install these before running the script:
- Docker with Docker Compose support
- uv
- Git
- Python matching the requirement in
pyproject.toml
Note: The current project file declares
requires-python = ">=3.14". Ifuv syncrefuses to create the environment, check your local Python version first.
The script has been tested on Windows and Fedora Server.
git clone https://github.com/Fernandohf/arr-installer.git
cd arr-installer
uv syncTo activate the virtual environment manually (optional, as uv run handles this automatically):
Linux/macOS:
source .venv/bin/activateWindows:
.venv\Scripts\activateRun the installer:
uv run main.pyOptional flags:
uv run main.py --verbose
uv run main.py --debug- You choose the install path, timezone, and which services to deploy
- Selecting
Jellyseerralso enablesJellyfin,Radarr, andSonarr - Selecting
FlareSolverralso enablesProwlarr - The script asks for one shared admin username and password
The installer creates a server directory like this:
Server/
├── docker-compose.yml
├── config/
│ ├── qbittorrent/
│ ├── prowlarr/
│ ├── radarr/
│ ├── sonarr/
│ ├── jellyfin/
│ ├── jellyseerr/
│ └── dashy/
└── data/
├── torrents/
└── media/
├── movies/
└── tv/
docker-compose.yml: The stack definition generated by the installerconfig/: Service state, API keys, app settings, user databases, and integration configdata/: Downloads and media folders created by the installer layout
At minimum, back up the full install directory you chose during setup.
For a complete recovery or migration, keep:
docker-compose.yml- The entire
config/directory - The entire
data/directory if your downloads and media live there
You do not need to back up:
.venv/.uv-cache/__pycache__/arr_installer.log
-
Stop the stack cleanly from the generated server directory:
docker compose down
-
Copy the whole install directory to your backup target.
Windows:
robocopy C:\Server D:\Backups\Server /MIRLinux:
rsync -a /opt/server/ /backup/server/
-
Start the stack again on the original machine if needed:
docker compose up -d
To move the stack to a new machine:
-
Install Docker and Docker Compose on the new server
-
Install
uvonly if you plan to run the installer again (not required just to restore) -
Copy the backed-up install directory to the new server
-
Open a shell in that restored directory
-
Start the stack:
docker compose up -d
In most cases, restoring the generated directory is enough. The containers mount relative paths from that directory, so the stack can usually be moved as a single unit.
Rerun uv run main.py only if you want to generate a fresh install or rebuild configuration intentionally.
If you already restored a working backup, prefer starting it with:
docker compose up -dThis avoids overwriting an existing docker-compose.yml, Dashy config, or app state.
If the new server has a different LAN IP, review these items after restore:
config/dashy/conf.yml- Dashy shortcuts are generated using the detected LAN IP from the original install
- Jellyseerr settings
- The script writes external service URLs using the detected LAN IP during bootstrap
- Any bookmarks, reverse proxy config, or firewall rules outside this repo
Internal container-to-container links (such as prowlarr, radarr, sonarr, and qbittorrent) generally keep working as long as the same Compose service names are preserved.
From the generated server directory:
docker compose pull
docker compose up -dIf a container conflict exists, the installer can offer docker compose down and retry during a fresh run, but for an existing deployment it is usually clearer to manage the stack directly with Docker Compose.
- If startup or API setup fails, inspect
arr_installer.log - If
uv syncfails, verify your Python version matchespyproject.toml - If some services do not appear in Dashy after a migration, update
config/dashy/conf.ymlwith the new host/IP and restart Dashy - If Jellyseerr points to old host addresses after a migration, update its settings from the UI or restore/edit its config and restart the stack
This project is licensed under the MIT License. See LICENSE.