This document describes the current upload-control model on srvarr.
There are two active control layers:
- adaptive global upload budgeting from Jellyfin playback
- native private-tracker prioritization inside the patched Transmission daemon
There is no public/private sub-cap split.
transmission-prioritizer is also active on srvarr, but it is now
split into two services:
transmission-prioritizer: appliesbandwidthPrioritychangestransmission-collector: exports Prometheus metrics without mutating torrents
Together they:
- mark preferred torrents
bandwidthPriority = high - if any preferred torrent currently has peers actively downloading from us,
keep non-preferred
torrents at
bandwidthPriority = normalwhileuploadRatio < 3.0and demote the rest tobandwidthPriority = low - if no preferred torrent currently has peers actively downloading from us,
promote non-preferred
torrents with
uploadRatio < 3.0tobandwidthPriority = highand keepuploadRatio >= 3.0torrents atbandwidthPriority = low - if a completed non-preferred torrent reaches
uploadRatio >= 6.0, pause it so the cleaner can remove it once it is old enough - exports per-class metrics for Prometheus / Grafana
It does not manage bandwidth groups, public caps, or SABnzbd suppression.
Host wiring:
Helper module:
Important current facts:
srvarrimportsadaptive-upload-policy.nixsrvarrimportstransmission-prioritizer.nixtransmission-prioritizercan be stopped independently fromtransmission-collector- Transmission gets:
TR_TRACKER_PRIORITY_FILE=/run/secrets/transmissionTrackerHosts
- the preferred tracker host secret lives at:
/run/secrets/transmissionTrackerHosts
jellyfin-upload-policy reads Jellyfin exporter metrics from beast over the
internal Prometheus mTLS endpoint on https://beast:9594/metrics and computes
a host-wide upload target.
Current values:
- idle ceiling:
25mbit - minimum target with healthy exporter data:
0.5mbit - conservative fallback when exporter data is unavailable:
8mbit - bitrate headroom:
10% - relaxation hold:
90s
Transmission then gets a session upload cap equal to 95% of that target.
Examples:
25mbittarget ->2968 kB/s15mbittarget ->1781 kB/s8mbitfallback ->950 kB/s0.5mbitminimum target ->59 kB/s
The same adaptive state also drives WireGuard tc shaping.
Shared state file:
/run/adaptive-upload-policy/state.json
The main active fields are the adaptive target, reason, timestamps, and
transmission_upload_limit_kbps.
Transmission is patched to honor TR_TRACKER_PRIORITY_FILE.
Current behavior:
- preferred tracker hosts are loaded from that file
- already-due announces for preferred trackers are dispatched first
- peers learned from preferred trackers are treated as preferred in peer scheduling
- tracker-provided announce cadence is not overridden
This is now the main private-tracker preference mechanism.
Implementation:
- pkgs/transmission-tracker-prioritizer/prioritizer.py
- pkgs/transmission-tracker-prioritizer/collector.py
- pkgs/transmission-tracker-prioritizer/main.py
The helper code is split into separate collector and prioritizer entrypoints with shared classification logic:
transmission-prioritizer: classifies torrents and writesbandwidthPriorityupdates back to Transmissiontransmission-collector: runs the same classification logic but only exports the observed state to Prometheus- both classify torrents by preferred tracker host when deciding which priorities to enforce
- sets:
- preferred torrents ->
bandwidthPriority = high - if any preferred torrent currently has peers actively downloading from us:
non-preferred torrents with uploadRatio < 3.0 -> bandwidthPriority = normal - if any preferred torrent currently has peers actively downloading from us:
non-preferred torrents with uploadRatio >= 3.0 -> bandwidthPriority = low - if no preferred torrent currently has peers actively downloading from us:
non-preferred torrents with uploadRatio < 3.0 -> bandwidthPriority = high - if no preferred torrent currently has peers actively downloading from us:
non-preferred torrents with uploadRatio >= 3.0 -> bandwidthPriority = low - if a non-preferred torrent is complete and
uploadRatio >= 6.0: stop/pause the torrent
- preferred torrents ->
- exports
low/normal/hightorrent priority metrics based on currentbandwidthPriority
It does not:
- create or manage a public bandwidth group
- split upload budget into “public” and “private” areas
- read SABnzbd exporter state
- read adaptive upload state
Primary places to inspect the system:
/run/adaptive-upload-policy/state.json- mTLS client material:
/run/secrets/jellyfinUploadPolicyClientCrt/run/secrets/jellyfinUploadPolicyClientKey
- logs:
jellyfin-upload-policyjellyfin-upload-policy-transmissionjellyfin-upload-policy-tc
The collector exports per-priority torrent, peer, download, and upload metrics through the node exporter textfile directory.
On srvarr, that export is handled by
transmission-collector, so metrics continue updating even if
transmission-prioritizer is stopped.
Important note:
host_observability_transmission_public_group_upload_limit_bytes_per_secondhost_observability_transmission_observed_public_group_upload_limit_bytes_per_secondhost_observability_transmission_reserved_private_upload_bytes_per_second
are now compatibility metrics only. The simplified helper exports them as 0.
The obsolete Public Upload Cap and Private Upload Reserve Grafana panels
were removed from the Media Pipe dashboard.