Suggestarr¶
Suggestarr (kubernetes/apps/media/suggestarr) watches what Plex users play, asks an LLM for
similar films and series, and files requests in Seerr. It replaced Recommendarr, archived in #6043
because its upstream had published no image since April 2025 while Suggestarr still ships regular
releases.
None of its settings are in Git: the app keeps them on its PVC and edits them through its own UI, so the HelmRelease sets only the port and log level.
Where the configuration lives¶
The suggestarr PVC is mounted at /app/config. The settings file is
/app/config/config_files/config.yaml, next to the SQLite database requests.db.
config.yaml holds API keys. Read single keys rather than the whole file, for example with a
python3 one-liner run through kubectl -n media exec deploy/suggestarr, and confirm that a
secret is set by its length.
The integration settings are stored twice. The integrations table in requests.db holds the
Seerr, TMDB and LLM settings (plus Jellyfin, OMDb and Trakt when used), and on every load a
non-empty value from that table overrides the same key in config.yaml. At startup the table is
seeded from config.yaml only where a row is missing or invalid, so an edit to one of those keys
in the file alone never takes effect.
Copies of the earlier settings from the 2026-10-12 reconfiguration are kept beside the live file
as config.yaml.bak-20261012 and config.yaml.bak-20261012b.
Changing settings¶
Use the web UI. Its save (POST /api/config/save) writes config.yaml through
api_service.config.config.save_env_vars and then updates the integrations table, which is the
only path that keeps the two in step.
If a change has to be scripted, call the app's own functions inside the pod rather than editing the YAML by hand:
save_env_varsrewrites the whole file from the dict it is given, keeping only keys the app knows and dropping empty values. Start fromload_env_vars()and change only the keys you mean to, or every other setting resets to its default.save_env_varsdoes not touch theintegrationstable. For a Seerr, TMDB or LLM key, also update its row with the database manager'sset_integration.- The server caches the merged settings in process, and a script run through
kubectl execclears only its own copy. Runkubectl -n media rollout restart deploy/suggestarrafterwards.
Wiring¶
| Setting | Value | Why |
|---|---|---|
SELECTED_SERVICE |
plex |
Watch history comes from Plex |
PLEX_API_URL |
http://plex.media.svc.cluster.local:32400 |
In-cluster, so no route or TLS is needed |
SEER_API_URL |
http://seerr.media.svc.cluster.local |
Seerr's Service listens on port 80 |
OPENAI_BASE_URL |
http://litellm.ai.svc.cluster.local:4000/v1 |
LiteLLM's OpenAI-compatible endpoint |
LLM_MODEL |
self-hosted |
LiteLLM falls back to claude, then openrouter/auto |
OPENAI_API_KEY |
the suggestarr LiteLLM virtual key |
Scoped to those three models |
TMDB_API_KEY |
the TMDB key from the kometa 1Password item |
Reuses Kometa's key instead of a second TMDB account |
REQUIRE_REQUEST_APPROVAL |
true |
An LLM picks the titles, so a human approves each one before it reaches Seerr |
CRON_TIMES |
0 0 * * * |
The app default, one run a day |
PLEX_LIBRARIES |
empty | Empty means every library |
SELECTED_USERS |
empty | Empty means every user |
Approval happens in Suggestarr, not Seerr. Each suggestion waits as awaiting_approval in
Suggestarr's own request queue (the pending_requests table) until its owner or an admin
approves it there, so a quiet Seerr does not mean the job is stalled. A job whose delivery mode
is manual or automatic overrides the global setting; the one job here, the daily
recommendation job, uses inherit.
The virtual key is declared in kubernetes/apps/ai/litellm/app/virtualkeys/suggestarr.yaml
(#6041), and its PushSecret mirrors it to the litellm 1Password item as
LITELLM_SUGGESTARR_API_KEY. The app takes it from there through the UI; no ExternalSecret
delivers it.