Skip to content

Releases: AlteredParadox/pmss-fleet-manager

v1.3.1

Choose a tag to compare

@github-actions github-actions released this 19 Oct 20:39
56e656e

Highlights

The add-box shortcut explains where plan and renewal come from. Clicking "+ add box" next to a service in settings prefilled host, username and type but left plan and renewal date empty, and the review step showed "— · —", so it looked as if the API data was dropped (#77, thanks @schmintendo). It was not: once saved, the box matches the service and shows the API plan and next due date live. The fields are blank on purpose, because a typed renewal date overrides the API value and would freeze at the current cycle. The wizard now uses the service's plan as the placeholder, says which service the box is matched to and what it renews on, and the review step previews both values marked "·api". The same hints appear when editing a box that is matched to a service. (#78)

Suspended services on the page. The frontend's renewal fallback now treats a Suspended (usually overdue) service's due date as a renewal, as the server has since 1.3.0. (#78)

Nothing else changed since 1.3.0 apart from README wording.

Container image: ghcr.io/alteredparadox/pmss-fleet-manager:1.3.1 (linux/amd64, linux/arm64).

What's Changed

  • README: status section as a short status plus a per-release history by @AlteredParadox in #75
  • README: credit the 1.3.0 review to Väinämöinen, MagnaCapax's review agent by @AlteredParadox in #76
  • Add-box wizard: show the matched service's plan and renewal instead of blank fields by @AlteredParadox in #78
  • README: 1.3.1 is the current release by @AlteredParadox in #79

Full Changelog: v1.3.0...v1.3.1

v1.3.0

Choose a tag to compare

@github-actions github-actions released this 19 Oct 07:16
fc7d885

Highlights

This release takes in a full read-through of the code by the Pulsed Media / PMSS maintainers (MagnaCapax, #72), merged with their commits intact via #73, plus the follow-ups they suggested. Thank you.

Behaviour change: Host-header check on wildcard binds. A dashboard bound to 0.0.0.0 or :: (every container) used to accept any Host header when -allowed-hosts was unset, which left a no-auth install open to DNS rebinding. It now serves localhost and any IP address, and refuses other names with a 421 until they are listed in -allowed-hosts / PMSS_ALLOWED_HOSTS. If you reach a container by hostname, add that name. This is why the version is 1.3.0 and not 1.2.5. (#72)

Autostart keeps your crontab. "Set up autostart" replaced every live crontab line that mentioned ~/bin/qbt-start, so a line like backup.sh && ~/bin/qbt-start was lost. It now replaces only lines whose whole command is the helper (redirections allowed), runs byte-wise so a line with odd bytes cannot turn grep's output into "Binary file matches" inside your crontab, and saves the previous crontab to ~/.config/pmss-fleet-manager/crontab.bak first. (#72, #73)

qBittorrent enabled in the Pulsed Media panel is respected. PMSS's own watchdog runs and configures qBittorrent on such accounts. The dashboard now detects the panel's flag, shows "panel-managed", keeps monitoring, and declines to install or autostart a second build that would fight it. (#72, #73)

Installer verifies downloads. For any GitHub release asset URL (the default userdocs build included) the dashboard fetches the asset's sha256 from GitHub's API and the box checks the download against it before the existing ELF and --version checks. Other URLs install unverified and the output says so. curl is preferred over wget, whose --https-only only applies to recursive downloads. (#72, #73)

No third-party requests from the page. The JetBrains Mono web font is embedded in the binary (SIL Open Font License 1.1, listed in the third-party notices) instead of loaded from Google Fonts, so viewers' addresses stay with your dashboard and offline installs look right. (#73)

Also from the review. Fractional cpu_hours in the Pulsed Media feed no longer reject the whole billing feed; suspended services count towards costs and renewal alerts; an acknowledged alert that escalates comes back; the throttle meter is shown only while throttled; a qBittorrent response over the size cap is an explicit error; -auth requires both user and password; the wizard shows the detected WebUI port as a hint rather than pinning it; the "localhost bypass" suggestion is gone (it would open the WebUI to other tenants); forgetting a pinned host key asks for confirmation; mutating requests need an http or https Origin; an SSH key the container cannot read is named in the error and HOME is fixed inside the image. (#72, #73)

Container image: ghcr.io/alteredparadox/pmss-fleet-manager:1.3.0 (linux/amd64, linux/arm64). Container users reaching the dashboard by hostname: set PMSS_ALLOWED_HOSTS.

Container image: ghcr.io/alteredparadox/pmss-fleet-manager:1.3.0 (linux/amd64, linux/arm64).

What's Changed

  • Review fixes from the PMSS maintainers (#72) plus the follow-ups they suggested by @AlteredParadox in #73
  • Fix fractional cpu_hours, keep the Host check on wildcard binds, and other fixes from a full read-through by @MagnaCapax in #72
  • README: 1.3.0 is the current release by @AlteredParadox in #74

New Contributors

Full Changelog: v1.2.4...v1.3.0

v1.2.4

Choose a tag to compare

@github-actions github-actions released this 19 Oct 05:48
204cc41

Highlights

WebUI port check keeps working under Pulsed Media's socket-table privacy. PMSS has an opt-in hardening (its ADR 0068) that makes /proc/net/tcp and /proc/net/tcp6 root-only so one tenant cannot read another's connection addresses. On a host with it enabled, 1.2.3 refused every qBittorrent login with could not read the listening sockets on the box; not sending credentials unverified. The same hardening deliberately keeps ss -tlnp working, so the probe and the live re-check before credential-sending actions now fall back to it. A socket ss attributes to one of your processes counts as yours; anything it cannot attribute is treated as another account's and still refused, and a port shared with one is still contested. (#70)

A container that cannot write its data directory says so. Instead of a bare permission error the process exits with the directory, the uid and gid it ran as, and both fixes: make the directory writable for that uid, or run with --user set to the directory's owner. On Unraid, where appdata is owned by nobody:users, set Extra Parameters to --user 99:100 or chown -R 65532:65532 the appdata folder. The README's container section has an Unraid entry. (#69)

Container image: ghcr.io/alteredparadox/pmss-fleet-manager:1.2.4 (linux/amd64, linux/arm64).

Container image: ghcr.io/alteredparadox/pmss-fleet-manager:1.2.4 (linux/amd64, linux/arm64).

What's Changed

Full Changelog: v1.2.3...v1.2.4

v1.2.3

Choose a tag to compare

@github-actions github-actions released this 19 Oct 00:42
1402072

Highlights

1.2.3 is the first release with a container image, and moves the build to Go 1.27.

Container image. Every release now publishes ghcr.io/alteredparadox/pmss-fleet-manager for linux/amd64 and linux/arm64 alongside the binaries, built by the same workflow from the same tag. The image is distroless: the static binary, CA roots and time-zone data, nothing else, running as an unprivileged user. Data lives in /data; every flag is available as an environment variable. See "Running in a container" in the README for the volume, TZ, SSH key and reverse-proxy notes.

docker run -d --name pmss-fleet-manager -p 127.0.0.1:8080:8080 -v pmss-data:/data -e TZ=America/Chicago ghcr.io/alteredparadox/pmss-fleet-manager:1.2.3

Go 1.27.2. The binaries and the image are compiled with Go 1.27.2; the Dockerfile builds with whatever toolchain go.mod names, so both artifacts always share one compiler.

No behaviour changes in the dashboard itself. Upgrading from 1.2.2 needs nothing beyond replacing the binary.

Container image: ghcr.io/alteredparadox/pmss-fleet-manager:1.2.3 (linux/amd64, linux/arm64).

What's Changed

  • Container image: Dockerfile, CI smoke build, GHCR push on release by @AlteredParadox in #66
  • Bump golang from 1.26-alpine to 1.27-alpine in the docker group by @dependabot[bot] in #67
  • Go 1.27.2 across the board; Dockerfile builds with go.mod's toolchain by @AlteredParadox in #68

Full Changelog: v1.2.2...v1.2.3

v1.2.2

Choose a tag to compare

@github-actions github-actions released this 18 Oct 18:42
bda53b8

Highlights

1.2.2 adds one feature: the dashboard can run under a reverse-proxy sub-path.

-base-path (env PMSS_BASE_PATH). Set it to the prefix your proxy forwards unchanged, for example -base-path /fleet, and open https://proxy/fleet/. Every route, the page and its assets are served under that prefix; the SPA works out the prefix from its own URL, so the same build also works behind a proxy that strips the prefix before forwarding, and standalone deployments are unchanged. Basic auth, the AGPL public pages and the same-origin check for mutating requests all apply under the prefix exactly as at the root. The flag is normalised (trailing or missing slash) and rejected at startup with a clear message if it contains characters a route pattern cannot take.

This is the first outside contribution to the project, started by @doomio in #64 and finished on their branch. Thank you.

No other behaviour changes. Upgrading from 1.2.1 needs nothing beyond replacing the binary.

What's Changed

New Contributors

Full Changelog: v1.2.1...v1.2.2

v1.2.1

Choose a tag to compare

@github-actions github-actions released this 18 Oct 06:09
7599943

Highlights

1.2.1 is a hardening release. It acts on two rounds of an independent external review of 1.2.0; the remaining findings are recorded as accepted design decisions (trust-on-first-use host keys, the unsigned upstream qBittorrent build, delete ordering, server-versus-browser time zones).

qBittorrent login safety. One login attempt runs at a time per box, and its outcome is shared with every request that was waiting on it, across the clients the dashboard rebuilds on reconnect and the wizard's detection runs. A burst of torrent actions with a wrong password, or a login whose connection drops mid-flight, sends the credentials once instead of once per action, so it cannot walk the box's loopback into qBittorrent's five-failure IP ban.

Pulsed Media feed cache. The cached services feed is stored as one record tied to a fingerprint of the API key that fetched it, is dropped the moment the key is cleared or replaced, and is only restored at startup under that same key. A fetch that was in flight across a key change is discarded. Cancelled services stay listed for history but no longer count towards box cost totals or renewal dates and alerts.

Smaller fixes. Box edits clear and save secrets in a single write. The Pulsed Media API key is never forwarded on a redirect. The qBittorrent installer downloads HTTPS-only, including across redirects, under a 200 MB size limit on both wget and curl. Response bodies from qBittorrent and Docker are capped at 16 MiB. Renewal days are counted as calendar days in the dashboard host's time zone on both server and browser (previously the server rolled over at UTC midnight and the browser at local midnight). The browser retries a failed first state load once the event stream opens, keeps at most one torrent-view request in flight with a two-second minimum interval, coalesces fleet rebuilds onto one animation frame, deduplicates shared services in the cost total, and refresh-all skips disabled boxes and reports failures.

Upgrade note. The services list is empty for about a minute after the first start on 1.2.1 while the old cache format is dropped and the feed is refetched.

What's Changed

  • Fixes from external review 1: login single-flight, feed drop on key change, single-write edit by @AlteredParadox in #59
  • Renewal dates as civil dates on both sides; installer size cap by @AlteredParadox in #60
  • Review 2 fixes: cache keyed to API key, shared login outcome, active-only costs by @AlteredParadox in #61
  • qbt: share a failed login across every client on the guard by @AlteredParadox in #62
  • README: status and hardening notes for 1.2.1 by @AlteredParadox in #63

Full Changelog: v1.2.0...v1.2.1

v1.2.0

Choose a tag to compare

@github-actions github-actions released this 18 Oct 03:06
647f139

What's Changed

Full Changelog: v1.1.0...v1.2.0

v1.1.0

Choose a tag to compare

@github-actions github-actions released this 17 Oct 17:44
d4009e9

What's Changed

  • README: fleet overview screenshot by @AlteredParadox in #31
  • SonarCloud batch 1: mechanical fixes and documented rule exceptions by @AlteredParadox in #32
  • SonarCloud: documented exceptions for the UI template style and mid-range complexity by @AlteredParadox in #33
  • SonarCloud: one complexity exception entry per file (no brace globs) by @AlteredParadox in #34
  • Reduce cognitive complexity of seven Go functions by pure extraction by @AlteredParadox in #35
  • app.js: extract helpers to cut cognitive complexity; prefer optional chains by @AlteredParadox in #36
  • SonarCloud: mid-range complexity exception for app.js, matching the Go one by @AlteredParadox in #37
  • README: 1.1.0 status and SonarCloud paragraph by @AlteredParadox in #38

Full Changelog: v1.0.0...v1.1.0

v1.0.0

Choose a tag to compare

@github-actions github-actions released this 17 Oct 06:45
f90588c

What's Changed

  • Bump Go to 1.26.9 for stdlib vulnerability fixes by @AlteredParadox in #2
  • Bump the github-actions group with 2 updates by @dependabot[bot] in #1
  • License under AGPL-3.0-or-later with headers, notices and source offer by @AlteredParadox in #3
  • Harden parsers and probe against hostile box and co-tenant input by @AlteredParadox in #4
  • Never retry a rejected qBittorrent login; verify the WebUI port is ours by @AlteredParadox in #5
  • Fix host-key re-pinning on edit; validate Host header; harden the UI by @AlteredParadox in #6
  • Cancel polls on edit/remove, back off failing boxes, keep du data, fix races by @AlteredParadox in #7
  • Remove dead code, unused fields and the unread samples history by @AlteredParadox in #8
  • Bound slow probe commands, name the hung section, tidy SSH auth by @AlteredParadox in #9
  • Probe: list only listening sockets instead of dumping /proc/net/tcp by @AlteredParadox in #10
  • Key daily traffic by the box's zone; drop slow SSE clients; summarise account config by @AlteredParadox in #11
  • Review round 1: listen owners from /proc only, port gate re-verified, cancelled polls ignored by @AlteredParadox in #12
  • Measure RAM pressure on process memory, not page cache; alert on OOM kills by @AlteredParadox in #13
  • Review round 2: NaN sanitised everywhere, address-aware port owners, OOM baseline, cancelled-poll ordering by @AlteredParadox in #14
  • Review round 3: detect honours the host-key pin, no float reaches JSON unsanitised by @AlteredParadox in #15
  • Probe: abandon a hung quota/df instead of waiting on it by @AlteredParadox in #16
  • Review round 4: one rule for host-key pins and stored secrets; guard armed on any stop by @AlteredParadox in #17
  • Retry failing boxes at the normal rate first, then back off; show it in the UI by @AlteredParadox in #18
  • Review round 5: live port re-check before credential actions; edits finish on the server's context by @AlteredParadox in #19
  • Review round 6: SSH agent hang on cancel; disabled boxes drop retry state; live port check end marker by @AlteredParadox in #20
  • Review round 7: database files owner-only from creation; offline box stays offline across edits by @AlteredParadox in #21
  • Review round 8: failed polls are cached too, so a restart restores a down box as offline by @AlteredParadox in #22
  • Review round 9 (first clean round): bound probe identity strings; snapshot edited state after the old poller stops by @AlteredParadox in #23
  • Review round 10: the detail page never shows one box under another box's URL by @AlteredParadox in #24
  • Bind failure: close the store before exiting 1 by @AlteredParadox in #25
  • Review round 11: a removed box's page is dropped, not kept; alerts hold through a blip in their source by @AlteredParadox in #26
  • Review round 12: alerts for a switched-off source resolve; settings saved elsewhere are never reverted by @AlteredParadox in #27
  • Review round 13 (clean round): settings saves serialised; cron entries counted only when live; PMSS eyebrow by @AlteredParadox in #28
  • Review round 14 (second clean round, loop complete): key change supersedes in-flight sync; settings body read before the lock by @AlteredParadox in #29
  • README: security and hardening section; status for 1.0.0 by @AlteredParadox in #30

New Contributors

Full Changelog: https://github.com/AlteredParadox/pmss-fleet-manager/commits/v1.0.0