-
Notifications
You must be signed in to change notification settings - Fork 0
Wiring
The reason Keelarr exists. Running the containers is easy; connecting them is the work.
| Connection | From → to |
|---|---|
| Download client | Radarr, Sonarr, Lidarr → SABnzbd or qBittorrent, each with its own category |
| Applications | Prowlarr → Radarr, Sonarr, Lidarr, so indexers sync into them |
| Indexer proxy | Prowlarr → FlareSolverr |
| Subtitles | Bazarr → Radarr, Sonarr |
| Library folders | A root folder in each Arr, created on the host path behind the container path |

This is the part that is easy to get wrong by hand.
"localhost" means something different inside each container. An address that works from your browser may not work from Prowlarr, and an address that works from Prowlarr may not work from Radarr. So Keelarr resolves each connection from the source app's position on the network:
| Topology | How the address is resolved |
|---|---|
| Shared user-defined network | By container name — Docker's DNS resolves it |
| Default bridge | By IP, because the default bridge carries no DNS |
| Host networking | Via the host address |
| macvlan | By the container's own address on that network |
| Published port, remapped | By the host port, not the container port |
When two apps genuinely cannot reach each other — different networks, nothing published — the link is reported as blocked, with the reason, rather than given an address that will silently time out.
Every possible connection is reconciled into one of four states:
| State | Meaning | Written? |
|---|---|---|
correct |
Something already there matches what we would configure | No — nothing to do |
drift |
Exactly one comparable entry exists, pointing somewhere else | No |
ambiguous |
Several comparable entries exist and none match | No |
absent |
Nothing comparable exists | Yes |
Drift is never overwritten. A download client pointing somewhere unexpected is usually a deliberate choice, and silently replacing it would be worse than leaving it. It is reported so you can decide.
Ambiguous is never guessed at. Two candidates and no clear match is not something to resolve by picking one.
Every write follows the same sequence:
- Read the app's own schema for that integration
- Build the payload from that schema, so fields Keelarr does not name keep the app's defaults
- Submit it to the app's own test endpoint
- Only if the app accepts it, write it
A refusal is reported in the app's own words. That matters because a write that
half-happens produces a bare 400 naming a field rather than the actual problem.
After writing, Keelarr runs each app's testall endpoint so the final verdict is
the app's opinion, not Keelarr's.
A wiring run that changes nothing is a success, not a failure. It runs automatically after every install, and reporting a red failure over an install that worked is a lie.
But it only says "every connection is already configured" when every link was actually confirmed correct. If two links were merely unreachable, it says that instead — "we wrote nothing" and "everything is correct" are different facts.
Two real examples, both invisible to unit tests and both found on live hosts:
A fresh SABnzbd whitelists only the hostname it sees itself as — inside a
container, that is the container ID. It answers 403 to every other name,
including its own container name, which is exactly what everything else
addresses it by.
http://sabnzbd:8080/api?mode=version → 403 Forbidden
http://172.25.0.9:8080/api?mode=version → {"version":"5.1.0"}
Keelarr appends the hostname through SABnzbd's own API, addressed by IP — the
hostname cannot carry its own fix — and keeps every entry already present,
because SABnzbd's set_config replaces the list rather than appending to it.
An Arr refuses a download client with no category, and its error names a field rather than the real problem. Keelarr checks the category exists and creates it before attempting the write.
A stack can be perfectly connected and still not do anything, because it needs something only you have. The check separates these:
- Connections — what Keelarr manages, and their state
- Needs you — an indexer, a Usenet account, a Plex token
Prowlarr with no indexers is reported explicitly: nothing in the stack can find releases until at least one exists. That is a finished result, not a half-done one, and the verdict says so.
Removing an app does not remove references to it from apps that were pointed at it. Keelarr detects these — Prowlarr's proxy for a deleted FlareSolverr, its sync to a Lidarr that no longer exists — and reports them. On a live NAS this found an orphaned Lidarr reference nobody knew about.
Wiring runs automatically after every install and deploy. To run it by hand, use Check Wiring in the toolbar to see the current state, then apply.
The check is strictly read-only, including the testall calls, which exercise
each app's existing configuration rather than anything Keelarr proposes.
Getting started
How it works
Reference