Omahub
← All plugins
K

NZBGet Queue

by ky

Live NZBGet download speed in the bar, with the queue, pause/resume and a speed limit in the popup.

Security review

Review recommended · 1 finding

Deterministic scan — not a security guarantee

Low
Risk level
Low
Analyzed commit
70df3ec
Scanned
1 week ago

Flagged patterns appear only in documentation files (README / docs) — descriptive examples, not executable code.

  • Docs package_manager README.md:120

    System-wide Python package installation (not --user).

    pip install`. |

Automated analysis only — not a security guarantee.

AI advisory review

No obvious issues detected

Language-model assessment · ~deepseek/deepseek-v4-flash-latest — advisory only

Low
AI risk level
Low
Recommendation
install
Model
~deepseek/deepseek-v4-flash-latest
Analyzed commit
70df3ec
Reviewed
1 week ago

The plugin is a straightforward NZBGet queue widget with careful security practices: it never sends credentials over plain HTTP to public URLs, refuses redirects, caps response sizes, and writes its state file safely with O_NOFOLLOW and atomic operations. The deterministic scan flagged a 'pip install' in the README, but that line actually states 'nothing to pip install' — it is documentation, not an installation command, so it is a false positive.

How this check works

This review combines the deterministic scan (the rule-based results above) with an independent look at the plugin's code by a language model. The model reads a trimmed sample of the repository's files, the manifest, and the README, then gives a plain-language risk level and a recommendation: install (no notable danger), review (look closer first), or avoid (clearly dangerous).

It runs on the same analyzed commit as the deterministic scan and is strictly advisory — it is not a security guarantee and never blocks a plugin by itself. A human moderator still reviews plugins before they are listed.

AI advisory only — automated analysis, not a security guarantee.

Install
$ omarchy plugin add https://github.com/Kyrunner/omarchy-nzbget-queue --enable
System #bar #quickshell #system

NZBGet Queue

Omarchy bar widget showing NZBGet's live download speed, with the queue, pause/resume and a speed limit in the popup.

Hidden entirely while nothing is downloading.

NZBGet Queue in the Omarchy bar

Install

omarchy plugin add https://github.com/Kyrunner/omarchy-nzbget-queue.git --enable

Setup

Create ~/.config/omarchy-nzbget/config.json:

{
  "url": "http://192.168.1.10:6789",
  "public_url": "",
  "user": "nzbget-control-username",
  "password": "nzbget-control-password"
}

chmod 600 it — those credentials can pause and reconfigure your downloader.

Key Meaning
url LAN address. Always tried first.
public_url Optional. Used only when the LAN address is unreachable, so the widget keeps working away from home. Must be https://: the credentials are never sent to a public address over plain HTTP, never follow a redirect, and replies over 4 MiB are refused. Leave "" if NZBGet has no public address.
user / password NZBGet's ControlUsername / ControlPassword, sent as HTTP Basic auth.

Away from home

With public_url set, the LAN address is tried first and the public one only on failure. That order matters: at 3s polling this widget makes ~28,800 requests a day, and pointing that at a public edge with a rate limiter or an IP-ban daemon is a good way to get banned from your own server.

The choice is remembered in ~/.local/state/omarchy-nzbget/endpoint.json, because backend.sh runs as a fresh process on every poll and would otherwise pay a LAN timeout on every one while you are away. After a fallback it stays on the public endpoint for 10 minutes, then re-probes the LAN — so coming home restores the fast path on its own. The popup shows remote while on that path.

Bad credentials are never failed over to the public endpoint. Retrying a wrong password against your own public edge is a good way to get banned by it.

Without a public_url, leaving the house makes NZBGet unreachable by definition, and a red ! saying so tells you nothing you can act on. So that one case hides from the bar instead (setting Hide from the bar when away from home, on by default). It is deliberately narrow: NZBGet down while you are at home, or a configured public address that also fails, is a real fault and still shows as broken. Turn the setting off to see the fault in every case.

The username and password are NZBGet's Settings → Security → ControlUsername / ControlPassword, sent as HTTP Basic auth. NZBGet ships with defaults (nzbget / tegbzn6789); if yours still accepts them, change them before exposing this or anything else to your network.

Using it

Bar NZBGet mark with the current rate, e.g. ↓ 12.4 MB/s. Hidden when idle.
Bar, paused Mark dimmed, with the word — you paused it, nothing is broken
Bar, processing Downloading finished; NZBGet is unpacking or repairing
Bar, red ! Something has been wrong for 45s straight; the popup names it. Off the home LAN with no public_url, the widget hides instead — see Away from home.
Click Show the queue
⏸ / ▶ Pause or resume all downloading
off 10 5 1 MB/s Speed limit presets
Space in popup Pause / resume
Middle-click Refresh now
r in popup Refresh now
Esc Close

What it shows, and what it refuses to invent

Each queued item gets a progress bar, percentage, transferred and total size, and its state in plain words — NZBGet's raw LOADING_PARS and VERIFYING_REPAIRED say nothing useful to someone watching a download, so they read as checking and verifying repair.

ETA only appears where it means something. NZBGet reports sizes, not estimates, so the ETA is computed from the current rate. That makes it honest for the item actually downloading and meaningless for anything queued behind it — which would have to guess at everything ahead of it — so queued items simply have no ETA rather than a confident-looking fiction.

For the same reason, a paused queue shows no ETA at all, and post-processing shows processing rather than ↓ 0 B/s, which reads as broken when NZBGet is in fact busy unpacking.

Polling

3s while something is downloading, backing off to 15s when the queue is empty. A speed readout needs a few seconds to feel live, but an idle NZBGet does not deserve a wakeup every 3s on a laptop. A failing poll retries at 3s too — the component never backs off slower than the plugin's own steady interval.

The queue itself is only fetched when status says there is one, so an idle poll is a single small request.

A failure is silent until it has lasted 45 seconds. Inside that window the widget keeps showing the last known rate, unmarked — nothing on the bar or in the popup flags it as stale yet; if it has nothing yet — the usual case at boot, since the bar starts before WiFi associates — it stays hidden rather than appearing just to say it is broken. Only 45s of continuous failure earns the red !, marks the popup last-known, and one good poll clears it.

Dependencies

NZBGet Developed against 26.2. Uses only the standard JSON-RPC API.
bash, python3 Standard library only — nothing to pip install.

The bar icon is an SVG, needing qt6-svg — already a hard dependency of quickshell.

Removing it

omarchy plugin remove ky.nzbget-queue
rm -rf ~/.config/omarchy-nzbget ~/.local/state/omarchy-nzbget

The plugin only ever writes ~/.local/state/omarchy-nzbget/endpoint.json, which records which address last worked. It reads its config and never edits it.

Debugging

backend.sh is the whole network surface, so it can be run over SSH:

./backend.sh                 # rate, queue and disk, as JSON
./backend.sh pause
./backend.sh resume
./backend.sh limit 5120      # KB/s; 0 = unlimited

Delete ~/.local/state/omarchy-nzbget/endpoint.json to force a LAN re-probe.

bash poll-output.test.sh checks what the poll reports when nothing answers, including the has_public flag the bar uses to tell "away from home" from "broken".

bash endpoint-safety.test.sh proves where the credentials may go: never to a plain-HTTP public address, never along a redirect, and never into a reply larger than 4 MiB. It runs the public path over real TLS against local stub servers.

bash state-write-safety.test.sh proves what the state writes refuse to do: a symlink planted at the temp name is never followed, a symlinked state file is never read through, and a state directory other accounts can write is refused outright rather than written to.

bash plain-text.test.sh proves every Text element in every .qml file sets textFormat: Text.PlainText, so a download name or status from the server is always drawn as text and never interpreted as markup.

Failures are distinct on purpose — not configured, bad config, auth failed, unreachable, http <code>, public_url must be https, response too large — because a dead downloader and an idle one must never look the same.

Design

See DESIGN.md for why the formatting lives in Python rather than QML, and why the bar item is built from a Row instead of the usual bar button.

Icons

nzbget.svg is from dashboard-icons (Apache 2.0) — the same source as the author's other Omarchy plugins.

Preview image

preview.png is a real session with the release name replaced by Night of the Living Dead (1968), which is public domain in the US — its original release prints omitted the copyright notice. Every other value in it (speed, progress, sizes, free space) is unaltered.