If you run Sonarr, Radarr or Lidarr in Docker and imports feel slow, or your free space drops by the size of every episode twice, the cause is almost always the same thing: too many volume mounts. The fix is boring and it is one line per container.

The symptom

A download finishes. The *arr picks it up and imports it. On a healthy setup that import is instant, no matter how big the file, and the download stays seeding without using a second copy of the disk space. On a broken setup the import takes as long as it would take to copy the file, and for a while you are holding two full copies of every release.

That difference is a hardlink versus a copy, and whether you get one or the other comes down to how the container sees the filesystem.

Why it happens

A hardlink is a second name for the same data on disk. It costs nothing and takes no time, but it only works within a single filesystem. The same is true of an atomic move: renaming a file within one filesystem is instant, while “moving” across filesystems is really copy-then-delete.

Here is the trap. On the NAS, /volume1/downloads and /volume1/TVShows are the same filesystem. But if you hand the container two separate bind mounts:

volumes:
  - /volume1/downloads:/downloads
  - /volume1/TVShows:/tv

then inside the container those are two separate mount points. The import gets treated as a cross-device operation, the hardlink is refused, and the move degrades to a full byte-for-byte copy followed by a delete. The host knew they were the same filesystem. The container did not.

The fix

Mount the parent once, and let the paths sit underneath it:

volumes:
  - /volume1/config/sonarr:/config
  - /volume1:/data

That is it. Every one of my *arrs and both download clients carry the same /volume1:/data line, with a comment in the compose file so future me does not “tidy it up”:

- /volume1:/data          # single mount: downloads + libraries on one filesystem

Inside the container the root folder becomes /data/TVShows, and the download client’s completed folder becomes /data/downloads/complete. Both sit under one mount point, so hardlinks and atomic moves work the way they were meant to.

The download client has to agree. If SABnzbd reports a path the *arr cannot resolve identically, you end up reaching for Remote Path Mappings, which is a patch over a problem you no longer need to have. Give SABnzbd and Transmission the same /volume1:/data and the paths line up on their own.

The other half: permissions

Hardlinks also need the process to be allowed to create them. Every container in the stack runs as the same user and group, with the same umask:

environment:
  PUID: 1026
  PGID: 101
  UMASK: "002"

UMASK: "002" is the part people miss. It makes new files group-writable, so the *arr that imports a file and the client that downloaded it are not fighting each other over who owns what.

The exceptions, and why they exist

Not everything wants the single mount, and it is worth being deliberate about which.

Plex only ever reads. It never imports, never moves, never hardlinks, so it gets narrow, purpose-named mounts instead: /volume1/Movies:/movies, /volume1/TVShows:/tv, and so on. Narrower is better when a container has no business writing to the library.

Prowlarr gets no media mounts at all. It only syncs indexers to the other *arrs, so there is nothing for it to see.

And then there is the honest wart. Lidarr carries one extra mount purely so that Soularr keeps working:

- /volume1/downloads/complete/slskd:/downloads/slskd   # kept so Soularr keeps working

That is exactly the pattern this post is arguing against, and it is there because a third-party tool hardcoded expectations about the path. The right answer was to point Soularr at the same folder expressed through the /data mount instead, so the import stays a hardlink, which is what it does now. The extra mount is a leftover I have not removed yet. More on that stack in the next post.

How to check yours

The quickest test is to look at the link count. After an import, run this on the host against the downloaded file:

ls -li /volume1/downloads/complete/some.release.mkv

The number in the second column is the link count. If it is 2, you have a hardlink and the library copy is the same data on disk. If it is 1, you have two separate copies and you are paying for both.