The two rules
Almost every configuration problem in this stack comes back to one of these. Learn them now and most of what follows is obvious.
Inside a container, localhost means that container. Sonarr looking at 127.0.0.1:8080 is looking inside itself. Use the service name from your Compose file: jellyfin, sonarr, radarr.
network_mode: service:gluetun it has no network identity of its own — it lives inside Gluetun's network. So other apps must connect to gluetun, not qbittorrent. Same for Jackett when it is behind the VPN.
If qBittorrent saves to /data/downloads/x.mkv, Sonarr must see that exact path. When they disagree, downloads finish and then never import. With the shared storage layout every app mounts one /data and this is free.
| Connecting to | Host | Port |
|---|---|---|
| qBittorrent (behind VPN) | gluetun | 8080 |
| qBittorrent (no VPN) | qbittorrent | 8080 |
| Jackett (behind VPN) | gluetun | 9117 |
| Jackett (no VPN) | jackett | 9117 |
| Sonarr | sonarr | 8989 |
| Radarr | radarr | 7878 |
| Lidarr | lidarr | 8686 |
| Jellyfin | jellyfin | 8096 |
What order to do this in
Each app needs something from the one before it — usually an API key. Going in this order means never doubling back.
- qBittorrent — set its password and save paths. Nothing else works until this does.
- Jackett — add indexers, collect the API key.
- Sonarr, Radarr, Lidarr — point each at qBittorrent and Jackett, set root folders.
- Bazarr — needs Sonarr's and Radarr's API keys.
- Jellyfin — create libraries over the folders the *arr apps now fill.
- Jellyseerr — needs Jellyfin, then Sonarr and Radarr.
- Uptime Kuma — monitor everything above, then set up alerts.
- Pocket ID — last, once the apps it protects are working.
qBittorrent
The download client. Configure this first — Sonarr and Radarr cannot be finished without it.
First runDo this firstFind the temporary password and change it
Recent versions no longer ship a fixed default password. One is generated on first start and written to the log:
docker compose logs qbittorrent | grep -i password
In Arcane, open the qBittorrent container and read its logs — the line is near the top.
- Open
http://your-server:8080and sign in asadminwith that password. - Go to Tools → Options → Web UI.
- Set a real username and password under Authentication.
- Tick Bypass authentication for clients on localhost only if you understand it. Leave it off otherwise.
Save pathsWhere downloads land, and why it matters
Under Tools → Options → Downloads:
- Default Save Path
/data/downloads/complete- Keep incomplete torrents in
- tick, then
/data/downloads/incomplete - Copy .torrent files
- off — the *arr apps manage this
- Pre-allocate disk space
- on, if you have room; avoids fragmentation
These are paths inside the container. With the shared layout, /data is your DATA_ROOT, so /data/downloads is really /srv/data/downloads on the host.
CategoriesSet up by the *arr appsKeeps TV, films and music apart
Categories put each app's downloads in their own subfolder and let each app see only its own work. You do not need to create them by hand — when you connect Sonarr, it creates tv-sonarr for you, Radarr creates radarr, Lidarr creates lidarr.
To check afterwards, look at the left sidebar in qBittorrent. If a category is missing, the connection from that app is not working.
Seeding and cleanup
Under Tools → Options → BitTorrent you can set a share ratio and what happens when it is reached. Pausing rather than deleting is the safe default — hardlinked files are safe to remove, but if you are not using hardlinks, deleting the torrent deletes the file your library points at.
API keys and permissionsFor the generator's deploy script
The generator can produce a deploy-to-arcane.sh that creates and starts your project through Arcane's API. It needs a key, and that key should be scoped.
Creating the key
- In Arcane, go to Settings → API Keys and create one.
- Grant only these three permissions:
- environments:read
- so the script can find which environment to deploy into
- projects:create
- to create the project
- projects:deploy
- to start it
- Copy the key. It is shown once.
If the names differ on your instance
Permissions follow a resource:action pattern, and the exact set depends on your Arcane version. Ask your own instance rather than guessing:
bash deploy-to-arcane.sh --permissions
That lists every permission your Arcane offers. If a call is refused, the script names the specific permission that was missing rather than failing with a bare error.
Running it
bash deploy-to-arcane.sh
It prompts for the URL and the key. The key is typed with the input hidden and held only in that shell process — never exported, never written to disk, and never passed as an argument, since arguments are visible to anyone running ps.
/proc, and in the environment of every child process. Typing it at a prompt avoids all three.Jackett
Turns many different tracker APIs into one format the *arr apps understand. It has no accounts and no library — it is plumbing.
Adding indexersAnd collecting what Sonarr needs
- Open
http://your-server:9117. - Press Add Indexer, search, and add the ones you use. Public indexers need nothing; private ones need your account details.
- Press Test on each. A failure here will also fail in Sonarr, so fix it now.
- For each working indexer, press Copy Torznab Feed and keep the URL.
- Copy the API Key from the top right of the page. It is the same for every indexer.
http://gluetun:9117/api/v2.0/indexers/<indexer-id>/results/torznab/ when Jackett is behind the VPN. Jackett's copy button gives you a localhost version — swap the host for gluetun (or jackett if you are not using a VPN).Sonarr
TV automation, and the template for Radarr and Lidarr — they are the same app with different libraries. Do this one carefully and the other two take two minutes each.
1 · Root folderStart hereWhere finished episodes go
Settings → Media Management, scroll to Root Folders, press Add Root Folder:
- Path
/data/media/tv(shared layout) or/tv(split layout)
On the same page, turn on Rename Episodes. Sonarr will then name files the way Jellyfin expects, which fixes most artwork problems before they happen.
ls /data.2 · Download clientConnecting to qBittorrent
Settings → Download Clients → + → qBittorrent:
- Name
- qBittorrent
- Host
gluetun— notqbittorrent, and neverlocalhost- Port
8080- Username / Password
- what you set in qBittorrent
- Category
tv-sonarr- Use SSL
- off
Press Test. A green tick means the connection works. Then Save.
ping -c2 gluetun. If that works, the problem is the port or the password instead.3 · IndexersPointing at Jackett
Settings → Indexers → + → Torznab → Custom. Do this once per indexer you added in Jackett:
- Name
- whatever the indexer is called
- URL
- the Torznab feed, with the host changed to
gluetun - API Key
- Jackett's API key
- Categories
- leave default unless you know otherwise
Press Test, then Save.
4 · Quality profileDeciding what "good enough" means
Settings → Profiles. The defaults work, but two adjustments save trouble:
- Cap the quality. A 1080p profile is the sensible default for most hardware. 4K files are enormous and will force Jellyfin to transcode on almost any client.
- Set a size limit. Under the profile, a maximum size per episode stops a single release filling your disk.
5 · Your API keyNeeded by Bazarr and Jellyseerr
Settings → General → Security → API Key. Copy it — Bazarr and Jellyseerr both need it.
If downloads finish but never import
Sonarr and qBittorrent disagree about paths. Compare what each one sees:
docker compose exec qbittorrent ls /data/downloads docker compose exec sonarr ls /data/downloads
Different listings mean different mounts. The proper fix is matching volumes; the patch is Settings → Download Clients → Remote Path Mappings, telling Sonarr that the client's path is really its own.
Radarr
Identical to Sonarr, with three values changed.
- Root folder
/data/media/movies- Download category
radarr- Rename setting
- Rename Movies, on
Everything else — download client host gluetun port 8080, Torznab indexers from Jackett, API key under Settings → General — works exactly as described for Sonarr.
Lidarr
Same again for music, with the usual caveat that music metadata is messier than film and TV.
- Root folder
/data/media/music- Download category
lidarr- Metadata profile
- Standard, unless you want every single and remix
Download client and indexers are configured exactly as for Sonarr. Expect more manual matching — Lidarr relies on MusicBrainz, so if an artist is wrong there it will be wrong here.
http://lidarr:8686) and API key — see Kima below.Bazarr
Fetches subtitles for the libraries Sonarr and Radarr already manage. It needs their API keys, so do this after both are working.
Connecting to Sonarr and RadarrTwo forms, same shape
Settings → Sonarr, toggle it on:
- Address
sonarr- Port
8989- API Key
- from Sonarr's Settings → General
- SSL
- off
Then Settings → Radarr with radarr and port 7878. Press Test on each, then save and restart Bazarr when it asks.
Languages and providersWhat to fetch, and from where
- Settings → Languages — create a profile, add the languages you want, and set it as the default for series and movies.
- Settings → Providers — add subtitle sources. Most need a free account; create one and enter the details.
- Settings → Subtitles — turn on Use embedded subtitles so Bazarr does not fetch what your files already contain.
Jellyfin
Where everything above ends up. Libraries are the main thing to get right, and the mistake is always the same one.
LibrariesThe important bitUse container paths, and split by type
Dashboard → Libraries → Add Media Library:
- Content type
- Movies — make a separate library for Shows
- Display name
- Films
- Folder
/media/movies— the path inside the container
Repeat with content type Shows and folder /media/tv, and Music for /media/music.
If a library comes up empty
The mount is wrong, not Jellyfin. Check what it can actually see:
docker compose exec jellyfin ls /media
Nothing listed means the volume path in your Compose file does not match your real folder.
UsersGiving the household accounts
Dashboard → Users → +. For each person:
- Set which libraries they can see under Library Access.
- Turn off Allow media playback that requires transcoding for casual users if your server is CPU-limited — the difference between one device quietly overloading the machine and it politely refusing.
- Leave administrative permissions off unless they need them.
TranscodingOnly if you need it
Dashboard → Playback → Transcoding. On native Linux with an Intel chip, set hardware acceleration to Intel QuickSync and enable the codecs your hardware supports. This requires the device mapping in your Compose file:
devices: - /dev/dri:/dev/dri
Jellyseerr
The request front end. It signs people in against Jellyfin and hands approved requests to Sonarr and Radarr, so it needs all three configured first.
Setup wizardRuns onceJellyfin, then the *arr apps
- Open
http://your-server:5055. Choose Sign in with Jellyfin. - Jellyfin URL:
http://jellyfin:8096. Sign in with your Jellyfin admin account — this becomes the Jellyseerr owner. - It offers to sync your Jellyfin libraries. Tick the ones people should be able to request from, and run the scan.
- Next it asks for Radarr and Sonarr. Add both.
Adding Radarr
- Hostname
radarr- Port
7878- API Key
- from Radarr's Settings → General
- Quality Profile
- the profile you set up in Radarr
- Root Folder
/data/media/movies- Default server
- on
Sonarr is the same with sonarr, port 8989, and root folder /data/media/tv. Sonarr also asks for a Language Profile — pick your default.
Users and quotasLetting the household in without losing your disk
- Settings → Users → Import Users from Jellyfin. Everyone with a Jellyfin account appears.
- Set Global Movie Request Limit and Global Series Request Limit — something like 5 per week is sane.
- Decide on auto-approval. Leaving it off means requests wait for you; turning it on for trusted users saves you being a bottleneck.
Immich
Independent of the media chain. The main setup is the mobile app, since phone backup is the point.
First run and mobile backupAdmin account, then your phone
- Open
http://your-server:2283and create the admin account. The first account is the administrator. - Administration → Settings → Storage Template — turn it on if you want files organised by date on disk rather than by upload id. Decide this before uploading much; changing it later means moving everything.
- Install the Immich app on your phone, and enter the server URL. On the same network that is
http://your-server:2283; from outside you will need remote access first. - In the app, Backup → choose which albums to back up → enable background backup.
Kima
Music streaming over the library Lidarr manages, with its own apps via the Subsonic API.
Setup and Lidarr linkLibrary, then automation
- Open
http://your-server:3030and create your account. - Point it at your music. Inside the container that is
/music, which maps to your media folder'smusicdirectory. - Let it scan. Audio analysis is CPU-heavy and takes a while on a large library.
- To connect Lidarr, give Kima the URL
http://lidarr:8686and Lidarr's API key from Settings → General.
Native apps
Kima implements the OpenSubsonic API, so apps like Symfonium, Amperfy and DSub can connect to it directly. Point them at your Kima URL with your Kima username and password.
Archiving apps
ArchiveBoxSaving web pages
Open http://your-server:8000 and sign in with admin and the generated password from your .env.
Add URLs through Add, or import bookmarks and RSS feeds. Each snapshot keeps several formats at once — HTML, PDF, screenshot and more — so storage grows faster than people expect.
PUBLIC_INDEX, PUBLIC_SNAPSHOTS, PUBLIC_ADD_VIEW). Turn those on only deliberately.Tube ArchivistArchiving YouTube channels
Open http://your-server:8001 and sign in with admin and the TA_PASSWORD from your .env.
- Settings → Application — set your download quality and format.
- Subscriptions — add channel URLs.
- Downloads — run a scan, then start the download queue.
vm.max_map_count being too low on the host. On ARM machines its Elasticsearch image has limited support, which is the one module likely to disappoint on a Raspberry Pi.Uptime Kuma
Watches everything else and tells you when it stops. Worth setting up early — it is the app that tells you when the others need attention.
HTTP monitorsStart hereThe most useful check, and it needs no permissions
Open http://your-server:3001, create your account, then Add New Monitor:
- Monitor Type
- HTTP(s)
- Friendly Name
- Jellyfin
- URL
http://jellyfin:8096— the container name, not localhost- Heartbeat Interval
- 60 seconds is plenty
- Retries
- 2 or 3, so a brief blip does not page you
Repeat for each service you care about:
| Service | URL |
|---|---|
| Jellyfin | http://jellyfin:8096 |
| Jellyseerr | http://jellyseerr:5055 |
| Sonarr | http://sonarr:8989 |
| Radarr | http://radarr:7878 |
| Immich | http://immich-server:2283 |
| qBittorrent | http://gluetun:8080 |
localhost means Uptime Kuma itself. Using container names also means you are testing the internal path rather than your router, so a monitor failing tells you something real.Docker container monitorsNeeds the socket mounted
An HTTP monitor tells you the app is answering. A container monitor tells you the container is running. They fail in different ways, so both are useful.
First check your Compose file has the socket mounted — in the generated stack this line is commented out by default:
volumes: - /var/run/docker.sock:/var/run/docker.sock:ro
Then in Uptime Kuma, Profile → Settings → Docker Hosts → Add Docker Host:
- Friendly Name
- Local
- Connection Type
- Socket
- Docker Daemon
/var/run/docker.sock
Save, then Add New Monitor with type Docker Container, container name jellyfin, and the Docker host you just made.
Status pageOptional, and safe to share
Status Pages → New Status Page. Add the monitors you want visible, and Kuma gives you a clean public page.
This is the one part of Uptime Kuma that is reasonable to expose publicly — it shows only up or down, not your admin interface. If your household keeps asking whether the server is down, this answers it for them.
Discord alerts
The quickest notification to set up, and the one most people want.
- In Discord, open the channel you want alerts in. You need Manage Webhooks permission, so your own server is easiest.
- Edit Channel → Integrations → Webhooks → New Webhook.
- Give it a name — Server alerts — and optionally an avatar. Press Copy Webhook URL.
- In Uptime Kuma, edit any monitor and press Setup Notification.
- Notification Type
- Discord
- Friendly Name
- Discord
- Discord Webhook URL
- paste it
- Bot Display Name
- optional
- Default enabled
- tick, so new monitors use it automatically
- Apply on all existing monitors
- tick, to cover what you already made
Press Test. A message should land in the channel within a second or two. If it does not, the webhook URL is wrong — nothing else in the chain produces that result.
Telegram alerts
A little more setup than Discord, but it reaches your phone properly and does not need a Discord account.
- In Telegram, search for @BotFather and start a chat.
- Send
/newbot. It asks for a display name, then a username ending inbot. - BotFather replies with a token — a long string like
123456789:AAG.... That token is a password; treat it like one. - Now start a chat with your new bot and send it any message. A bot cannot message you first, so without this step nothing will arrive.
- In Uptime Kuma, Setup Notification → Telegram, paste the bot token, then press Auto Get beside the Chat ID field. It reads the message you just sent and fills the ID in.
- Notification Type
- Telegram
- Bot Token
- from BotFather
- Chat ID
- press Auto Get after messaging your bot
- Send silently
- optional — notifies without a sound
- Default enabled
- tick
Press Test. If Auto Get finds nothing, you have not messaged the bot yet — that is the step everyone misses.
Cloudflare Tunnel
Reaches your services from anywhere without opening a single port. An outbound connection from your server to Cloudflare does the work, which also means it works behind CGNAT where port forwarding is impossible.
The advice you will find everywhere is that streaming media through a tunnel violates Section 2.8 of Cloudflare's terms. That section was removed in 2023 — so that specific claim is out of date.
What replaced it is narrower but still relevant: the content restriction moved into Cloudflare's CDN-specific terms, and their own announcement says customers may serve video and large files through the CDN so long as that content is hosted by a Cloudflare service such as Stream, Images or R2. Video hosted on your own server is not.
So the honest position is that it is neither clearly prohibited nor clearly allowed. Plenty of people run Jellyfin through a tunnel without incident; others report throttling or a blocked subdomain. If your access matters, read Cloudflare's current terms yourself rather than trusting any guide, including this one.
- Cloudflare terminates TLS. Traffic is encrypted to Cloudflare, decrypted there, then re-encrypted to your server. They can see it. That is how the protection works, but it is not end-to-end.
- The free plan caps requests at 100 MB. This quietly breaks larger Immich photo and video uploads through the tunnel — the app will simply fail on big files.
Lightweight, text-based interfaces: Jellyseerr for requests, a status page, dashboards. Small payloads, no bandwidth concerns, no terms ambiguity. For Jellyfin and Immich, Tailscale avoids every one of the issues above — nothing is public at all.
Creating the tunnelStart hereAll of this happens on Cloudflare's side
You need a domain whose DNS is managed by Cloudflare. The free plan is enough.
- Go to the Cloudflare Zero Trust dashboard.
- Networks → Tunnels → Create a tunnel, and choose Cloudflared as the type.
- Name it —
home-serveris fine — and save. - Cloudflare shows you install commands for various platforms. You do not need them. You only want the token — the long string beginning
eyJinside the command it displays. - Paste that token into the generator's Connection step, or into
CLOUDFLARE_TUNNEL_TOKENin your.env.
.gitignore already excludes .env.Starting itNo ports, no certificates, no router changes
docker compose up -d cloudflared docker compose logs -f cloudflared
You are looking for Registered tunnel connection, usually four of them to different Cloudflare locations. The tunnel then shows as Healthy in the dashboard.
Nothing was opened on your router, and no certificate was issued on your side — Cloudflare handles HTTPS at their edge.
Routing servicesDone in the dashboard, not in your files
This is the part that surprises people: your Compose file contains no routing at all. Which hostname reaches which service is configured entirely in Cloudflare.
In the tunnel's Public Hostname tab, add an entry per service:
- Subdomain
requests- Domain
- your domain
- Service type
- HTTP
- URL
jellyseerr:5055
Use the container name, not localhost. cloudflared runs in a container on the same Docker network, so localhost would mean cloudflared itself — the same rule as everywhere else in this stack.
| Service | Tunnel URL | Sensible? |
|---|---|---|
| Jellyseerr | jellyseerr:5055 | Good fit |
| Uptime Kuma status | uptime-kuma:3001 | Good fit |
| Jellyfin | jellyfin:8096 | See the terms note above |
| Immich | immich-server:2283 | 100 MB upload cap |
| Arcane, qBittorrent, *arr apps | — | Never |
DNS records are created for you automatically — there is nothing to add by hand.
Adding a login in frontCloudflare Access, optional
A tunnel publishes a service to the whole internet. Anything without solid authentication of its own should have a login in front of it.
Under Access → Applications, add a self-hosted application for the hostname, then a policy — allow specific email addresses, or a whole domain. Cloudflare then requires a one-time code before the request ever reaches your server.
Pocket ID
One passkey login across the apps that support it. This section is long because the honest answer is more complicated than "set up SSO and you are done" — the coverage is real but partial, and it is better to know that before you start.
| App | Support | Reality |
|---|---|---|
| Immich | Native | Works fully, mobile app included |
| Arcane | Native | Supported directly |
| Jellyfin | Plugin | Web browser or Quick Connect only |
| Sonarr, Radarr, Lidarr | None | Their own single login |
| Bazarr, qBittorrent | None | Their own login |
| Uptime Kuma | None | Its own accounts |
| ArchiveBox, Tube Archivist | None | Their own accounts |
Realistically that is one login for Immich, Arcane and Jellyfin in a browser. Genuinely useful if those are the apps other people touch. Not stack-wide SSO.
https://id.example.com resolves with a valid certificate.First runStart hereAdmin account and your first passkey
- Visit
https://id.example.com. On first run it presents a setup wizard. - Create the admin account and register a passkey when prompted — your phone, laptop, or a hardware key.
- Register a second passkey on a different device immediately.
If you are locked out anyway
Pocket ID's CLI can issue a one-time login link:
docker compose exec pocket-id \ /app/pocket-id one-time-access-token admin
That prints a URL valid once, for a short window. Open it and register a new passkey.
Adding an OIDC clientThe same five steps for every app
Every app you connect needs a client entry in Pocket ID. The process never changes:
- Administration → OIDC Clients → Add OIDC Client.
- Name it after the app.
- Enter that app's callback URL — each app documents its own, and the ones you need are below.
- Save. Pocket ID shows a Client ID and a Client Secret. The secret is shown once — copy it now.
- Paste both into the app, along with the issuer URL.
Most apps only need the issuer and will discover everything else themselves:
https://id.example.com/.well-known/openid-configuration
ImmichBest supportedFull SSO including the mobile app
The one where SSO is most worth having, since Immich is the app family members use daily.
In Pocket ID
Create a client named Immich with these callback URLs — all three:
https://photos.example.com/auth/login
https://photos.example.com/user-settings
app.immich:///oauth-callback # the mobile app
In Immich
Administration → Settings → OAuth:
- Issuer URL
https://id.example.com/.well-known/openid-configuration- Client ID
- from Pocket ID
- Client Secret
- from Pocket ID
- Scope
openid email profile- Button Text
- Sign in with Pocket ID
- Auto Register
- on — creates accounts on first login
app.immich:///oauth-callback registered, SSO works in the browser and fails on phones, which is a confusing way to find out.ArcaneNative OIDC support
Arcane supports OIDC directly. Create a client in Pocket ID with Arcane's callback URL, then enter the issuer URL, client ID and secret in Arcane's authentication settings.
JellyfinRead before startingCommunity plugin, with a real limitation
Jellyfin has no native OpenID Connect support. There is a community SSO plugin, and it works — but it carries a limitation that matters enormously for a media server.
Native OIDC is being built upstream, but the discussion points at Jellyfin 13.0 at the earliest, and it will not reach current servers. Until then this is the situation.
Which plugin
The original 9p4/jellyfin-plugin-sso was archived in May 2026 and is unmaintained. The actively maintained fork keeps the same plugin ID, so it is an in-place upgrade if you already had the old one — and unlike the original it has a proper admin configuration UI rather than API-only setup.
- Repository URL
https://raw.githubusercontent.com/K0lin/jellyfin-plugin-sso/manifest-release/manifest.json- Requires
- Jellyfin 10.8+, 10.11.11 or newer recommended
Installing
- Administration → Plugins → Repositories → Add, and paste the repository URL above.
- Administration → Plugins → Catalog, find SSO Authentication, install it.
- Restart Jellyfin.
- In Pocket ID, create a client whose callback URL follows the plugin's pattern. The provider name at the end is yours to choose, and must match on both sides:
https://jellyfin.example.com/sso/OID/redirect/pocketid - In Plugins → SSO Authentication → Settings, add an OIDC provider with your issuer URL, client ID and secret. Enable it, and set folder access.
- Restart Jellyfin again — configuration changes do not take effect until you do.
Adding the login button
The button is not added automatically. Edit config/web/config.json:
{
"customLinks": [
{ "name": "Sign in with SSO",
"url": "/sso/OID/start/pocketid",
"icon": "lock" }
]
}
Everything elseWhat to do about apps with no OIDC
Sonarr, Radarr, Lidarr, Bazarr, qBittorrent, Uptime Kuma, ArchiveBox and Tube Archivist have no OpenID Connect support. You have three honest options.
Keep them private — recommended
Do not publish them. Reach them over Tailscale or your LAN, and let their own login be a second layer rather than the only one. For administrative tools you touch occasionally, this is the right engineering answer for a home setup.
Forward authentication
A proxy component checks authentication before passing a request on, putting a login in front of apps that cannot do it themselves.
Just use their own logins
A strong unique password on each, in a password manager. Unglamorous, and completely fine.
Users and groupsAdding people, and removing them properly
Adding someone
- In Pocket ID, Users → Add User.
- Send them a one-time link so they register their own passkey on their own device. You never handle a credential for them.
- Create groups if you want them —
media-usersandmedia-adminsis plenty for a household. Apps that read group claims can map them to their own permissions.
Removing someone
Because accounts live in several systems, offboarding is a checklist rather than one button:
- Delete or disable them in Pocket ID — stops SSO logins immediately.
- Delete their Jellyfin user separately.
- Remove them from Jellyseerr so pending requests do not linger.
- Decide what happens to their Immich library before deleting that account, since it removes their photos.
- Revoke active Jellyfin sessions, or a signed-in device keeps playing.
Bring the log line. The troubleshooting page starts with the four commands that identify most problems, and has searchable answers for the specific ones — including the connection failures this page is designed to prevent.