The image can fetch files over HTTP, FTP, SMB, NFS and rsync (wget, libcurl,
lftp, cifs-utils, nfs-utils, rsync — docs/buildroot-config.md §5.10, §5.16,
§5.22, §5.23) and over none of the peer-to-peer protocols. A growing amount of freely
redistributable arcade and other media — homebrew and public-domain collections,
permissively-licensed game and A/V sets, large software-preservation archives — is
published over BitTorrent rather than HTTP, because the publishers cannot carry the
bandwidth for direct downloads. Today a MiSTer cannot touch any of it without a PC in
the middle.
A MiSTer is an unusually good BitTorrent peer, too: it is often powered continuously,
it already has a large exFAT volume mounted, and a client lets the board keep seeding
what it fetched back to the swarm — which is the point of that distribution model
rather than a side effect of it.
The second motivation is LAN-local. A household or club with several MiSTers should
pull a set over the WAN once and have the remaining boards get it from each other at
LAN speed. That needs Local Peer Discovery, and LPD turns out to be the requirement
that eliminates most of the field.
Requirements
- Headless and scriptable. No X, no Qt, no TUI-only interface.
- Local Peer Discovery.
- DHT, so a set stays reachable when its trackers go down — which, for volunteer
preservation projects, they do.
- Selective download. This material is routinely published as one torrent per
collection holding thousands of files and hundreds of gigabytes; a user wants three
of those files, not the other 11,167.
- Upstream-maintained, and ideally already packaged by Buildroot — no new hash-sync
case, no new Renovate stream, no patch series of ours to carry.
Survey of what Buildroot 2026.08 actually offers
| Package |
LPD |
DHT |
Selective |
Verdict |
| transmission 4.1.3 |
yes, default on |
yes, default on |
yes, -g/-G |
proposed |
| rtorrent 0.15.3 |
no |
yes |
yes |
fails req. 2 |
| ctorrent dnh3.3.2 |
no |
no |
partial |
2008 release, no magnet support either |
| libtorrent-rasterbar |
yes |
yes |
yes |
library only — no CLI client packaged on top of it, and Buildroot pins the v1-only 1.2 branch (1.2.20) |
| aria2 |
yes |
yes |
yes |
not in Buildroot; last upstream release is 1.37.0 (Nov 2023) |
The rtorrent result is the surprising one and is worth recording: rakshasa's libtorrent
0.15.3 has a full src/dht/ implementation but no LPD at all — the standard LPD
multicast group 239.192.152.143 does not appear anywhere in its source tree. rtorrent
is otherwise the obvious "CLI BitTorrent client" answer, and it cannot do the thing we
most want.
Proposal
Enable the upstream package: BR2_PACKAGE_TRANSMISSION + BR2_PACKAGE_TRANSMISSION_DAEMON.
Everything in the requirements list is default-on in 4.1.3 (libtransmission/session.h:424-447):
bool dht_enabled = true; bool lpd_enabled = true;
bool pex_enabled = true; bool utp_enabled = true;
LPD is the standard 239.192.152.143:6771 / [ff15::efc0:988f]:6771 pair
(libtransmission/tr-lpd.cc:67), so two boards on one LAN find each other with no
configuration.
Buildroot never passes -DENABLE_UTILS and upstream defaults it ON
(CMakeLists.txt:64), so transmission-remote, -create, -edit and -show come
with the base package — only the daemon needs its own symbol.
Do not enable BR2_PACKAGE_TRANSMISSION_CLI. libtransmission is a static library
(libtransmission/CMakeLists.txt:15), so every binary embeds its own full copy, and
transmission-cli has no file-selection options whatsoever (cli/cli.cc:53-77) — it
downloads the entire torrent, which is the exact opposite of requirement 4. We pay for
a second copy of the engine to get a tool we do not want anyone using.
Toolchain prerequisites are all already met: MMU, gcc 15.3.0 (needs ≥ 7), wchar,
libstdcpp, threads, dynamic libs.
New dependencies pulled in: dht, libb64, libdeflate, libminiupnpc, libnatpmp,
libpsl (→ libidn2), libutp. Already in the target: openssl, libcurl, libevent,
zlib, ncurses, and libunistring (1.9 MB, via gnutls). The bundled web UI is a 252 KB
prebuilt public_html in the release tarball, so no host node/esbuild dependency
appears.
Placement: package/mister-userspace/Config.in under the §5.10 networking block, bare
selects per that file's convention, documented in docs/buildroot-config.md §5.10 and
docs/package-manifest.md.
Work items
- Kconfig + docs. The two selects above, §5.10 rationale, package-manifest entry.
- Init script. Buildroot's
S92transmission is wrong for this image: it starts the
daemon at boot as user transmission with
TRANSMISSION_HOME=/var/config/transmission-daemon. Our rootfs is read-only and
reflashed wholesale, so settings.json, resume/ and torrents/ have to live on
/media/fat or every OS update destroys in-progress downloads and all seeding state.
Needs a board-overlay replacement, and it should be off by default — the azcopy
precedent (packaged, not enabled) is the right one here.
- Security posture — ADR 0031. The daemon listens on an RPC port (9091) and a peer
port, and performs UPnP/NAT-PMP port mapping by default. Its RPC whitelist defaults to
loopback and authentication defaults to off, which is safe only for as long as it
stays bound to loopback. On an image that is already root:1 over SSH and FTP with no
iptables filter table on the RT kernel, a new listening daemon deserves an explicit
disposition in ADR 0031 rather than a quiet select. Recommended defaults: RPC bound
to 127.0.0.1, port-forwarding off, both opt-in through the documented FAT-backed
settings.json.
- exFAT behaviour. Preallocation defaults to
Sparse (session.h:480) and exFAT has
no sparse files. Needs a rig test writing a multi-hundred-megabyte file before we
trust it; "preallocation": 0 is the fallback.
- Scale test. A single collection torrent in this space can reach ~11k files and
~200k pieces for multi-terabyte content — roughly 4 MB of piece hashes before any
per-file structures, on a board with 1 GB of DDR shared with the FPGA. Measure RSS
with metadata of that size loaded and document a recommended ceiling.
- docs/bittorrent.md with the headless recipe and the FAT-backed layout.
Known limitations — accept and document
No BitTorrent v2. libtransmission/torrent-metainfo.cc:143-147 reads // v2, ignore for today and logs 'file tree' is ignored. Hybrid torrents still work through their v1
half; a v2-only torrent will not load. If v2-only sets become common, the answer is a
libtorrent-rasterbar 2.x-based client, not a patched transmission — the two share no
code whatsoever (Transmission's entire external library surface is fast_float, fmt,
rapidjson, small, utfcpp, wide-integer, curl, a TLS library, libdeflate, libevent,
libnatpmp, miniupnpc, dht, libpsl, libutp, libb64; the string "libtorrent" appears in the
tree only in a peer-ID name table and in comments). Note that Buildroot's
libtorrent-rasterbar is pinned to 1.2.20, which is itself v1-only, so that route would
start with a package bump.
Magnet so= (BEP 53) is ignored. The magnet parser handles dn, tr, ws and xt
only (libtransmission/magnet-metainfo.cc:240-267). Publishers that hand out per-file
magnets carrying a select-only file index get that index silently dropped, and the whole
collection is queued instead. Workaround, and a good candidate for a small wrapper script
that parses so= itself:
transmission-remote --start-paused -a '<magnet-or-url>'
transmission-remote -t <id> --files # 0-based, torrent file order
transmission-remote -t <id> -G all -g 1,5,9-12
transmission-remote -t <id> -s
Indices are printed from 0 in the torrent's own file order (utils/remote.cc:1352-1414),
which matches the file index publishers cite.
Acceptance
make mister_de10nano_defconfig && make builds clean; scripts/check-defconfigs.sh passes.
transmission-daemon starts from the FAT-backed config directory, and resume state
survives an OS update.
- Two boards on one LAN discover each other via LPD on a non-private torrent (verify with
tcpdump on 239.192.152.143:6771).
- DHT reaches a ready state on a torrent whose trackers are all dead.
- Selective download fetches only the chosen files out of a multi-thousand-file torrent.
- Nothing new listens on a non-loopback interface unless the user explicitly enables it.
The image can fetch files over HTTP, FTP, SMB, NFS and rsync (
wget,libcurl,lftp,cifs-utils,nfs-utils,rsync— docs/buildroot-config.md §5.10, §5.16,§5.22, §5.23) and over none of the peer-to-peer protocols. A growing amount of freely
redistributable arcade and other media — homebrew and public-domain collections,
permissively-licensed game and A/V sets, large software-preservation archives — is
published over BitTorrent rather than HTTP, because the publishers cannot carry the
bandwidth for direct downloads. Today a MiSTer cannot touch any of it without a PC in
the middle.
A MiSTer is an unusually good BitTorrent peer, too: it is often powered continuously,
it already has a large exFAT volume mounted, and a client lets the board keep seeding
what it fetched back to the swarm — which is the point of that distribution model
rather than a side effect of it.
The second motivation is LAN-local. A household or club with several MiSTers should
pull a set over the WAN once and have the remaining boards get it from each other at
LAN speed. That needs Local Peer Discovery, and LPD turns out to be the requirement
that eliminates most of the field.
Requirements
preservation projects, they do.
collection holding thousands of files and hundreds of gigabytes; a user wants three
of those files, not the other 11,167.
case, no new Renovate stream, no patch series of ours to carry.
Survey of what Buildroot 2026.08 actually offers
-g/-GThe rtorrent result is the surprising one and is worth recording: rakshasa's libtorrent
0.15.3 has a full
src/dht/implementation but no LPD at all — the standard LPDmulticast group
239.192.152.143does not appear anywhere in its source tree. rtorrentis otherwise the obvious "CLI BitTorrent client" answer, and it cannot do the thing we
most want.
Proposal
Enable the upstream package:
BR2_PACKAGE_TRANSMISSION+BR2_PACKAGE_TRANSMISSION_DAEMON.Everything in the requirements list is default-on in 4.1.3 (
libtransmission/session.h:424-447):LPD is the standard
239.192.152.143:6771/[ff15::efc0:988f]:6771pair(
libtransmission/tr-lpd.cc:67), so two boards on one LAN find each other with noconfiguration.
Buildroot never passes
-DENABLE_UTILSand upstream defaults itON(
CMakeLists.txt:64), sotransmission-remote,-create,-editand-showcomewith the base package — only the daemon needs its own symbol.
Do not enable
BR2_PACKAGE_TRANSMISSION_CLI.libtransmissionis a static library(
libtransmission/CMakeLists.txt:15), so every binary embeds its own full copy, andtransmission-clihas no file-selection options whatsoever (cli/cli.cc:53-77) — itdownloads the entire torrent, which is the exact opposite of requirement 4. We pay for
a second copy of the engine to get a tool we do not want anyone using.
Toolchain prerequisites are all already met: MMU, gcc 15.3.0 (needs ≥ 7), wchar,
libstdcpp, threads, dynamic libs.
New dependencies pulled in:
dht,libb64,libdeflate,libminiupnpc,libnatpmp,libpsl(→libidn2),libutp. Already in the target: openssl, libcurl, libevent,zlib, ncurses, and
libunistring(1.9 MB, via gnutls). The bundled web UI is a 252 KBprebuilt
public_htmlin the release tarball, so no host node/esbuild dependencyappears.
Placement:
package/mister-userspace/Config.inunder the §5.10 networking block, bareselects per that file's convention, documented in docs/buildroot-config.md §5.10 anddocs/package-manifest.md.
Work items
S92transmissionis wrong for this image: it starts thedaemon at boot as user
transmissionwithTRANSMISSION_HOME=/var/config/transmission-daemon. Our rootfs is read-only andreflashed wholesale, so
settings.json,resume/andtorrents/have to live on/media/fator every OS update destroys in-progress downloads and all seeding state.Needs a board-overlay replacement, and it should be off by default — the azcopy
precedent (packaged, not enabled) is the right one here.
port, and performs UPnP/NAT-PMP port mapping by default. Its RPC whitelist defaults to
loopback and authentication defaults to off, which is safe only for as long as it
stays bound to loopback. On an image that is already root:1 over SSH and FTP with no
iptables filter table on the RT kernel, a new listening daemon deserves an explicit
disposition in ADR 0031 rather than a quiet
select. Recommended defaults: RPC boundto
127.0.0.1, port-forwarding off, both opt-in through the documented FAT-backedsettings.json.Sparse(session.h:480) and exFAT hasno sparse files. Needs a rig test writing a multi-hundred-megabyte file before we
trust it;
"preallocation": 0is the fallback.~200k pieces for multi-terabyte content — roughly 4 MB of piece hashes before any
per-file structures, on a board with 1 GB of DDR shared with the FPGA. Measure RSS
with metadata of that size loaded and document a recommended ceiling.
Known limitations — accept and document
No BitTorrent v2.
libtransmission/torrent-metainfo.cc:143-147reads// v2, ignore for todayand logs'file tree' is ignored. Hybrid torrents still work through their v1half; a v2-only torrent will not load. If v2-only sets become common, the answer is a
libtorrent-rasterbar 2.x-based client, not a patched transmission — the two share no
code whatsoever (Transmission's entire external library surface is fast_float, fmt,
rapidjson, small, utfcpp, wide-integer, curl, a TLS library, libdeflate, libevent,
libnatpmp, miniupnpc, dht, libpsl, libutp, libb64; the string "libtorrent" appears in the
tree only in a peer-ID name table and in comments). Note that Buildroot's
libtorrent-rasterbar is pinned to 1.2.20, which is itself v1-only, so that route would
start with a package bump.
Magnet
so=(BEP 53) is ignored. The magnet parser handlesdn,tr,wsandxtonly (
libtransmission/magnet-metainfo.cc:240-267). Publishers that hand out per-filemagnets carrying a select-only file index get that index silently dropped, and the whole
collection is queued instead. Workaround, and a good candidate for a small wrapper script
that parses
so=itself:Indices are printed from 0 in the torrent's own file order (
utils/remote.cc:1352-1414),which matches the file index publishers cite.
Acceptance
make mister_de10nano_defconfig && makebuilds clean;scripts/check-defconfigs.shpasses.transmission-daemonstarts from the FAT-backed config directory, and resume statesurvives an OS update.
tcpdump on
239.192.152.143:6771).