Try a shorter word — “disk” rather than “disk space running out”. Or clear the search to browse everything.
The four commands
Run these before changing a single setting. Between them they identify the cause of most problems, and they never make anything worse.
Look at the STATUS column. “Restarting” means it's crash-looping. “Exited” means it gave up.
docker compose ps
This is where the answer usually is. Read from the bottom up — the last error before a restart is the real one.
docker compose logs --tail 50 servicenameA full disk causes bizarre, unrelated-looking failures across every container at once.
df -h docker system df
Worth one try. If it comes back broken, it's configuration, not a glitch — go back to the logs.
docker compose restart servicenameerror, failed, denied or refused. Everything above it is usually normal startup chatter. If you paste that one line into a search engine along with the app's name, you'll almost always find your answer.A container won't start
CommonA container keeps restarting over and over
A restart loop means the app starts, hits a fatal error, and dies — repeatedly. The error is in the logs every single time.
docker compose logs --tail 60 servicename
In this stack it's nearly always one of four things:
| What the log says | What it means |
|---|---|
| permission denied | PUID/PGID don't match the folder owner. See the permissions section. |
| no such file or directory | A path in your .env doesn't exist on the host yet. |
| address already in use | Another program has that port. See the port conflict entry. |
| database is locked / corrupt | Usually an unclean shutdown. Restore the config folder from backup. |
If the logs are empty, the container is dying before it can write anything — that points at a bad image, an unsupported architecture, or a malformed environment variable.
“Port is already allocated” or “address already in use”
Something else on the machine is using that port. Find out what:
# Linux / macOS sudo ss -tulpn | grep 8096 # or sudo lsof -i :8096
Then either stop that program, or change the host side of the mapping in your Compose file. The left number is the host, the right is inside the container — only change the left one:
ports: - "8097:8096" # now reachable on :8097
“No such file or directory” on a volume
Docker will happily create an empty directory where you meant to point at real data, so this often shows up as an app that starts but sees nothing.
Check the paths in your .env actually exist, exactly as written:
ls -la /srv/media /srv/downloads
Watch for typos, a missing letter of case (/Media vs /media matters on Linux), and trailing slashes. If a folder is genuinely missing, create it and set ownership:
sudo mkdir -p /srv/media/{movies,tv,music}
sudo chown -R $USER:$USER /srv/media
“No matching manifest” or the image won't pull
The image has no build for your CPU architecture. This turns up on Raspberry Pi and Apple Silicon.
uname -m # aarch64 or arm64 means ARM
You can force emulation as a stopgap, at a real speed cost:
services:
something:
platform: linux/amd64
In this stack, Tube Archivist's Elasticsearch component is the usual culprit on ARM. Everything else has native builds.
Everything broke at once and I changed nothing
Check the disk first. A full disk produces failures that look like anything but a full disk.
df -h docker system df
If Docker itself is hoarding space, clear what isn't in use:
docker image prune -a docker system prune
docker system prune --volumes will remove unused volumes, and if a container happens to be stopped at that moment, its data can be considered unused. Avoid the --volumes flag unless you're certain.The usual cause is a downloads folder nobody has emptied, or old images from months of updates.
I can't reach it
CommonThe web page won't load at all
Work through this in order — it's almost always number 2 or 3.
- Is it running?
docker compose ps— if it's not up, this is a startup problem, not a network one. - Right address? From another device you need the server's IP, not
localhost. Find it withhostname -Ion Linux, oripconfigon Windows. - Right port? Check the left-hand number in the
ports:mapping. - Firewall? On Ubuntu,
sudo ufw allow 8096. On Windows, allow Docker Desktop through on private networks. - Behind the VPN? qBittorrent and Jackett publish through Gluetun. If Gluetun is unhealthy, both become unreachable even though they're running.
Very commonSonarr or Radarr can't connect to qBittorrent
This is the single most frequent problem with this stack, and the fix is counter-intuitive.
Inside a container, localhost means that container — not your server. So pointing Sonarr at 127.0.0.1:8080 makes it look inside itself, find nothing, and report a connection failure.
Containers reach each other by container name. But qBittorrent is a special case here: because it uses network_mode: service:gluetun, it has no network identity of its own — it lives inside Gluetun's network. So other containers must ask for Gluetun.
| In Sonarr, set download client to | Host | Port |
|---|---|---|
| qBittorrent behind a VPN | gluetun | 8080 |
| qBittorrent with no VPN | qbittorrent | 8080 |
| Jackett behind a VPN | gluetun | 9117 |
The same rule applies everywhere: Jellyseerr finds Sonarr at sonarr:8989, Bazarr finds Radarr at radarr:7878.
docker compose exec sonarr ping -c2 gluetun — if that resolves, the name is right and your problem is the port or the password instead.How do I reach my server from outside the house?
Three approaches, in the order most people should consider them.
- Tailscale — install it on the server and your phone, and they behave as though on the same network. Nothing is exposed publicly, it works around CGNAT, and it takes about five minutes. Start here.
- Cloudflare Tunnel — gives you a real public address without opening any ports. Good when you want other people to reach it. Note their terms on proxying large video streams.
- Reverse proxy with port forwarding — the traditional route. Most flexible, most to get wrong. You'll want proper certificates and, ideally, an auth layer in front of anything administrative.
Permissions and file ownership
Very common“Permission denied” or an app can't write to its folder
The container runs as a specific user ID, and that ID doesn't have rights to the folder you mounted.
Find your own IDs:
id
# uid=1000(you) gid=1000(you) ...
Put those numbers in .env as PUID and PGID, then make sure the folders are actually owned by that user:
sudo chown -R 1000:1000 /srv/media /srv/downloads docker compose up -d
Check what a container thinks it is, if you're unsure:
docker compose exec sonarr id
id reports.Imports copy the file instead of moving it, and I'm using double the space
Sonarr and Radarr can hardlink — effectively giving a file two names for free — but only when the download and the library are on the same filesystem and are visible through a single mount inside the container.
Mounting them separately breaks it, even on the same disk:
# Breaks hardlinks — two separate mounts
- /srv/downloads:/downloads
- /srv/media/tv:/tv
Mount one shared parent instead, and keep both underneath it:
# Works — one mount, consistent paths - /srv/data:/data # on the host: # /srv/data/downloads # /srv/data/media/tv
Then point qBittorrent at /data/downloads and Sonarr's library at /data/media/tv. Every app must see the same path for the same file.
Sonarr says the download finished but can't find the file
The download client is reporting a path that means nothing to Sonarr. qBittorrent says the file is at /downloads/x, Sonarr looks at /downloads/x, and if those two containers mount different host folders under the same name, they disagree about reality.
The proper fix is consistent mounts, as above. The patch is a remote path mapping in Sonarr under Settings → Download Clients → Remote Path Mappings, telling it that the client's /downloads is its own /data/downloads.
Verify what each container actually sees:
docker compose exec qbittorrent ls /downloads docker compose exec sonarr ls /downloads
If those two listings differ, that's your problem in one command.
VPN and downloads
CommonGluetun won't start or shows as unhealthy
Read its logs first — Gluetun is unusually clear about what's wrong.
docker compose logs --tail 40 gluetun
Ranked by how often each is the cause:
- Provider name spelled differently. It must match Gluetun's own spelling exactly, lowercase —
private internet access, notPIA. - Wrong key. A WireGuard private key is required, not the public one. It ends in
=and is about 44 characters. - Missing address. WireGuard also needs
WIREGUARD_ADDRESSES, something like10.64.0.2/32. - No TUN device. The container needs
/dev/net/tunandNET_ADMIN. Both are in the generated file — check they weren't dropped. - A country with no servers. Leave
SERVER_COUNTRIESempty to test.
Kima has its own downloader — is that behind the VPN?
No, and this is worth understanding before you use it.
Kima includes built-in Soulseek support for finding music directly, plus optional Lidarr-driven downloads. Unlike qBittorrent, Kima is not routed through Gluetun in the generated stack — it runs on the normal Docker network, because it also has to serve your library to your devices.
So if you enter Soulseek credentials in Kima\'s settings, that peer-to-peer traffic uses your ordinary connection. That may be perfectly fine for you, but it should be a decision rather than a surprise.
If you want that traffic tunnelled, you would need to route Kima through Gluetun as well, which complicates reaching its web interface. Leaving the Soulseek integration unconfigured avoids the question entirely — everything else in Kima works without it.
How do I confirm the VPN is actually working?
Ask the container what the internet thinks its address is:
docker compose exec gluetun wget -qO- https://ipinfo.io/ip
Compare it to your real address:
curl -s https://ipinfo.io/ip
Those two must be different. If they match, traffic is not going through the VPN — stop and fix that before downloading anything.
Confirm qBittorrent is genuinely sharing that network:
docker compose exec qbittorrent wget -qO- https://ipinfo.io/ip
It should return the same address as Gluetun. Worth re-checking after any change to the download stack.
I can't log into qBittorrent
Recent qBittorrent versions no longer ship a fixed default password. On first start they generate a temporary one and write it to the log:
docker compose logs qbittorrent | grep -i password
Log in as admin with that value, then change it immediately in Tools → Options → Web UI.
Downloads are stalled or crawling
Separate the two possible causes before changing settings.
- Nothing is downloading at all — likely the VPN. Check Gluetun is healthy and that qBittorrent has connectivity.
- It connects but stays slow — often no forwarded port. Without one you can only reach peers who can accept incoming connections, which cuts your available swarm considerably.
Some providers support port forwarding through Gluetun; many don't. Mullvad, AirVPN and Proton have historically been options, though policies change — check your provider's current position.
Also worth ruling out: a queue paused after a disk-full event, or speed limits left on in qBittorrent's options.
Library and playback
CommonJellyfin buffers or stutters
Almost always transcoding. Start playback, then look at the Jellyfin dashboard — if the active stream says “Transcoding” rather than “Direct Play”, your CPU is rebuilding the video in real time.
Common reasons a file gets transcoded:
- The client can't decode that codec — HEVC on older devices is the usual one.
- Burned-in subtitle rendering, which forces a full transcode.
- Limited upload bandwidth when watching remotely.
- A quality cap set in the client's own playback settings.
On native Linux with an Intel chip, enable hardware acceleration under Dashboard → Playback and pass the device through:
devices: - /dev/dri:/dev/dri
Jellyfin can't see my files
Check what Jellyfin actually sees, from inside the container:
docker compose exec jellyfin ls /media
Empty output means the mount is wrong — the host path in .env doesn't point where you think. Files listed but no library means it's a Jellyfin-side setting instead:
- Library folders must be added using the container path (
/media/movies), not the host path. - Naming matters for metadata matching.
Film Name (2019).mkvworks;film.final.copy.mkvoften won't. - Films and TV need separate libraries with the right content type set.
- Trigger a scan manually after adding folders.
Immich is slow or keeps failing
Immich is the most demanding thing in this stack. It runs a database, a cache and a machine-learning service alongside the app itself.
- Memory. Give it at least 4 GB, ideally more during an initial import. On Docker Desktop, raise the VM's allocation in Settings.
- First import is heavy. Thumbnails and face recognition for a large library take hours. That's normal.
- Don't change the database password after setup. The existing database still expects the old one, and the app will fail to connect. Restore the old value or start the database fresh.
- Version mismatches. The server and machine-learning images should be on the same release.
The wrong artwork or metadata keeps getting matched
Matching relies on filenames. Ambiguous names get ambiguous results.
Movies/The Thing (1982)/The Thing (1982).mkv TV/Show Name/Season 01/Show Name - S01E01.mkv
The year is what separates remakes from originals. If a specific item is stubborn, most apps let you set the match by ID manually — in Jellyfin, “Identify” on the item lets you paste a database ID directly.
Letting Sonarr and Radarr handle renaming avoids most of this, since they name files in the format these scanners expect.
Windows and macOS specifics
Everything is slow on Windows
Most likely your files are on the Windows side of the divide. Paths under /mnt/c/ cross a translation layer between Linux and Windows, and it's slow for the many-small-reads pattern that library scanning produces.
Keep media inside the WSL filesystem instead:
# Slow /mnt/c/Users/You/Videos # Fast /home/you/media
You can still browse those from Explorer via \\wsl$. If the media must stay on a Windows disk, mounting the whole physical disk into WSL with wsl --mount is faster than going through /mnt/.
Also worth checking: antivirus scanning Docker's data folder in real time, and WSL's memory cap in .wslconfig.
macOS can't see my external drive
Docker Desktop only mounts folders you've explicitly shared. Add the path under Settings → Resources → File sharing, and make sure VirtioFS is selected under General for reasonable speed.
My server stops working overnight
The machine is sleeping. Desktop operating systems assume nobody wants a computer running at 3am.
- Windows — Settings → System → Power, sleep set to Never on mains. On a laptop, set lid-close to do nothing.
- macOS — System Settings → Displays → Advanced → prevent sleeping when the display is off. Or run
caffeinate -sin a Terminal window. - Linux — usually already fine on a desktop install; check
systemctl status sleep.targetif not.
Also confirm Docker starts on login (Desktop) or at boot (sudo systemctl enable docker), and that services use restart: unless-stopped so they come back after a reboot.
General questions
Is any of this legal?
The software is entirely legal. Every application here is open source with legitimate uses — organising media you own, streaming your own recordings, archiving public-domain and Creative Commons material, backing up your own photos, downloading Linux distributions.
What you do with it is a separate question, and it's yours to answer. Downloading or sharing copyrighted material you have no right to is unlawful in most places, and no tool on this page changes that. Copyright law also differs meaningfully between countries.
This project doesn't provide, host, index or endorse unauthorised copies of anything, and nothing here is legal advice. If you don't have the right to a file, don't use this to obtain it.
Do I actually need a VPN?
If you're running qBittorrent, this project treats it as required, and the generator won't produce a torrent stack without one. BitTorrent publishes your IP address to every peer in a swarm by design — that's how the protocol finds people.
For everything else here, no. Jellyfin, Immich, the *arr apps and monitoring have no need for one.
What does this cost to run?
The software is free. Costs are hardware, electricity, and optionally a VPN.
A used mini PC at around $150 that lasts three years works out near $4 a month before electricity — a low-power machine typically adds a few dollars a month. Drives are the ongoing expense as a library grows.
The hardware page compares the options properly, including why renting a VPS is usually more expensive than owning hardware for anything storage-heavy.
Do I need to know Linux?
No. The Arcane path is designed so that after the initial install you manage everything from a web page — starting, stopping, updating and reading logs are all buttons.
You'll type commands twice: once to install Docker, once to start Arcane. Both are copy-paste, and the platform guide covers Windows, macOS, Linux and NAS separately.
That said, some understanding accumulates whether you plan it or not — and it's worth having. Reading a log file is the single most useful skill here, and it's less intimidating than it looks.
Do I have to install all of it?
No, and you shouldn't. That's the point of the project.
Start with Jellyfin. Add Jellyseerr when you want others to request things. Add Sonarr and Radarr when manually managing files gets tedious. Add Immich when you want your photos off someone else's cloud.
Every module you add is another thing to configure, update and eventually debug. A stack of three services you understand beats fifteen you don't.
Why Jellyfin rather than Plex?
Jellyfin is fully open source with no paid tier, no account with a third party, and no feature gated behind a subscription. Everything runs on your hardware.
Plex is more polished in places, has broader client support on older TVs, and its remote access setup is simpler for non-technical users. Those are real advantages.
This project builds around Jellyfin because self-hosting the whole stack is the goal. If Plex suits you better, most of the surrounding pieces — Sonarr, Radarr, Bazarr, qBittorrent — work identically with it.
How often should I update?
Monthly is a reasonable rhythm. Security updates for anything reachable from outside your network deserve more urgency.
docker compose pull docker compose up -d
In Arcane it's pull, then redeploy. Read release notes before major version jumps, particularly for Immich, which occasionally requires migration steps.
What should I back up?
Your config folder and your .env. That's every setting, key and connection you patiently configured, and it's small.
- Essential — the config directory,
.env,docker-compose.yml - Essential and irreplaceable — your Immich photo library and its database
- Nice to have — media, which can generally be re-acquired
Stop the stack before backing up databases, so you copy a consistent state:
docker compose stop
# run your backup
docker compose start
Will this run on a Raspberry Pi?
Partly. A Pi 4 or 5 handles Jellyfin for direct play, the *arr apps, and Uptime Kuma comfortably.
It won't transcode meaningfully, and Immich and Tube Archivist will struggle. Use an SSD rather than an SD card — SD cards fail under constant database writes, usually at the least convenient moment.
As a first server to learn on, it's a good choice. As the machine your household relies on, a used mini PC costs little more and does considerably more.
Why Arcane instead of Portainer?
Both manage Docker through a browser and either would work. Arcane is a newer, lighter Go application with a clearer interface for Compose projects, which is most of what this stack needs. It's BSD-3-Clause licensed.
Portainer is more established with a larger community and more documentation available. If you already run it, there's no reason to switch — everything here deploys the same way.
Can I move everything to a different machine later?
Yes, and it's easier than people expect. Copy three things: your docker-compose.yml, your .env, and your config directory. Then docker compose up -d on the new machine.
Points to watch: keep the same paths or update .env to match the new ones, check PUID and PGID against the new machine's user, and move media separately since it's usually far larger.
This is a good argument for starting on whatever computer you already own. Outgrowing it later costs you an afternoon, not a rebuild.
Still stuck?
When you go looking for help, bring the log line. “Sonarr won't connect” is hard to answer; the actual error text, your Compose file with secrets removed, and what you already tried usually gets a fast reply.
Useful first stops: each project's own GitHub issues and documentation — they're linked from the apps list — and the r/selfhosted and TRaSH Guides communities for stack-wide questions.
REDACTED before posting anywhere public — this catches people out regularly.