How to Set Up an iroh Network: A Complete Guide
To set up an iroh network, deploy an iroh-relay server for NAT traversal fallback, configure each peer with an Endpoint pointing to the relay, and optionally run an iroh-dns-server for human-readable addressing.
Setting up an iroh network involves configuring the distributed infrastructure that enables peer-to-peer connectivity through NAT traversal and encrypted QUIC streams. The n0-computer/iroh repository provides the necessary binaries and libraries to establish this connectivity with minimal boilerplate. This guide walks through deploying the required relay infrastructure, initializing client endpoints, and optionally configuring DNS resolution for production deployments.
Architecture Overview
An iroh network consists of three distinct components that work together to provide seamless peer-to-peer connectivity:
- iroh-relay – A publicly accessible server that forwards encrypted packets when direct connections fail due to strict NATs or firewalls.
- Endpoint – The client-side abstraction (created via the
irohcrate) that handles key generation, hole-punching, and protocol multiplexing. - iroh-dns-server (optional) – A DNS service that resolves PKARR records, enabling human-readable addressing like
endpoint-id.iroh.link.
Deploying the iroh-relay Server
The iroh-relay is the only mandatory infrastructure component. It exposes an HTTP API on port 3340 for client registration and can optionally provide QUIC address discovery on port 7824.
Development Mode
For local testing, run the relay in development mode without TLS:
cargo run --features="server" --bin iroh-relay -- --dev
This command compiles and starts the relay with permissive settings suitable for testing. According to the iroh-relay/README.md, the --dev flag disables certificate validation and enables plain HTTP communication.
Production Configuration
For production deployments, configure access control via a TOML configuration file:
# config.toml
access = "everyone"
The access field supports allow-lists, deny-lists, or shared-token schemes for restricting which endpoint IDs can utilize the relay. Refer to the access control documentation in iroh-relay/README.md for production-hardening options.
Creating an Endpoint in Rust
Each participant in the network creates an Endpoint using the iroh crate. The endpoint automatically generates a permanent EndpointId (a cryptographic public key) and manages the connection lifecycle.
Basic Endpoint Setup
The following example, adapted from iroh/examples/connect.rs, demonstrates the minimal code required to join an iroh network:
use iroh::endpoint::Endpoint;
use iroh::relay::RelayMap;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Create a local endpoint with a persistent EndpointId
let endpoint = Endpoint::bind().await?;
// Configure the relay for fallback connectivity
let relay_cfg = RelayMap::default()
.with_url("http://localhost:3340".parse()?);
endpoint.set_relay_map(relay_cfg).await?;
// Connect to a remote peer using their EndpointId
let remote_id: iroh::EndpointId = "iroh:...".parse()?;
let conn = endpoint
.connect(remote_id, b"my-proto/0.1")
.await?;
// Open a bidirectional QUIC stream
let (mut send, mut recv) = conn.open_bi().await?;
send.write_all(b"hello iroh").await?;
send.finish()?;
let reply = recv.read_to_end(1024).await?;
println!("reply: {}", String::from_utf8_lossy(&reply));
Ok(())
}
Key Methods and Files
The implementation relies on several core components defined in the source tree:
Endpoint::bind()(defined iniroh/src/lib.rs) – Creates a UDP/QUIC socket and persists the endpoint ID to$XDG_DATA_HOME/iroh/endpoint-id.RelayMap::default()(fromiroh-base/src/relay_url.rs) – Constructs a relay configuration supporting multiple URLs for redundancy.set_relay_map()– Registers the relay configuration with the endpoint, enabling fallback when direct hole-punching fails.
Optional DNS and PKARR Resolution
While peers can connect directly using raw EndpointId strings, the iroh-dns-server provides human-readable addressing through PKARR (Public Key Addressable Resource Records).
Running the DNS Server
Start the DNS server with PKARR support enabled:
cargo run --bin iroh-dns-server -- --config-path=example-dns.toml
Configuration requires enabling the PKARR service in the TOML file:
listen = "0.0.0.0:53"
pkarr = true
With this service running, peers resolve addresses like endpoint-id.iroh.link to their current QUIC sockets without exchanging raw UDP information. See iroh-dns-server/README.md for zone configuration and forwarding rules.
Address Resolution Types
The system supports multiple address types defined in iroh-base/src/endpoint_addr.rs, including raw UDP sockets, QUIC addresses, and PKARR DNS records.
Complete Working Example
To establish a functional iroh network:
- Start the relay infrastructure using either development mode (
--dev) or a production configuration with TLS certificates. - Initialize peer endpoints by calling
Endpoint::bind()and configuring theRelayMapwith your relay URL. - Exchange EndpointIds either out-of-band or via the DNS server if deployed.
- Establish connections using
endpoint.connect()with an ALPN protocol identifier (e.g.,b"my-proto/0.1"), which enables protocol multiplexing over single connections.
The iroh/examples/echo.rs file provides a complete client-server demonstration showing bidirectional stream handling, while iroh/examples/transfer.rs illustrates file transmission over custom protocols.
Summary
- Deploy iroh-relay – The only required infrastructure component for NAT traversal fallback and connectivity between restricted peers.
- Configure Endpoint – Use
Endpoint::bind()andset_relay_map()in Rust applications to join the network with automatic hole-punching. - Optional DNS – Run iroh-dns-server to enable PKARR-based human-readable addressing (
*.iroh.link). - Core Implementation – All networking logic resides in
iroh/src/lib.rs, with type definitions iniroh-baseforRelayUrland endpoint addressing.
Frequently Asked Questions
What infrastructure is required to set up an iroh network?
The minimum requirement is a single iroh-relay server. This binary handles NAT traversal and packet forwarding when direct connections fail. While optional, the iroh-dns-server simplifies peer discovery by mapping endpoint IDs to DNS names. No central coordinator or blockchain is required for basic operation.
Can I run an iroh network without a relay?
While possible on local networks with unrestricted UDP, the relay is essential for production deployments where peers reside behind corporate firewalls or symmetric NATs. The relay acts as a fallback path when hole-punching fails, ensuring connectivity in approximately 95% of network topologies.
How does the EndpointId persist between application restarts?
The Endpoint::bind() method automatically generates and stores the EndpointId (Ed25519 public key) in the platform-specific data directory ($XDG_DATA_HOME/iroh/endpoint-id on Linux). Subsequent calls to bind() load this identity, maintaining stable addressing across process lifecycles.
What is the difference between RelayMap and direct addressing?
RelayMap configures fallback servers for when direct UDP connectivity fails, while direct addressing (specifying an IP and port) attempts immediate connection. The endpoint always attempts direct hole-punching first; the relay map only activates after direct attempts timeout, ensuring optimal performance.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →