IrohBeam

IrohBeam embeds Iroh in Elixir applications as a small, supervised, authenticated QUIC transport. Peers dial stable key-derived endpoint IDs while Iroh handles changing IP paths, hole punching, and relays.

{:ok, endpoint} =
IrohBeam.Endpoint.start_link(
identity: {:file, "data/iroh.identity"},
alpns: ["my-app/1"],
network: :n0
)
peer_id = IrohBeam.EndpointId.parse!(System.fetch_env!("PEER_ID"))
{:ok, connection} = IrohBeam.Endpoint.connect(endpoint, peer_id, "my-app/1")
{:ok, stream} = IrohBeam.Connection.open_bi(connection)
:ok = IrohBeam.Stream.send(stream, "hello")
:ok = IrohBeam.Stream.finish(stream)
{:ok, reply} = IrohBeam.Stream.recv(stream, 64 * 1024)

IrohBeam also provides an optional OTP 29 Erlang distribution carrier. It uses Iroh as the authenticated byte transport while OTP retains cookies, the distribution handshake and encoding, RPC, links, monitors, ticks, and node lifecycle:

{:ok, _net_kernel} =
IrohBeam.Distribution.start(
name: :"api@east",
identity: {:file, "data/api.iroh"},
network: :n0,
peers: %{
:"worker@west" =>
{:id, System.fetch_env!("WORKER_IROH_ID")}
}
)
true = Node.connect(:"worker@west")
:pong = Node.ping(:"worker@west")

Launch an unnamed dynamic node with elixir --erl "-proto_dist iroh -no_epmd" .... Static peer configuration is exact and immutable while running. IrohBeam does not provide membership, automatic topology, service discovery, auto-connect, partition healing, or a libcluster strategy.

Every live endpoint or distribution VM has a distinct private key. Share public IDs, addresses, tickets, relay policy, and separately managed Erlang cookies—not one group private key.

Installation

def deps do
[
{:iroh_beam, "~> 0.2.0"}
]
end

Supported precompiled NIF 2.16 targets:

A clean supported consumer downloads a verified archive and does not invoke Cargo. Source builds require Rust 1.91.0; set IROH_BEAM_BUILD=1 to force one. The general transport requires Elixir ~> 1.20 and NIF 2.16 support. The optional distribution carrier is explicitly supported on OTP 29.x only.

Network profiles

ID-only dialing needs lookup. Direct/custom deployments normally share an IrohBeam.EndpointAddr or standard IrohBeam.EndpointTicket, or configure a static address. Distribution uses the same target values in its exact peer map.

Bounded transport and distribution

Connections expose authenticated remote IDs, negotiated ALPN, admission, selected path, streams, datagrams, and deterministic close. Receives always require a positive byte limit. Writes honor QUIC flow control; there is no unbounded native queue. One operation may mutate each stream half while send and receive remain concurrent.

Distribution keeps one native read and one flow-controlled write in flight per link. It validates packet-four frame lengths before retaining bodies, rejects unknown endpoint IDs and node/key mismatches before OTP, keeps normal cookies, and does not use EPMD or a local TCP tunnel.

See the guides for identity, endpoints, connections, streams, native distribution, private relays, security, telemetry, and troubleshooting. The optional two-machine transport example and two-machine distribution example distinguish physical-network smoke workflows from automated local proofs.

Development

The project pins Iroh 1.0.3, iroh-tickets1.0.0, Rustler 0.38.0, Rust 1.91.0, OTP 29.x for distribution, and NIF 2.16. It has no dependency on a sibling Iroh checkout.

mix deps.get
docker compose up -d iroh-relay
bin/qa_check.sh
docker compose down --volumes --remove-orphans

License

IrohBeam is MIT licensed. Iroh and Rustler retain their MIT/Apache-2.0 terms; see NOTICE.