There's a version of this hobby where the media server runs on one machine, the files live on another, the library tools run on a third, and every one of them has a slightly different idea of where anything is. It works, sort of, until it doesn't โ and then you're debugging four programs that each believe a different thing about the same file.
The alternative is boring and much better: put all of it on the NAS. The storage, the media server, and the library tools, on one box, sharing one filesystem. Most of the problems in the other articles here simply don't happen in this arrangement, and the ones that do are much easier to reason about.
A UGREEN NAS with a mirrored pair of 20 TB drives, formatted ext4, running everything in Docker: the media server, the library tools, and the subtitle manager. Roughly 19 TB usable. None of the advice below is UGREEN-specific โ the same layout applies to Synology, QNAP, TrueNAS, Unraid, or a repurposed desktop with a couple of drives in it. The brand matters far less than the mount layout.
Why one box
- Hardlinks become possible. They only work within a single filesystem. Split your files across machines and every import silently duplicates. This is the big one โ see the disk space article.
- No network hop between the library and the files. Importing a large file becomes a filesystem operation rather than a transfer.
- One place to reason about permissions. When four programs write to the same tree across three machines, permissions become a genuine research project.
- It's already on. A NAS is a machine designed to run continuously and quietly. That's exactly the job description.
The mount layout, which is the whole trick
Everything runs in containers, and each container only sees the paths you hand it. That choice is the single most consequential decision in the setup, and it's the one most people get wrong.
Tools that move files get the whole root
Your library managers move files from a working directory into the organized library. For them to link rather than copy, they must be able to see that both locations are on the same filesystem. So you mount one root, not individual folders:
# The librarians โ one root, mapped to one path
/storage โ /data
# Which means, from inside the container:
/data/downloads the working directory
/data/media/tv the organized library
/data/media/movies Not this, which is the common mistake:
# โ Three separate mounts. Nothing can be linked.
/storage/downloads โ /downloads
/storage/media/tv โ /tv
/storage/media/movies โ /movies Both layouts work. Files arrive, get named, show up in your library. The second one just quietly stores everything twice forever, and gives you no indication it's doing so.
Tools that only read can have a narrower view
The media server itself never moves anything between directories โ it reads the finished library. So it doesn't need the shared root, and it's perfectly fine for it to see a different path entirely:
# The media server โ only needs the library
/storage/media โ /media
/storage/media/transcode-temp โ /transcode This trips people up because the advice "all your paths must match" gets repeated without the qualifier. The tools that move files must agree with each other. The tool that only plays files doesn't have to agree with anybody.
The exception is anything that writes into your library โ a subtitle manager, for instance. Those should see the library the same way the media server does, since they're putting files alongside your episodes.
Configs live outside the media tree
Each application gets its own configuration directory, kept well away from your media:
/storage/apps/config/sonarr โ /config
/storage/apps/config/radarr โ /config
/storage/apps/config/plex โ /config Two reasons this matters more than it looks:
- Backups. Your config directories are small, irreplaceable, and represent years of accumulated setup. Your media is enormous and mostly re-creatable. Keeping them separate lets you back up the important part properly.
- Rebuilds. Containers are disposable. When configuration lives outside, you can destroy and recreate one at any time and it comes back exactly as it was.
Make every container write as the same user
Containers run as whatever user you tell them to. If one writes as one identity and another as a different one, you get a library where some files can't be modified by the tool that needs to modify them. It surfaces as bizarre intermittent failures, and it is miserable to debug after the fact.
Set the same user and group ID across every container that touches media:
PUID=1000 # same everywhere
PGID=100 # same everywhere
TZ=America/New_York Set the timezone too, on everything. Scheduling, logs, and DVR recordings all depend on it, and a container defaulting to UTC will record the right show at the wrong time.
Give the transcoder its own scratch space
When the media server has to convert a file on the fly, it writes large temporary files. Point that at a dedicated directory rather than letting it land wherever the default is.
It keeps the mess in one identifiable place, it's easy to clear if a crash leaves debris behind, and if you ever add a fast drive to the machine it's a single setting to relocate.
Three things this arrangement doesn't solve
- RAID is not a backup. A mirrored pair survives a dead drive. It does not survive an accidental delete, a bad move operation, or the array itself failing โ both copies are updated identically and instantly. Anything genuinely irreplaceable (home video, family photos, your config directories) needs a real backup somewhere else. Your ripped disc collection is inconvenient to lose. It isn't the same thing.
- NAS processors are modest. Great at serving files, unremarkable at converting video. If viewers' devices can play your files directly, one box serves a lot of people. If they can't, you'll find the ceiling faster than you expect. Enable hardware transcoding if it's available โ it's the difference between one stream and several.
- Capacity sneaks up on you. An array at 90% is fine right up until an import fails halfway and leaves things in a strange state. Decide your uncomfortable number in advance and act on it while the situation is still boring, not at 100% with things already breaking.
Setting it up in the right order
- Decide the directory tree first โ one root, media and working directories beneath it. Changing this later means re-importing everything.
- Mount that root into the librarians, as a single mapping.
- Mount the media directory into the server, plus a transcode scratch path.
- Put configs somewhere separate, one directory per app.
- Set matching user, group, and timezone on everything.
- Verify hardlinks actually work before importing at scale โ import one file and check the link count. Details in the disk space article.
- Set up backups for the config directories while there's nothing in them worth losing.
Step six is the one people skip, and it's the one that costs terabytes. Sixty seconds of checking now against a very grim evening later.
The short version
- One box, one filesystem. Storage and services together.
- Tools that move files share a single mounted root. This is what makes linking possible.
- The media server only reads โ its paths don't need to match anyone else's.
- Configs live outside the media tree, one per app, and get backed up.
- Same user, group, and timezone on every container.
- RAID is redundancy, not backup. Know the difference before you need to.