Service catalogue
Rendered from spec at76d46f3 (2026-10-25) · its source · Edit this page
Status: Accepted · Audience: Operator · Area: F — Extensibility
Purpose
Say what each service is for, in terms of what it does for the operator rather than what it is.
A stack of twenty-three bundled services is opaque. “Prowlarr” and “Bazarr” convey nothing; the operator sees a list of names, cannot tell which matter, and cannot judge whether a failure is serious. When something breaks they don’t know whether they’ve lost subtitles or lost everything.
The catalogue is also the criteria by which anything new is judged. Nineteen services is already a lot, and every addition costs memory, attack surface, update burden, and cognitive load.
Behaviour
Every service is described by its job
| Service | What it does for you | Without it |
|---|---|---|
| Prowlarr | Holds your indexer accounts in one place and shares them with everything else | Every app needs indexers configured separately |
| FlareSolverr | Gets past bot-protection on some indexers | Those indexers return nothing |
| NZBHydra2 | A search box across all your Usenet indexers at once | Search one indexer at a time |
| SABnzbd | Downloads from Usenet | No Usenet downloads |
| qBittorrent | Downloads torrents | No torrent downloads |
| Gluetun | Routes torrent traffic through your VPN and blocks it if the VPN drops | Your home IP is visible to every peer |
| Sonarr | Watches for new episodes and fetches them | Find and download episodes yourself |
| Radarr | Same, for films | Find and download films yourself |
| Lidarr | Same, for music | — |
| Bindery | Same, for books and audiobooks | — |
| Bazarr | Finds and downloads subtitles | No automatic subtitles |
| Jellyfin | Plays your library on TVs, phones and browsers | Files on disk, no way to watch them |
| Seerr | Where the household asks for things | Requests come to you in person |
| Calibre-Web-Automated | Reading and organising your ebook library | — |
| Audiobookshelf | Listening to audiobooks, with progress synced | — |
| Recyclarr | Keeps quality settings in line with community guidance | Tune quality profiles by hand |
| Unpackerr | Extracts archived releases so they can be imported | Some downloads never import |
| Homepage | One page linking everything, with live status | Remember a dozen URLs and ports |
| Caddy (optional) | Friendly hostnames instead of ports | Use localhost:8989 and friends |
The “without it” column is what makes this useful: it converts an inventory into a judgement about severity.
Criticality is stated
| Level | Meaning | Services |
|---|---|---|
| Critical | Failure has consequences beyond the stack | Gluetun |
| Core | Stack cannot do its job | Prowlarr, download clients, the *arr for the media type in use |
| Important | Significant capability lost | Jellyfin, Seerr |
| Enhancing | Quality of life | Bazarr, Recyclarr, Unpackerr, Homepage, FlareSolverr, NZBHydra2 |
| Optional | Off unless asked for | Caddy |
Gluetun is alone at critical, and for the reason stated throughout: it is the only service whose failure can affect the operator outside their own machine.
Provenance is visible
Each service’s licence, upstream project, and pinned version — so the operator can verify the open-source claim rather than take it on faith.
Every bundled service lemonfiber does not build is OSI-licensed: GPL-3.0 (Prowlarr, Sonarr, Radarr, Lidarr, Bazarr, Calibre-Web-Automated, Homepage), GPL-2.0 (Jellyfin, SABnzbd, qBittorrent), MIT (Seerr, Gluetun, FlareSolverr, Recyclarr, Unpackerr, Bindery, Audiobookshelf), Apache-2.0 (NZBHydra2, Caddy).
The services whose images lemonfiber builds from its own code — the request gate
and the decline service
(ADR-0033)
— carry lemonfiber’s own licence, Hippocratic-3.0, as the rest of its code
does (licence rationale). Their
source is public, so their licence is verified the same way, and it is
source-available rather than open source.
Inclusion criteria are explicit
A service enters the stack only if it is open source under an OSI-approved
licence — or, where lemonfiber builds its image from its own code, carries
lemonfiber’s own licence (F2-R5) — publishes native linux/arm64 and
linux/amd64 images, is actively maintained, does something no included service
already does, and works without a paid tier.
Stating the criteria makes “why isn’t X included?” answerable, and makes additions a judgement against a standard rather than a matter of taste.
Maintenance signals are tracked, not discovered late
Each bundled service has the date of its last upstream release recorded in the bundle’s
last_release, beside its pin, by the reviewers who move the pin, and refreshed whenever
they move it. A service going quiet is not itself a problem — a mature application may
simply not need frequent releases — but it is a signal worth holding, because the
alternative is discovering an abandoned dependency only when it breaks.
The recorded date is the latest release upstream has published, not the date the pinned version shipped. Those diverge precisely when the signal matters: a project that released six times since your pin is alive, and one that has released nothing since is the case worth noticing. A date ahead of upstream’s actual latest release is not a stale record but a wrong one, and fails validation.
The table below carries only services whose signal needs a judgement recorded against it; the dates themselves are bundle data, so they version with the stack rather than with this document.
| Service | Signal |
|---|---|
| Lidarr | Slowest-moving in the stack; roughly eight months between releases as of mid-2026. Not archived, still functional, and no viable successor exists — see exclusions. Retained, watched. |
Notable exclusions are recorded
| Not included | Why |
|---|---|
| Plex | Not open source |
| Readarr | Discontinued upstream in 2025; Bindery replaces it |
| Melodarr | Presents itself as an actively maintained Lidarr successor. It is a fork with two days of commits, no releases, no published image, and no activity since April 2026. Investigated and rejected — a dead fork is worse than a slow-moving working project. |
| Beets, Headphones | Beets is a tagger and organiser, not acquisition automation; Headphones is effectively dead. Neither replaces Lidarr. |
| Autobrr, cross-seed | Substantial sub-projects; deferred |
| Tdarr | Transcode automation; weak fit without hardware acceleration on two of three platforms |
| Authelia, Authentik | Admin surfaces are loopback-only, so SSO solves a problem the stack doesn’t have |
| Watchtower | Automatic updates of state-migrating services is the failure mode E1 exists to prevent |
Edge cases
| Situation | Behaviour |
|---|---|
| Operator asks what a failing service does | Description available inline at the point of failure, not only in documentation. |
| Service description drifts from reality | The catalogue lives in the manifests that declare the services, so they version together. |
| Operator adds an unknown service | Show it with an unknown description rather than hiding it. |
| Upstream project is abandoned | Record it; treat replacement as a spec change with an ADR. |
| Licence changes upstream | Detect at pin-bump time; a non-OSI licence disqualifies the service. |
| Service dropped from the stack | Record why and what replaced it. |
Acceptance criteria
| ID | Requirement |
|---|---|
| F2-R1 | Every service MUST carry a plain-language description of what it does for the operator. |
| F2-R2 | Every service MUST state the consequence of its absence. |
| F2-R3 | Every service MUST carry a criticality level. |
| F2-R4 | Every service MUST record its licence, upstream project, and pinned version. |
| F2-R5 | Every bundled service MUST be under an OSI-approved licence, except a service whose image lemonfiber builds from its own code, which MUST carry lemonfiber’s own licence (Hippocratic-3.0); an upstream’s image lemonfiber rebuilds MUST keep its upstream’s licence. |
| F2-R6 | Every bundled service MUST publish native linux/arm64 and linux/amd64 images. |
| F2-R7 | Inclusion criteria MUST be stated explicitly. |
| F2-R8 | Notable exclusions MUST be recorded with reasons. |
| F2-R9 | Service descriptions MUST be available inline where a service is referenced, not only in documentation. |
| F2-R10 | The catalogue MUST be versioned with the manifests that declare its services: a bundled service’s first-party plugin manifest, pinned by the bundle, or a stack manifest. |
| F2-R11 | An unknown service MUST be displayed with an unknown description rather than hidden. |
| F2-R12 | An upstream licence change away from OSI approval MUST disqualify the service at pin-bump time. |
| F2-R13 | Removal of a service MUST record the reason and any replacement. |
| F2-R14 | Each bundled service MUST have its last upstream release date recorded in the bundle beside its pin, kept by the reviewers who move the pin and refreshed whenever they move it; a stack manifest’s service MUST record its own. |
| F2-R15 | A candidate service’s maintenance status MUST be established from its commit and release history, never from its own self-description. |
Related
- B1 Forms — how services group into profiles
- F1 Customisation — adding services
- G2 Plain-language layer — how descriptions are written
- 90-appendix licence rationale