Run your own Blossom storage with Tor when you need easy private reachability, or use your own HTTPS setup when you do not.
Wildbloom Node is a small, cross-platform Blossom server. It stores blobs on your disk by SHA-256 and accepts only tightly scoped Nostr authorisation. Tor is an optional transport, not a storage requirement. The same node can use a persistent Tor v3 onion, stay local-only, or sit behind an operator-managed HTTPS reverse proxy. It does not use WebRTC, STUN or TURN.
This is a production candidate, not a durability promise. The headless node targets macOS, Linux and Windows. The native tray application lets the operator choose Tor or direct mode. It bundles a signature-verified Tor Expert Bundle for the Tor choice, but does not start it in direct mode. Unsigned preview installers are built separately from production releases; we will not label them as trusted downloads until the platform signing and clean-machine acceptance gates pass.
A fresh desktop install waits for the operator to choose a transport before it starts either process. Existing saved settings continue to select Tor unless the operator changes them.
Blossom gives Nostr applications a sensible content-addressed storage protocol, but using somebody else's server is still using somebody else's disk. They can lose it, remove it or stop paying the bill. Wildbloom Node makes a user's own machine a standard Blossom server and lets another authorised node copy the blob through BUD-04.
It is not a torrent client. Every replica currently stores a complete blob and serves it over ordinary Blossom HTTP. Nostr can carry private storage offers and replication intent; Tor or direct HTTPS carries the bytes. A separate QUIC and opaque-relay lane is a future spike, not part of the durability claim. RelaySwarm's WebRTC session remains for live browser media rather than storage.
- BUD-01
GETandHEAD, optional file extensions and single byte ranges. - BUD-02 streaming
PUT /uploadwithContent-LengthandX-SHA-256. - BUD-04
PUT /mirrorfrom hash-addressed onion origins through the private Tor SOCKS listener, or from public HTTPS origins through direct mode. - BUD-06 authorised upload preflight with quota and per-blob checks.
- Strict BUD-11 kind
24242signature, operation, hash, server and expiry checks. - Authenticated, self-only BUD-12 listing with bounded cursor pagination, plus claim-aware deletion. One signer cannot list or delete another signer's claims.
- Persistent SQLite metadata and a disk content-addressed store.
- Pre-stream global quota reservation, per-blob limits, deduplication and interrupted-upload cleanup.
- Deny-by-default writes, bounded concurrent streams, complete integrity scans and repair from previously verified mirror sources.
- Claim-aware owner, friend and guest retention over one deduplicated CAS. Friends have expiring per-key byte ceilings; signed guest mirrors use only spare capacity and are evicted first.
- Opaque attachment serving for friend-only and guest-only blobs, including
nosniff; conflicting owner MIME claims also fail opaque. - Crash reconciliation restores indexed tombstones and removes unindexed files left by interrupted file/database transactions.
- Loopback-only binding by default, with a persistent Tor v3 onion or an operator-supplied HTTPS origin.
- Native Rust and Tauri compile CI configured for macOS, Linux and Windows.
- A native Tauri tray shell with platform data directories, start-at-login, storage status and no private-key input.
- Installed
.deband NSIS preview acceptance on fresh hosted Linux and Windows runners, including Tor bootstrap, Blossom health, single-instance behaviour, child cleanup and uninstall.
There is no proof-of-storage protocol, paid quota or automatic discovery of strangers willing to hold data. Repair can restore a damaged local copy only when the node already recorded a verified source which is still online. Those boundaries are documented in the roadmap.
The storage priority contract defines the exact admission and eviction promises. The implementation and adversarial local tests are present; cross-platform CI and the independent V4V recovery journey remain release evidence rather than assumptions.
The desktop application is the intended consumer install. Until signed installers are published, build it only from a revision you have reviewed.
Install Rust 1.94.1, the platform's normal Tauri 2 build prerequisites, GnuPG and the Tauri CLI. Choose the matching target and Tor bundle name:
| System | Rust target | Tor bundle name |
|---|---|---|
| Windows x64 | x86_64-pc-windows-msvc |
windows-x86_64 |
| Linux x64 | x86_64-unknown-linux-gnu |
linux-x86_64 |
| macOS Apple Silicon | aarch64-apple-darwin |
macos-aarch64 |
| macOS Intel | x86_64-apple-darwin |
macos-x86_64 |
From a fresh clone, replace the two values below with that row:
cargo install tauri-cli --version 2.11.4 --locked
scripts/prepare-tor-runtime.sh <tor-bundle-name> desktop/src-tauri/tor-runtime
cargo build --locked --release --target <rust-target> -p wildbloomd
cp target/<rust-target>/release/wildbloomd desktop/src-tauri/binaries/wildbloomd-<rust-target>
# On macOS only: scripts/sign-macos-tor-runtime.sh - desktop/src-tauri/tor-runtime
cd desktop/src-tauri
cargo tauri build --target <rust-target>On Windows, both daemon paths end in .exe. This produces an explicitly
unsigned preview. The verified Tor runtime is bundled as a complete resource,
not fetched on first start. Production signing and updater artefacts are made
only by the fail-closed release workflow described in the release process.
Linux desktop releases use native .deb and .rpm packages; the headless
daemon can be built as an ordinary binary on other Linux distributions. Both
packages have detached release signatures; Linux updates are explicit package
installs rather than an AppImage replacement dressed up as an auto-update.
The headless path needs Rust 1.94.1
or later. Tor mode additionally needs a current
Tor Expert Bundle, with the tor
executable on PATH.
git clone https://github.com/forgesworn/wildbloom-node.git
cd wildbloom-node
cargo build --release
./target/release/wildbloomd --allow-pubkey <64-lower-case-hex-public-key>The first Tor bootstrap can take several minutes and has a fifteen-minute
allowance; later starts reuse its private directory cache. Once ready, the log
prints the stable .onion Blossom URL. Add that URL to a Blossom-capable client. The
node stores data in the operating system's per-user application-data directory
unless --data-dir or WILDBLOOM_DATA_DIR says otherwise. Without an owner,
friend grant or explicit open-shelter policy it remains read-only.
For a supported local-only node without Tor, keep the same explicit owner authority:
cargo run -p wildbloomd -- --no-tor --allow-pubkey <64-lower-case-hex-public-key>For an internet-facing direct node, keep wildbloomd on loopback, terminate
TLS in a hardened reverse proxy on the same host and give the daemon that exact
public origin. Direct public-HTTPS mirroring and repair must be selected
explicitly:
cargo run -p wildbloomd -- \
--no-tor \
--public-url https://blossom.example \
--direct-https-mirrors \
--allow-pubkey <64-lower-case-hex-public-key>Direct mode reveals ordinary client and server network metadata. It does not configure DNS, TLS, a firewall, NAT traversal or a router. Plain public HTTP origins are refused; only loopback and onion origins may use HTTP.
Useful controls:
--quota-bytes <BYTES> total stored blob quota, default 10 GiB
--max-blob-bytes <BYTES> maximum single blob, default 1 GiB
--allow-pubkey <HEX> owner public key, repeatable
--friend-grant <P:L:E> friend pubkey, byte limit and Unix expiry
--open-shelter admit unknown signed mirrors as guest data
--max-concurrent-writes <N> concurrent upload/mirror limit, default 4
--repair-interval <SECONDS> integrity and repair interval, default 3600
--verify-storage verify every stored byte and exit
--bind <IP:PORT> local listener, default 127.0.0.1:3742
--tor-bin <PATH> Tor executable, default tor
--no-tor do not start managed Tor
--direct-https-mirrors fetch public HTTPS mirrors directly
Do not put the local listener on the public internet merely because the flag exists. If a conventional HTTPS reverse proxy is genuinely required, read the threat model first.
Applications use the selected onion, HTTPS or local URL exactly as they use another Blossom server:
- Hash the exact bytes with SHA-256.
- Sign a short-lived kind
24242uploadevent for that hash and this node's exact hostname. PUT /uploadwith the event inAuthorization: Nostr <base64url-event>.- Keep the returned descriptor URL or publish it through the application's normal Nostr records.
- To add another replica, sign for the destination node and call its
PUT /mirrorwith the source descriptor URL.
An operator may add an invited key with
--friend-grant <pubkey>:<byte-limit>:<expires-at>. --open-shelter is a
separate, explicit policy: unknown keys may submit signed BUD-04 mirrors when
the high free-space watermark remains intact, but they still cannot upload
directly and receive no retention promise.
Wildbloom's browser app keeps encryption client-side, so a node stores ciphertext rather than plaintext. See the exact protocol and trust boundaries and the V4V dogfood path.
cargo fmt --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace
scripts/audit-dependencies.shSecurity issues should follow SECURITY.md. Contributions are welcome under the MIT licence. Desktop packages also retain the exact upstream licences for their signature-verified Tor runtime; see third-party notices.
If this is useful, sponsor TheCryptoDonkey on GitHub, support BRAYs on Ko-fi, or back ForgeSworn on Geyser.