Archive of https://git.etawen.dev/mia/hbshare — Private invite-only BitTorrent pool for sharing homebrew between trusted peers. https://git.etawen.dev/mia/hbshare
  • C++ 67.7%
  • HTML 27.9%
  • Shell 3.7%
  • Makefile 0.7%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-05-15 20:53:15 -04:00
scripts Initial commit: hbshare — private homebrew-sharing BT pool 2026-05-15 20:32:26 -04:00
src Initial commit: hbshare — private homebrew-sharing BT pool 2026-05-15 20:32:26 -04:00
.gitignore Initial commit: hbshare — private homebrew-sharing BT pool 2026-05-15 20:32:26 -04:00
gallery.html Initial commit: hbshare — private homebrew-sharing BT pool 2026-05-15 20:32:26 -04:00
LICENSE Initial commit: hbshare — private homebrew-sharing BT pool 2026-05-15 20:32:26 -04:00
Makefile Initial commit: hbshare — private homebrew-sharing BT pool 2026-05-15 20:32:26 -04:00
Makefile.linux Initial commit: hbshare — private homebrew-sharing BT pool 2026-05-15 20:32:26 -04:00
README.md README: privacy note about IP exposure + recommend gateway + encrypt 2026-05-15 20:53:15 -04:00

hbshare

A private BitTorrent pool for sharing homebrew between trusted peers.

Intended use. hbshare is for sharing homebrew applications, content you have authored, and other files you have the legal right to distribute, between members of a private invite-only pool. It is not intended for, and must not be used to distribute, copyrighted material you do not own or are not licensed to redistribute. You are responsible for what you choose to put in your share roots.

Privacy. Like every BitTorrent client, hbshare exposes your IP address to other peers in the swarm and to the BT mainline DHT — this is intrinsic to the protocol, not a bug. The salted infohash hides what you are sharing from outsiders, but anyone you peer with sees who (i.e. your IP). If that matters to you, run hbshare behind a gateway you control — a VPN, a small VPS, or a WireGuard tunnel — so the gateway's address is what appears to peers and on the DHT, not your home IP. And since pool membership is a discovery filter rather than a real security boundary, encrypt data you care about before putting it in share_roots, and only share the POOL_SECRET with people you actually trust.

Every item in share_roots becomes a torrent whose info-hash is salted with POOL_SECRET (info["source"] = POOL_SECRET — the private-tracker trick) so it never collides with public BT swarms of the same content. Pool members find each other on the BT mainline DHT under SHA-1("hbshare-pool:" + POOL_SECRET + ":members"); non-members can't compute that key.

Originally written for jailbroken PS5 homebrew sharing, but builds and runs unmodified on Linux — the same binary architecture works for sharing homebrew, ROMs you own, indie game builds, or any other content between trusted peers.

What it does, end to end

   share_roots/
     ├─ MyHomebrew/sce_sys/param.json   ── auto-share scan picks it up
     └─ MyHomebrew.torrent              ── hash once, cached forever
              │
              ▼
   libtransmission.tr_torrentNew + .Start + .Verify
              │
              ▼
   announces on the DHT under its salted infohash
              │
              ▼
   peer-A.hbshare is also announcing on `pool_member_key`
              │
              ▼
   our pool_member_search_loop dht_search'es that key → peer-A's IP
              │
              ▼
   peer_catalog_refresh_loop fetches peer-A:port/api/share + /api/settings
              │
              ▼
   handle_gallery merges peer-A's items into ours (dedupe-by-infohash,
   firmwares array per item) — the unified pool catalog

Key knobs

  • POOL_SECRET — #define at the top of src/main.cpp. Change + rebuild to fork a new pool. Every torrent's infohash and the pool membership key derive from this.
  • Settings.firmware — auto-detected via kernel_get_fw_version() on PS5, falls back to /etc/os-release on Linux. Stamped onto every torrent we create and merged into peers' cards.
  • 4 MB piece size on new torrents — fewer hashes on initial publish, still good swarm dynamics.

PS5 build

source /opt/ps5-payload-sdk/toolchain/prospero.sh
make
# → hbshare.elf (~15 MB)

Depends on the pacbrew prebuilt sysroot having libtransmission. If it isn't there, scripts/build-libtransmission.sh rebuilds it (applies the 16 MB pthread-stack patch to session-thread.cc that PS5 needs).

Deploy

nc -q 9999 <ps5-ip> 9021 < hbshare.elf

Opens the gallery at http://<ps5-ip>:8067/ — POOL_SECRET is substituted into the served HTML so the browser auto-authenticates without a prompt.

Linux / desktop build

hbshare builds natively on Linux/macOS too — same source, two Makefiles. The Linux build uses libtransmission's full internal API (so it can create torrents from local content the same way the PS5 does).

# one-time: fetch + build libtransmission 4.0.6 from source
sudo apt install build-essential cmake pkg-config \
  libmicrohttpd-dev libcurl4-openssl-dev libjson-c-dev libarchive-dev \
  libssl-dev libb64-dev libdeflate-dev libevent-dev zlib1g-dev \
  libzstd-dev libpsl-dev libminiupnpc-dev libnatpmp-dev
./scripts/build-libtransmission-linux.sh

# then any time you want to rebuild hbshare itself:
make -f Makefile.linux        # → hbshare-linux (~5 MB)

Why source-build libtransmission? Debian's libtransmission-dev ships only the 24 public-API headers; hbshare needs the internal C++ classes (tr_metainfo_builder, tr_torrent_metainfo) for creating salted torrents.

State directory on Linux: $HOME/.hbshare/ (overridable via the Makefile's HBSHARE_DIR define).

Settings (/data/hbshare/settings.ini on PS5, ~/.hbshare/settings.ini on Linux)

Auto-generated on first boot with sane defaults. Editable knobs:

Key Default Notes
port 8067 HTTP port for the gallery + API
download_dir /data/homebrew Where downloads land (also a share root → re-seeds automatically)
auto_share_scan true Hash + seed everything in share_roots on boot
dht_enabled true Mainline BT DHT
utp_enabled true µTP NAT hole-punching for unforwarded peers
pex_enabled true Peer exchange
lpd_enabled true Local-network peer discovery
firmware auto Override if firmware autodetect returns wrong format
trackers five public UDP trackers Baked into magnets for swarm-bootstrap

pool_secret is not here — it's compiled in.

API surface

Verb Path Auth Purpose
GET / none Gallery HTML (with embedded POOL_SECRET)
GET /api/gallery Bearer Merged catalog (local + peers via DHT discovery)
GET /api/list Bearer Active torrents + per-torrent stats
GET /api/share Bearer Local content eligible for seeding
GET /api/seed/jobs Bearer Hash-job progress (boot-time auto-scan)
GET /api/settings Bearer Current settings incl. firmware
GET /api/icon, /api/meta/icon public Cover art (<img> can't send Bearer)
POST /api/add Bearer Body: source=<magnet>
POST /api/seed Bearer Body: path=/... — hash + seed a local item
POST /api/remove Bearer Body: id=<n>&delete_files=0|1
POST /api/settings Bearer Update settings.ini
POST /api/gallery/import Bearer Import a peer's exported gallery.json
POST /api/pool/inject Bearer Debug: add a peer to the discovery table by hand

Limitations

  • First publish of a 100 GB item costs ~8 min of disk reading + SHA-1. Cached forever after; later peers inherit hashes via BEP-9.
  • Pool needs ≥ 1 forwarded peer: same as any BT swarm. With one forwarded anchor, µTP hole-punches everyone else through.
  • Self-loop transfers (same-PS5 client and server) stall at ~48 KB due to a SceNet send-buffer interaction. Not an issue for real cross-host transfers.