> ## Content Index
> Fetch the complete content index at: https://blog.dbotech.net/llms.txt
> Use this file to discover other available public pages before exploring further.

# How my self-hosted media server works
- URL: https://blog.dbotech.net/how-my-self-hosted-media-server-works/
- Published: 2026-09-22T00:58:49.000Z
- Updated: 2026-09-22T00:59:22.000Z
- Description: How Jellyfin, TrueNAS, Radarr, Sonarr, qBittorrent, Seerr, and Recyclarr turn one storage path into a media library I control.
- Author: Derr
- Tags: Self-hosting, Homelab, Jellyfin, Media Server, Docker

I built my media server because I wanted to own my media again.

Streaming was convenient until every service started carving out its own catalog, raising its price, and reminding me that access could disappear whenever a licensing deal changed. I was tired of paying more while having less control over what I could watch.

My answer was a self-hosted setup built around Jellyfin. It keeps my movies, television, and anime in one library that I control. The finished system feels simple from the couch, but there is a fair amount happening behind the Play button.

## What runs the server

The stack is split into a few jobs:

- **Jellyfin** presents the library and handles playback.
- **Seerr** is the front door for adding something I want to watch.
- **Radarr** manages movies.
- **Sonarr** manages regular television and anime.
- **Prowlarr** gives the Arr applications one place to manage their configured sources.
- **qBittorrent** is the active download client.
- **Recyclarr** keeps my quality profiles and custom formats aligned with TRaSH Guides.
- **TrueNAS** holds the actual media over NFS.

Everything runs in Docker and is managed through Dockge. I like having each service in its own Compose stack. Updates are easy to understand, configuration lives outside the containers, and I can work on one part without pretending the whole server is one giant application.

## One storage path underneath everything

The most important decision was not which app to install. It was the folder layout.

All of the applications that move or organize files see the same `/data` path. On the host, that path is backed by an NFS share from TrueNAS. Inside the containers, Radarr, Sonarr, and qBittorrent all see the same structure:

```
/data/
├── torrents/
│   ├── movies/
│   ├── tv/
│   └── anime/
├── usenet/
│   ├── incomplete/
│   └── complete/
└── media/
    ├── movies/
    ├── tv/
    └── anime/

```

The layout leaves room for both torrent and Usenet workflows, although qBittorrent is the active client today. Downloads and finished media stay on the same filesystem. That matters because the Arr applications can use hardlinks instead of making a second full copy of a large file.

Jellyfin gets a narrower view. It sees only the finished media directory, mounted read-only as `/media`. Jellyfin can scan and play files, but it does not need permission to reorganize or delete them. That boundary is intentional.

## From request to playback

The workflow starts in Seerr. I choose a movie or series, and the request goes to the appropriate manager.

Radarr handles movies. Sonarr handles television and anime, with a separate profile for each type. They decide whether a release fits the rules I have set, send the job to the download client, and then import the completed file into the finished library.

Jellyfin scans the library and adds the title to its catalog. By the time I sit down to watch, the messy part has disappeared. I see artwork, seasons, episode descriptions, subtitles, and a Play button.

I deliberately leave source and provider details out of the public configuration. They are not important to the design anyway. The useful part is the division of responsibility: one app accepts requests, the Arr applications make organization decisions, the download client transfers data, and Jellyfin serves the result.

## Quality without endless upgrades

I use Recyclarr to keep the quality logic consistent instead of rebuilding profiles by hand. It syncs selected TRaSH Guides definitions into Radarr and Sonarr every day.

My regular television profile targets WEB 1080p. Movies use an HD Blu-ray and WEB profile. Anime has its own 1080p profile with a strict English-audio requirement.

The anime rule is intentionally picky. A generic label such as “dual audio” is not enough by itself. The release needs an explicit English-audio match. Raws, low-quality groups, AV1 releases, and French-subtitled releases are rejected by the profile.

I also keep automatic upgrades disabled. Once a file is in the library, I do not want Radarr or Sonarr replacing it because a release with a slightly better score appeared later. The profiles control new and missing downloads without turning the library into a permanent upgrade queue.

That choice is less automated than the default enthusiast setup, but it is much easier to live with. Storage use stays predictable and existing files remain where I left them.

## Jellyfin stays at the center

Jellyfin is the part people actually interact with, so I keep the rest of the stack out of its way. It has read-only media access, persistent configuration, a separate cache, and access to the server's graphics device through `/dev/dri` for hardware-accelerated transcoding.

Most of my viewing does not need much server-side work. On my laptop I use Jellyfin Media Player. On the Apple TV I use Infuse, which requires a paid subscription but gives me the playback experience I want in the living room.

Infuse connects to the Jellyfin library, so I still keep one source of truth for watched status and organization. The client is different, but the library remains mine.

## The difficult part was the existing library

Installing Jellyfin was easy compared with organizing years of existing media.

The old library had inconsistent movie folders, duplicate releases, and names that did not always tell Radarr or Sonarr what they were looking at. Moving everything into a shared `/data` structure required backups, dry runs, collision checks, and a refusal to guess when two files looked similar.

I learned to treat media cleanup like a data migration rather than a weekend file-sorting project. A duplicate should only be removed after proving that a retained copy exists. A folder should only be moved when the destination is unambiguous. If an anime release has unclear language metadata, it is safer to review it than to let an automated rule decide.

That caution made the migration slower. It also kept “cleanup” from becoming another word for accidental deletion.

## What self-hosting changes

This setup still needs maintenance. Containers need updates. Metadata occasionally needs correction. A title can be matched incorrectly, and a profile can be stricter than I intended. Self-hosting replaces a subscription company's decisions with my own, including the bad ones.

For me, that trade is worth it. I know where the files live. I choose the clients. I can change the quality policy without waiting for a streaming service to offer a better tier. If a company removes a title from its catalog, my library does not change.

The best part is that none of this complexity follows me to the couch. I open Jellyfin or Infuse, choose something, and watch it. The server quietly handles everything else.

## Where I would start today

If I were building the system again, I would begin with the storage layout before importing a single title:

1. Give every file-moving application the same `/data` mount.
2. Keep downloads separate from the finished media library.
3. Mount the finished library read-only in Jellyfin.
4. Create separate Sonarr profiles for regular television and anime.
5. Use Recyclarr for repeatable quality rules, then turn off upgrades if you do not want existing files replaced.
6. Back up the application databases before reorganizing an existing library.

The applications can change. The clean path model and the separation of responsibilities are what make the setup manageable.

I started this because I was tired of rising streaming prices and rented access. What I ended up with is a library that behaves the way I want it to, on the devices I actually use, with no company in the middle deciding whether a title should still be there next month.