Skip to content

Jellyfin Movie Automation With a Discord Approve Button

By Bikram Bhujel

I wanted new movies to show up in Jellyfin without me hunting for them every weekend. What I didn't want was a server that downloads whatever it likes and fills my disks with films nobody in the house will watch. Most guides for Radarr and its friends stop at "add the movie and it downloads", which is exactly the part I wanted to control.

So I built it the other way round. A small job finds well rated movies every morning and asks first. Nothing downloads until I press Approve in Discord. This post is how I set it up on my TrueNAS and Proxmox homelab, including the three mistakes that made an approved movie quietly go nowhere.

Discord channel showing a Jellyfin movie request with green Approve and red Decline buttons posted by a Seerr bot

Quick answer

Use Seerr (the project that replaced Jellyseerr) as the approval gate in front of Radarr. Give a daily script a request only Seerr account, so everything it finds lands as Pending. A small Discord bot posts each pending request with Approve and Decline buttons and calls the Seerr API when you press one. Radarr then sends the approved movie to qBittorrent behind a VPN, and Jellyfin picks it up. The one setting that breaks it silently: Radarr must be marked as the Default server in Seerr.

What I wanted, and what I didn't

My rules were simple. Only films rated 7.5 or higher with at least 1,000 votes. Only things that are actually out to watch, not cinema releases. 1080p by default, because my pool is a 2.7 TB mirror and 4K remuxes eat that quickly. And the most important one: a human says yes before a single byte downloads.

The approval part is what makes this different from a normal Radarr setup. Radarr is great at finding and grabbing releases, but it has no idea whether you actually want a film. Seerr does. It is a request manager that sits between people and Radarr, and every request can wait for an admin to approve it.

How the pieces connect

Here is everything involved and where it runs in my setup. Your machines will differ, but the roles stay the same.

PartRuns onIts job
Movie scout (Python, systemd timer)Ubuntu VM on ProxmoxFinds good films once a day and files them as pending requests
SeerrDocker on TrueNAS (Dockge)Holds requests until approved, then hands them to Radarr
Discord botSame Ubuntu VMPosts pending requests with Approve and Decline buttons
Radarr and ProwlarrDocker on TrueNASPick the best 1080p release from the indexers
qBittorrentTrueNAS app, behind WireGuardDownloads, with a kill switch so my home IP stays hidden
JellyfinTrueNAS appPlays the finished film

The flow in one line: scout files a request, the bot posts it in Discord, I press Approve, Seerr sends it to Radarr, Radarr sends it to qBittorrent, the file lands in the Movies folder, Jellyfin shows it, and Discord says it's available.

If you don't have the VPN part yet, I wrote up how I run qBittorrent behind a free WireGuard VPN with port forwarding. Only download films you have the right to, of course. The approval step is a good place to make that call.

Step 1: Check the folders before anything else

I almost skipped this, and it's the bit that decides whether imports are instant or copy every file twice. Radarr and qBittorrent need to see the download folder and the movie library on the same filesystem, so Radarr can hardlink the finished file instead of copying it.

On my NAS, qBittorrent saw the share as /mnt/Pool/Jellyfin/JellyFin_Content, while Radarr's container mounted the same dataset as /media. Same disk, two different names. That works, but only if Radarr knows the two paths are the same place. In Radarr that's Settings > Download Clients > Remote Path Mappings:

Host:        192.168.0.50
Remote path: /mnt/Pool/Jellyfin/JellyFin_Content/
Local path:  /media/

I also checked that Jellyfin's Movies library pointed at the same Movies folder Radarr uses as its root folder. It did, under a slightly different spelling inside the Jellyfin container, which is normal. If Radarr writes to a folder Jellyfin doesn't scan, you'll approve films and never see them.

One thing I deliberately did not do: import my existing 400 or so films into Radarr. Radarr only manages what you add to it, so the old library stays exactly as it is and Radarr's renaming rules never touch it.

Step 2: Make Radarr pick sensible files

Out of the box, Radarr's HD-1080p profile happily grabs 1080p remuxes, which can be 30 GB or more for one film. I trimmed the profile and set size limits so a two hour film lands at around 12 GB at most.

SettingWhat I setWhy
HD-1080p profileWEB 1080p and Bluray 1080p onlyNo remux, no HDTV captures
Bluray-1080p sizePreferred 60, max 100 MB per minuteAbout 7 to 12 GB for a two hour film
Ultra-HD profileRemux removed, Bluray-2160p as the target4K only when I ask for it
Minimum free space50 GB (default was 100 MB)Stops imports before the pool fills
Rename moviesOnClean "Title (Year)" names for Jellyfin

While I was in there I found every indexer marked as failed. My Radarr and Prowlarr reach the internet through their own ProtonVPN tunnel, and it had dropped for a while that morning. The tunnel came back on its own, but Radarr keeps an indexer disabled for a bit after failures. Running Test All under Indexers cleared it. Two indexers in Prowlarr were also failing with "blocked by CloudFlare Protection", and adding the FlareSolverr tag to them fixed that.

Step 3: Install Seerr (Jellyseerr is now Seerr)

I went to install Jellyseerr and found its Docker image tagged as deprecated. Jellyseerr and Overseerr have merged into one project called Seerr, which works with Jellyfin, Emby and Plex. If you're following an older guide, use Seerr instead. The setup is the same idea.

Seerr's container runs as a normal user, so its config folder has to exist and belong to that user before it starts. My NAS doesn't give me a shell easily, so I let a tiny helper container create the folder first. This is the Docker Compose stack I deployed in Dockge:

services:
  seerr-init:
    image: busybox:1.37
    command: sh -c "mkdir -p /c/seerr && chown -R 568:568 /c/seerr"
    volumes:
      - /mnt/Pool/config:/c
    restart: "no"
  seerr:
    image: ghcr.io/seerr-team/seerr:v3.5.1
    init: true
    user: "568:568"
    environment:
      - TZ=Asia/Kathmandu
    ports:
      - 5055:5055
    volumes:
      - /mnt/Pool/config/seerr:/app/config
    depends_on:
      seerr-init:
        condition: service_completed_successfully
    restart: unless-stopped

A small tip if you paste this into Dockge's editor: it auto indents as you type, which wrecks YAML. Pasting the whole file at once is fine; typing it line by line is not.

Step 4: Connect Seerr to Jellyfin and Radarr

Seerr's setup wizard asks for your Jellyfin server first. I got "The username or password is incorrect" five times in a row before I noticed why. I had typed Radarr's port, 7878, into the Jellyfin port box. Seerr was asking Radarr to log me in, and Radarr said no. Jellyfin was on a different port, and with that fixed the login worked first time. If you get that error with credentials you know are right, check the port before resetting any password.

Then add Radarr in the Services step:

  • Hostname 192.168.0.50, port 7878, no SSL, URL Base empty.
  • The API key from Radarr's Settings > General.
  • Quality profile HD-1080p, your movies root folder, minimum availability Released.
  • Tick Default Server, Enable Scan and Enable Automatic Search.

That Default Server tick matters more than anything else on the page. More on that below.

Finally, check Settings > Users. New users should have Request permission only, with auto approve off. That is your gate.

Step 5: A daily scout that only asks

Seerr already knows ratings, vote counts and release dates, because it reads them from TMDb. So the scout doesn't need its own API keys. It signs in to Seerr as a request only user called hermes and uses Seerr's discover endpoint with filters:

GET /api/v1/discover/movies?sortBy=popularity.desc
    &voteAverageGte=7.5&voteCountGte=1000
    &primaryReleaseDateGte=2024-11-10&primaryReleaseDateLte=2026-09-11

For each result it skips anything Seerr already marks as available, requested or processing, which covers every film already in Jellyfin. It files at most five new requests a day and remembers what it filed, so a film I decline never comes back. Before doing anything it checks its own account, and if that account is an admin or can auto approve, it refuses to run. I added that because one wrong permission would turn "asks first" into "downloads everything".

It runs from a systemd timer on my Ubuntu VM:

[Timer]
OnCalendar=*-*-* 09:00:00
RandomizedDelaySec=15m
Persistent=true

The first dry run listed five films from 2026 that I didn't have, all above 7.5. A normal run filed one as Pending, and Seerr showed it waiting with no Radarr ID, which is exactly what I wanted to see.

Step 6: Approve straight from Discord

Seerr can post to Discord through a webhook, and that part took two minutes. The pending alert showed up in my channel with the poster and "Pending Approval". So I typed "Approved" under it. Nothing happened, obviously. A webhook only sends messages into Discord. It can't read anything back.

To approve from Discord you need a real bot, because only bots receive button clicks. Mine is about 150 lines of Python with discord.py, running as a systemd service next to the scout. It does four things:

  1. Every minute it asks Seerr for pending movie requests and posts any new one with the poster, rating and two buttons.
  2. When someone presses a button, it checks they have the Manage Server permission. Anyone else gets a private "only admins" reply.
  3. It calls Seerr's approve or decline endpoint with Seerr's own API key.
  4. Eight seconds after an approval it reads the request back and checks Seerr really handed it to Radarr. The message then changes to "Approved, sent to Radarr, downloading", or warns me if it didn't.

Setting up the bot itself is done in the Discord Developer Portal: create an application, copy the bot token, and invite it to your server with View Channels, Send Messages, Embed Links and Read Message History. It doesn't need any privileged intents. Keep the token in a file only the bot's service user can read, never in the script.

Once the bot was posting pending requests, I turned off Seerr's own "Request Pending Approval" webhook alert so every film didn't appear twice. The webhook still posts Approved, Available and Failed.

The first real test: I pressed Approve on the message, Radarr picked a 3.9 GB 1080p WEB release, and qBittorrent was pulling it at about 5.7 MB/s with 23 minutes left.

What went wrong along the way

Approved, but nothing downloaded

The very first film I approved sat there as Approved and never reached Radarr. Seerr's log had the answer: "There is no default Radarr server configured." I had ticked Default Server during setup and checked it afterwards. It turned out an older Seerr tab still had the Radarr form open with the old values, and saving it there wrote them back. Lesson: close stale settings tabs, and if an approval doesn't download, check this flag first.

Worse, a request stuck like that can't be retried or edited. Seerr answers "Only pending requests can be modified". I had to delete the request and its media entry in Seerr and request the film again. That's also why the bot now checks for a Radarr ID after every approval instead of trusting the button press.

Deleting a torrent doesn't cancel a film

I deleted one download in qBittorrent because I changed my mind about the film. Radarr still had the movie marked as wanted, so it would simply have grabbed it again on its next search. The right way is to press Decline, or remove the movie in Radarr with "add import exclusion" ticked, and clear the request in Seerr.

Typing keys into a VM console

Getting the bot token onto the VM was harder than writing the bot. The Proxmox console doesn't take pastes, and my Mac couldn't reach the VM on the home network at all, even though the VM could reach the Mac. The VM was already on my Tailscale network, so I SSHed in over Tailscale and pasted the keys into nano from there. If you're stuck on a console, check whether Tailscale is already giving you a way in.

How to roll it back

  • Stop new requests: sudo systemctl disable --now movie-scout.timer on the VM. Nothing else changes.
  • Remove the buttons: sudo systemctl disable --now seerr-bot, then turn Seerr's Pending Approval webhook alert back on.
  • Undo Radarr changes: put Remux back in the HD-1080p profile and set the size limits back to unlimited. Your existing films aren't affected either way.
  • Remove Seerr: stop and delete the stack in Dockge, then delete its config folder. Radarr, qBittorrent and Jellyfin keep working on their own.

A few things I learned

  • Put the gate in one place. Seerr is the only thing allowed to send work to Radarr. The scout and the bot both go through it, so there's one setting to check when something looks wrong.
  • Give automation the smallest account that works. The scout can only request. The bot can approve, but only a Discord admin can press its buttons.
  • Verify the hand-off, not the click. An "Approved" status in Seerr didn't mean Radarr had it. Checking for the Radarr ID caught a real fault on day one.
  • Cap the daily list. Five a day is plenty. Without a cap the first run would have filed dozens of requests from two years of releases.

I keep notes on the rest of my home setup in Homelab Intelligence, and the TrueNAS side of this started with my TrueNAS home server build. If you want to reach Seerr from outside the house, my guide to Cloudflare Tunnel for TrueNAS covers that without opening ports. And if you'd rather have someone set up something like this for you, that's what my homelab and network services are for.

Frequently asked questions

Is Jellyseerr still maintained?

No. Jellyseerr and Overseerr merged into a single project called Seerr, and the Jellyseerr Docker image is now tagged as deprecated. Seerr supports Jellyfin, Emby and Plex, and new installs should use the ghcr.io/seerr-team/seerr image.

Why did my approved request in Seerr not download?

Usually because no Radarr server is marked as Default in Seerr's Services settings, so Seerr has nowhere to send the film. Its log says "There is no default Radarr server configured". Tick Default Server, save, then delete and recreate the stuck request, because approved requests can't be retried.

Can I approve Seerr requests from Discord?

Not with Seerr's built-in Discord notifications, because webhooks only send messages and can't read replies or button clicks. You need a small Discord bot that posts pending requests with buttons and calls Seerr's approve or decline API when an admin presses one.

How do I stop Radarr downloading huge remux files?

Remove Remux-1080p from the HD-1080p quality profile and set a maximum size for Bluray-1080p under Settings, Quality. A limit of 100 MB per minute keeps a two hour film at about 12 GB. Do the same for Remux-2160p in the Ultra-HD profile.

Will Radarr rename or move the movies I already have?

No. Radarr only manages films you add to it. Existing folders in your Jellyfin library stay untouched unless you run Library Import in Radarr, so you can turn on renaming for new downloads without risking your current collection.

Comments

Questions and corrections are welcome. I read every comment before it appears, and remove spam and promotional links.