Repository navigation
Security
- The web server no longer serves files outside the frontend build directory. All earlier versions are affected; update to this release.
Highlights
- Demand-aware allocation between download clients: a client that isn't using its share lends the unused part to clients that are, download and upload. On by default; toggle in Settings > Bandwidth. (#85)
- Inactive clients are promoted once they reach 80% of their safety-net cap; in two-client setups they previously had to exceed it. (#85)
- Dashboard panels can be reordered from a per-panel menu and minimised into one-line summaries; the layout is saved per browser. The stream-count graph is now its own panel. (#86)
- Throttling can be switched off from the dashboard, optionally for a set duration, and the control lives in General settings; the state persists across restarts and clients are set to unlimited while it is off. (#78)
- Threshold notifications have a configurable cooldown in Notification settings. (#72)
- Bandwidth settings and the wizard carry the "set 10-20% below your real line speed" advice and per-client speed-unit notes. (#83, #84)
Fixes
- Client speed limits are converted with each client's real byte unit. qBittorrent, NZBGet, Deluge and SABnzbd limits become 2-5% tighter than before (they were over-allocated); Transmission is unchanged.
- SQLite now really runs in WAL journal mode with foreign-key enforcement on (both were configured but silently skipped on every release so far). Existing databases convert on the first start;
speedarr.db-walandspeedarr.db-shmappear besidespeedarr.dband belong in any backup taken while the container is running. The startup log reports the effective mode. (#88) - The setup wizard no longer returns 500 for Emby/Jellyfin servers while in setup mode. (#32, still experimental)
- A malformed throttling-state timestamp now fails open instead of leaving throttling stuck. (#78)
- Log noise: the per-poll "Multiple active" line is DEBUG, standby and single-active lines carry a direction prefix, and demand-aware state changes log as SATURATED/SLACK. (#85)
Dependencies
- Backend runtime: Python 3.14.7 (slim-bookworm), up from 3.11.7. Every dependency installs from a prebuilt wheel on amd64 and arm64, and the image no longer carries gcc, so it is about 40% smaller.
- Backend: FastAPI 0.141, starlette 1.6 (pinned directly; clears seven starlette advisories carried by the previous transitive 0.35.1), pydantic 2.13, SQLAlchemy 2.0.52, uvicorn 0.52, aiohttp 3.14.3, pyasn1 0.6.4. apscheduler removed from the image (it was never used).
- Backend auth: passlib and python-jose replaced by bcrypt 5.0.0 and PyJWT 2.14.0; cryptography 50.0.1 pinned directly. Passwords longer than 72 bytes are rejected when set (accented letters, symbols and emoji count as 2 to 4 bytes each); existing passwords are unaffected.
- Frontend build: Node 24.21 LTS on Alpine 3.24 (was Node 20.11), Vite 8.2 on rolldown, TypeScript 6.0, ESLint 10 with typescript-eslint 8 and a flat config, jsdom 30 and jest-dom 7 for the unit tests. No runtime dependency changed; the served bundle is about 3% smaller.
- Frontend: React Router 7, vitest 4.1.11, plus the Dependabot frontend group and the transitive security bumps (postcss, brace-expansion, minimatch, browserslist, js-yaml, baseline-browser-mapping).
- CI: checkout, login, metadata, qemu and gh-release actions bumped.
Notes for API users
- API clients using an API key must send
Content-Type: application/jsonwith JSON request bodies (POST /api/control/manual-throttle,/api/control/restore-speeds,/api/control/pause-monitoring,/api/bandwidth/temporary-limits); requests without the header are rejected with 422. The examples on the API keys settings page already include it.
What's Changed
- Release v2026.09.21 by @coreyeaston in #97
Full Changelog: v2026.07.07...v2026.09.21