- C++ 67.7%
- HTML 27.9%
- Shell 3.7%
- Makefile 0.7%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| scripts | ||
| src | ||
| .gitignore | ||
| gallery.html | ||
| LICENSE | ||
| Makefile | ||
| Makefile.linux | ||
| README.md | ||
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 thePOOL_SECRETwith 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—#defineat the top ofsrc/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 viakernel_get_fw_version()on PS5, falls back to/etc/os-releaseon 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.