jaime.build home

Media automation stack

1,700-plus movies and 160-plus shows, each added with about thirty seconds of work.

Automated movie and TV pipeline, grab to playback.

Radarr · Sonarr · rclone · Plex · Jellyfin

Status
Live
Movies
1,700+
TV shows
160+
Sync intervals
30 / 45 min
Manual effort per item
~30 sec

Why I built it

I keep my own movie and TV library instead of renting access to someone else's. The catch is upkeep. Every new movie used to mean downloading a file, moving it to the server, renaming it so the media server would recognize it, filing it in the right folder, and kicking off a library scan. That's fine for ten movies. It stops being fine long before 1,700 of them, and TV makes it worse because one show can be hundreds of episodes across a dozen seasons.

The goal was the same one behind my ebook pipeline: shrink the manual work down to the one decision worth making by hand. I pick what enters the library. The downloading, transferring, naming, sorting, and serving all happen without me.

What it is

The pipeline runs across two machines: a rented seedbox that does all the torrenting, and my home server, which stores and serves the library.

on the seedbox Prowlarr indexer manager Radarr / Sonarr collection managers Media folders completed downloads on my home server rclone sync every 30/45 min Unraid array one media share Plex + Jellyfin two servers, one library
Adding the torrent is the only manual step, about thirty seconds

It starts with a grab. I find a release on a private tracker and add the torrent to Deluge on the seedbox. My part takes about thirty seconds, and it ends there. A label goes on at add time, and Deluge routes the completed download into a movies folder or a TV folder on its own.

Radarr and Sonarr run on the seedbox too, one managing the movie collection and one managing TV. They search through Prowlarr, my indexer manager and the single place tracker credentials live, and they handle the part of library upkeep I hated most, the naming. Files come out matching the conventions media servers expect, down to season folders and episode numbering. I never rename anything.

From there my home server takes over. Two rclone scripts run on a schedule through Unraid's User Scripts plugin, movies every thirty minutes and TV every forty-five. Each one copies anything new from the seedbox down to the media share on the array. They copy instead of moving, so the seedbox keeps its files and the torrents keep seeding.

Once files land on the array, everything downstream reads from that one share. Plex and Jellyfin both serve it. Tautulli sits next to Plex, tracking play history and stream quality.

There's also a lazier entry point than the tracker itself. Seerr puts a Netflix-style browse and request screen in front of the whole thing. Hit request on a movie or show, and it flows to Radarr or Sonarr, which take it from there. It works fine from a phone, which is where I mostly use it.

The library this feeds currently sits at more than 1,700 movies and 160 shows, over 6,000 episodes in all.

Why both Plex and Jellyfin

Running two media servers on one library looks like indecision, and for a while it was. Jellyfin went in as an evaluation against Plex, with the assumption that one of the two would eventually go.

Neither one lost. Jellyfin is faster and snappier in daily use, and its web UI makes Plex feel bloated by comparison. Plex wins on Skip Intro, where its native feature is more reliable than Jellyfin's audio fingerprinting plugin, and its mobile apps are more polished. Six weeks in, neither gap looked big enough to give up the other side's strengths, so I stopped treating it as a competition and made both permanent.

Keeping both costs almost nothing. The media exists once on disk, both servers read the same share, and the second front end amounts to one more container and a config folder. Anything Radarr or Sonarr delivers shows up in both after a scan. Jellyfin also handles hardware transcoding.

The hiccups

The sync scripts ran clean while copying nothing. At some point the seedbox provider migrated my account to a different server, and the rclone config on my end kept the old hostname. The scripts kept firing on schedule and exiting with zero errors while transferring nothing at all. I caught it when grabs stopped showing up in the library. One hostname update fixed it, but the scripts had been reporting success the whole time, and that bothered me more than the outage did.

Deluge learned to play dead. The daemon on the seedbox would occasionally die and leave zombie processes behind, and the watchdog that was supposed to catch this used pgrep, which counts a defunct process as a running one. So Deluge could be down while every check swore it was up. The fix was a smarter restart script that verifies the daemon actually responds instead of merely existing in the process table.

Radarr was doubling my storage. Its import step left me with two full copies of each movie, the seeding original and the renamed library file. Hardlinks fixed it. A hardlink is one file with two names, so the torrent keeps seeding under its original name while the library sees a clean renamed one, and the data sits on disk once.

Plex browsing got slow. The library started to drag, with covers and metadata loading late. Plex keeps its metadata as an enormous pile of tiny files, and on Unraid that pile was living behind the user share layer, which adds overhead to every file operation. Pointing the config volume straight at the cache pool cut the share layer out of the path and brought browsing back to normal.

What I'd do differently

I'd build verification into the sync scripts from day one. The stale hostname failure was only possible because a clean exit code was my entire definition of success. A few extra lines, checking whether anything transferred and when the last file landed, would have caught the dead connection on the first run. Instead the library sat quietly frozen until I noticed. Every scheduled job I run now checks what it moved, not just its exit code.