A self-contained package that turns an ordinary machine (an old laptop is enough) into a censorship-resistant Blurt RPC node, reachable over Tor (.onion v3) and I2P (.b32.i2p) — with no public IP, no port-forward, no DNS, no registrar, and no hosting company.
  • Shell 87.6%
  • Python 12.4%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-08-26 10:54:27 -07:00
config hidden-rpc v0.1.5 2026-08-13 22:24:02 -07:00
docs hidden-rpc v0.1.14 2026-08-23 23:22:05 -07:00
installer hidden-rpc v0.1.17 2026-08-26 10:54:27 -07:00
.gitignore hidden-rpc v0.1.0 — one-command private Blurt RPC node (Tor + I2P) 2026-08-13 17:52:24 -07:00
LICENSE hidden-rpc v0.1.0 — one-command private Blurt RPC node (Tor + I2P) 2026-08-13 17:52:24 -07:00
README.md hidden-rpc v0.1.14 2026-08-23 23:22:05 -07:00
RELEASE-NOTES.md hidden-rpc v0.1.17 2026-08-26 10:54:27 -07:00
release.sh hidden-rpc v0.1.5 2026-08-13 22:24:02 -07:00
VERSION hidden-rpc v0.1.17 2026-08-26 10:54:27 -07:00

hidden-rpc

A self-contained package that turns an ordinary machine (an old laptop is enough) into a censorship-resistant Blurt RPC node, reachable over Tor (.onion v3) and I2P (.b32.i2p) — with no public IP, no port-forward, no DNS, no registrar, and no hosting company.

It bundles a full blurtd + a hidden-service transport layer + grandma-friendly operator tooling, so any Blurt RPC admin can stand up a node on hardware they already own.

  • Home: git.agorise.net/agorise/hidden-rpc (Forgejo)
  • License: AGPL-3.0-or-later
  • Status: Phase 0 (scaffold). See docs/ROADMAP.md.

What this is — and what it is NOT

It is

A packaging/transport/tooling layer that wraps existing upstreams. It does not fork or re-implement blurtd (or, later, Nexus) — it consumes them as upstream dependencies and adds the value on top: self-authenticating hidden-service reachability, JSON-RPC batch support, and one-command operator setup that stays calm on flaky home hardware.

Wrap, don't fork. If we ever find ourselves patching blurtd internals, we've taken a wrong turn. Fixes to the chain node go upstream; this repo owns the layer around it.

It is NOT

  • Not a witness / block-production tool. p2p block gossip over Tor is latency-sensitive and chain-wide — out of scope. (A witness may also expose their RPC as .onion with this package; that's fine. Block production over Tor is not.)
  • Not a naming/addressing system. No vanity .i2p addressbook, no .loki/LNS. RPC endpoints are machine-to-machine — nobody types them — so memorability buys nothing while re-introducing a naming-trust dependency. We support only raw .onion v3 + .b32.i2p, both of which are self-authenticating (the address is the key hash) and therefore strictly stronger than clearnet + TLS + DNS.
  • Not a trust layer. This package makes a trustworthy-transport node. Whether a given node's answers are true is a separate problem solved by the reader (see below).

The trust caveat (load-bearing — read this)

Tor/I2P hide where you read, not whether what you read is true.

Reaching a node over a hidden service tells you nothing about the honesty of its data. Cross- checking and quorum — racing the same call at several independent nodes and requiring them to agree before trusting a head block or balance — is the reader's responsibility. In the Agorise stack that reader is Morphit, which implements race + quorum as a parallel track in its own repo.

Nothing in this package's docs or output should ever imply that reaching a node means trusting its data. If you catch such an implication, it's a bug.

Local blurtd is still the gold standard. The strongest reader runs its own blurtd and reads localhost. This package's hidden-RPC tier is the fallback for readers too small to hold the chain, or for onion-only / locked-down environments.


Relationship to Morphit

hidden-rpc is a separate project from Morphit, with a different audience (all Blurt RPC admins, not only Morphit operators) and an independent release cadence.

  • Morphit consumes these nodes. It reads the chain through them and publishes the on-chain directory (morphit_rpc_v1, signed by @morphit) that lists them.
  • Morphit does not own this software. This repo does not know about the marketplace; it just exposes a chain node over a hidden service and emits its address in a form Morphit's registration tooling can pick up.
  • The morphit_rpc_v1 op is defined and broadcast in the Morphit repo, not here.

Why "outbound-only" is the whole point

Hidden services dial out. There is no inbound connection to accept, so there is no public IP to obtain, no port to forward, no registrar to satisfy, and no CGNAT/ISP-NAT problem. A laptop behind a typical home router — or behind carrier-grade NAT — can serve RPC to the world without any cooperation from the ISP.


Flaky by design

Laptops sleep; home internet flaps. Per-node uptime is not the goal — the union of nodes being reachable is. We do not engineer per-node high-availability. We engineer for trivial add/remove of nodes and clean "just doesn't answer" failure. (Morphit's race + failover handles the consumer side.)


Repository layout

hidden-rpc/
├── README.md            ← you are here
├── LICENSE              ← AGPL-3.0-or-later
├── VERSION              ← current release version (used by release.sh)
├── RELEASE-NOTES.md     ← notes for the current release
├── release.sh           ← maintainer: one-command publish to Forgejo
├── config/
│   ├── config.ini              ← ready-to-use: upstream config, webserver bound to loopback
│   └── rpc-config.upstream.ini ← Blurt-published config, verbatim (provenance)
├── installer/
│   ├── hidden-rpc-setup.sh     ← one-command auto-installer (Phase 2; first run = Phase 1 proof)
│   └── README.md               ← installer usage
└── docs/
    ├── ROADMAP.md       ← build order, phases 06
    ├── DECISIONS.md     ← settled + open decisions log
    ├── GAPS.md          ← gap analysis of the upstream setup instructions
    └── MANUAL-SETUP.md  ← Phase 1: the one-laptop proof, reproducible by hand

Current status & next step

Released and running. The one-command installer (installer/hidden-rpc-setup.sh) is the canonical setup — by default it trustlessly bootstraps the chain from a signed on-chain pointer (chain_snapshot_v1 by @morphit): it fetches the block_log (IPFS, mirror fallback), verifies its SHA-256, places Blurt's genesis file, and replays every block. It binds the RPC to loopback, stands up the Tor and I2P hidden services, and prints the node's two addresses. It's idempotent, self-cleaning, and survives reboots. A --trusted-state opt-in sets up fast from a presynced state snapshot (you trust its publisher). Three nodes are live over both networks.

./installer/hidden-rpc-setup.sh

For how it works under the hood (and the manual equivalent), see docs/MANUAL-SETUP.md. The reasoning and the resolved unknowns are in docs/DECISIONS.md; the roadmap and what's left (Nexus, Morphit handoff) are in docs/ROADMAP.md.