iroh Documentation

IP addresses break, dial keys instead. A library that adds QUIC + NAT Traversal to your apps.

RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy iroh on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name iroh -p 80:80 --restart always n0-computer/iroh:latest

Technical Documentation: n0-computer/iroh

ℹ️ Provenance: Multi-Tier Ingestion Β· CodeWiki Reference

Overview (`README.md`)

[](https://iroh.computer)

less net work for networks








What is iroh?

Iroh gives you an API for dialing by public key.
You say β€œconnect to that phone”, iroh will find & maintain the fastest connection for you, regardless of where it is.

Hole-punching

The fastest route is a direct connection, so if necessary, iroh tries to hole-punch.
Should this fail, it can fall back to an open ecosystem of public relay servers.
To ensure these connections are as fast as possible, we continuously measure iroh.

Built on [QUIC]

Iroh uses noq to establish QUIC connections between endpoints.
This way you get authenticated encryption, concurrent streams with stream priorities, a datagram transport and avoid head-of-line-blocking out of the box.

Compose Protocols

Use pre-existing protocols built on iroh instead of writing your own:

  • iroh-blobs for BLAKE3-based content-addressed blob transfer scaling from kilobytes to terabytes
  • iroh-gossip for establishing publish-subscribe overlay networks that scale, requiring only resources that your average phone can handle
  • iroh-docs for an eventually-consistent key-value store of iroh-blobs blobs

Getting Started

Rust Library

It's easiest to use iroh from rust.
Install it using cargo add iroh, then on the connecting side:

rs
const ALPN: &[u8] = b"iroh-example/echo/0";

let endpoint = Endpoint::bind().await?;

// Open a connection to the accepting endpoint
let conn = endpoint.connect(addr, ALPN).await?;

// Open a bidirectional QUIC stream
let (mut send, mut recv) = conn.open_bi().await?;

// Send some data to be echoed
send.write_all(b"Hello, world!").await?;
send.finish()?;

// Receive the echo
let response = recv.read_to_end(1000).await?;
assert_eq!(&response, b"Hello, world!");

// As the side receiving the last application data - say goodbye
conn.close(0u32.into(), b"bye!");

// Close the endpoint and all its connections
endpoint.close().await;

And on the accepting side:

rs
let endpoint = Endpoint::bind().await?;

let router = Router::builder(endpoint)
    .accept(ALPN.to_vec(), Arc::new(Echo))
    .spawn()
    .await?;

// The protocol definition:
#[derive(Debug, Clone)]
struct Echo;

impl ProtocolHandler for Echo {
    async fn accept(&self, connection: Connection) -> Result<()> {
        let (mut send, mut recv) = connection.accept_bi().await?;

        // Echo any bytes received back directly.
        let bytes_sent = tokio::io::copy(&mut recv, &mut send).await?;

        send.finish()?;
        connection.closed().await;

        Ok(())
    }
}

The full example code with more comments can be found at echo.rs.

Or use one of the pre-existing protocols, e.g. iroh-blobs or iroh-gossip.

Other Languages

If you want to use iroh from other languages, make sure to check out iroh-ffi, the repository for FFI bindings.

Repository Structure

This repository contains a workspace of crates:

  • iroh: The core library for hole-punching & communicating with relays.
  • iroh-relay: The relay client and server implementation. This is the code we run in production for the public relays (and you can, too!).
  • iroh-base: Common types like EndpointId or RelayUrl.
  • iroh-dns-server: DNS server implementation powering the DNS/Pkarr address lookup for EndpointIds, running at dns.iroh.link.

License

Copyright 2025 N0, INC.

This project is licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.


Overview (`docker/README.md`)

Iroh Docker Images

Intro

A set of docker images provided to easily run iroh in a containerized environment.
Features iroh-relay and iroh-dns-server.

The provided Docker files are intended for CI use but can be also manually built.

Building

  • All commands are run from the root folder
  • If you're on macOS run docker buildx build -f docker/Dockerfile --target iroh-relay --platform linux/arm64/v8 --tag n0computer/iroh-relay:latest .
  • If you're on linux run docker buildx build -f docker/Dockerfile --target iroh-relay --platform linux/amd64 --tag n0computer/iroh-relay:latest .
  • Switch out --target iroh-relay for iroh-dns-server

Running

iroh-relay

  • Provide a config file: docker run -v /path/to/iroh-relay.conf:/config/iroh-relay.conf -p 80:80 -p 443:443 -p 3478:3478/udp -p 9090:9090 -it n0computer/iroh-relay:latest --config /config/iroh-relay.conf

iroh-dns-server

  • Provide a config file: docker run -v /path/to/iroh-dns-server.conf:/config/iroh-dns-server.conf -p 53:53/udp -p 9090:9090 -it n0computer/iroh-dns-server:latest --config /config/iroh-dns-server.conf

Overview (`iroh-base/README.md`)

iroh-base

This crate provides base types and utilities used throughout Iroh.

License

This project is licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in this project by you, as defined in the Apache-2.0 license,
shall be dual licensed as above, without any additional terms or conditions.


Overview (`iroh-dns-server/README.md`)

iroh-dns-server

A server that functions as a pkarr relay and
DNS server.

This server compiles to a binary iroh-dns-server. It needs a config file, of
which there are two examples included:

The server will expose the following services:

  • A DNS server listening on UDP and TCP for DNS queries
  • A HTTP and/or HTTPS server which provides the following routes:
    • /pkarr: GET and PUT for pkarr signed packets
    • /dns-query: Answer DNS queries over
      DNS-over-HTTPS

All received and valid pkarr signed packets will be served over DNS. The pkarr
packet origin will be appended with the origin as configured by this server.

License

This project is licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in this project by you, as defined in the Apache-2.0 license,
shall be dual licensed as above, without any additional terms or conditions.


Overview (`iroh-dns/README.md`)

iroh-dns

DNS-based endpoint discovery for Iroh.

This crate contains the core types for publishing and resolving iroh endpoint information via DNS, using the pkarr signed packet format.

License

This project is licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in this project by you, as defined in the Apache-2.0 license,
shall be dual licensed as above, without any additional terms or conditions.


Overview (`iroh-relay/README.md`)

Iroh Relay

Iroh's relay is a feature within iroh, a peer-to-peer networking system
designed to facilitate direct, encrypted connections between devices. Iroh aims
to simplify decentralized communication by automatically handling connections
through "relays" when direct connections aren't immediately possible. The relay
server helps establish connections by temporarily routing encrypted traffic
until a direct, P2P connection is feasible. Once this direct path is set up,
the relay server steps back, and the data flows directly between devices. This
approach allows Iroh to maintain a secure, low-latency connection, even in
challenging network situations.

This crate provides a complete setup for creating and interacting with iroh
relays, including:

  • Relay Protocol: The protocol used to communicate between relay servers and
    clients
  • Relay Server: A fully-fledged iroh-relay server over HTTP or HTTPS.
    Optionally will also expose a QAD endpoint and metrics.
  • Relay Client: A client for establishing connections to the relay.
  • Server Binary: A CLI for running your own relay server. It can be configured
    to also expose metrics.

Used in iroh, created with love by the n0 team.

Build the server

You can build an optimised release of iroh-relay by running cargo build
with the appropriate flags from the workspace parent directory as follows.

text
cd ../
cargo build \
  --profile optimized-release \
  --package iroh-relay \
  --features server

You will find the optimised binary at target/optimized-release/iroh-relay.

Access control

The relay server supports several access control modes, configured via the
access field in the TOML config file.

Allow everyone (default)

toml
access = "everyone"

Allowlist / Denylist by endpoint ID

toml
# Allow only specific endpoints
access.allowlist = ["<endpoint-id>", "<endpoint-id>"]

# Or block specific endpoints and allow everyone else
access.denylist = ["<endpoint-id>"]

Shared token (local, no external service)

Requires connecting clients to present one of the configured shared secrets via an
Authorization: Bearer <token> header, or a ?token= URL query parameter.

toml
access.shared_token = ["token-a", "token-b"]

The token list can also be overridden by the IROH_RELAY_ACCESS_TOKEN environment
variable, which sets a single allowed token and takes precedence over the config file
value. A single value is used (rather than a comma-separated list) to avoid restricting
the character set of tokens.

The token list must not be empty, and no token may be an empty string; the server will
fail to start if either condition is violated.

On the client side, set the token using
RelayConfig::with_auth_token
or
RelayMap::with_auth_token.

Note: this shared token does not support revocation other than updating the config and restarting the service.

HTTP callout (external auth service)

The relay calls an external HTTP endpoint for each incoming connection,
passing the connecting endpoint's ID. The token below authenticates the relay
to your auth service (machine-to-machine), not the connecting client.

toml
access.http.url = "https://your-auth-service.example.com/relay-auth"
# Optional: authenticate the relay's outbound request to your service
access.http.bearer_token = "service-to-service-secret"

The bearer token can also be set via the IROH_RELAY_HTTP_BEARER_TOKEN
environment variable.

For every connection, the relay sends a POST request with no body to
access.http.url. The connecting endpoint's ID is sent in the
X-Iroh-Endpoint-Id header. If a bearer token is configured, it is sent in an
Authorization: Bearer <token> header.

To allow the connection, your service must respond with status 200 and the
response body true.

Example request:

http
POST /relay-auth HTTP/1.1
x-iroh-endpoint-id: da1ee49ba54d124a2e2b0f043bac3d63ec086b0b40e7d0895914898b237e847e
x-iroh-nodeid: da1ee49ba54d124a2e2b0f043bac3d63ec086b0b40e7d0895914898b237e847e
authorization: Bearer service-to-service-secret
accept: */*
host: your-auth-service.example.com

Note: the endpoint ID is also sent in the deprecated X-Iroh-NodeId
header for backwards compatibility. It will be removed in a future release.
New services should use X-Iroh-Endpoint-Id.

Local testing

Advice for testing your application that uses iroh with a locally running iroh-relay server

dev mode

When running the relay server using the --dev flag, you will:

  • only run the server over http, not https
  • will NOT run the QUIC endpoint that enables QUIC address discovery

The relay can be contacted at "http://localhost:3340".

Both https and QUIC address discovery require TLS certificates. It's possible to run QUIC address discovery using locally generated TLS certificates, but it takes a few extra steps and so, is disabled by default for now.

dev mode with QUIC address discovery

So you want to test out QUIC address discovery locally?

In order to do that you need TLS certificates.

The easiest get that is to generate self-signed certificates using rcgen

  • get rcgen (git clone https://github.com/rustls/rcgen)
  • cd to the rcgen directory
  • generate local certs using cargo run -- -o path/to/certs

Next, add the certificate paths to your iroh-relay config, here is an example of a config.toml file that will enable quic address discovery.

toml
enable_quic_addr_discovery = true

[tls]
cert_mode = "Manual"
manual_cert_path = "/path/to/certs/cert.pem"
manual_key_path = "/path/to/certs/cert.key.pem"

Then run the server with the --dev flag, like you would when normally testing locally:
cargo run --features="server" --bin iroh-relay -- --config-path=/path/to/config.toml --dev

The relay server will run over http on port 3340, as it does using the --dev flag, but it will also run a QUIC server on port 7824.

The relay will use the configured TLS certificates for the QUIC connection, but use http (rather than https) for the server.

Using iroh-relay as a library to run in-process relays in integration tests

When using iroh as a transport library in an application or other library, there is a simple way of running an in-process relay server:

  • Enable test-utils feature of the iroh crate
toml
iroh = { version = "0.95", features = ["test-utils"] }
  • Spawn a relay server by calling iroh::test_utils::run_relay_server().await
    This will start a relay server with a self-signed TLS certificate, listening on a localhost port, and return the server's URL.
  • For the iroh endpoints to successfully connect to the relay, disable TLS certificate verification by calling Endpoint::ca_tls_config with CaRootConfig::insecure_skip_verify().

License

This project is licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in this project by you, as defined in the Apache-2.0 license,
shall be dual licensed as above, without any additional terms or conditions.


Overview (`iroh/README.md`)

less net work for networks






Iroh is a Rust library to establish direct connections between endpoints.
It gives you an API for dialing by public key. You say "connect to that
endpoint", and iroh finds and maintains the best connection for you.

Under the hood iroh establishes peer-to-peer QUIC connections between
endpoints. The fastest route is a direct connection, so iroh tries to
hole-punch one whenever it can. If that fails it falls back to using
relay servers.

Because iroh is built on QUIC, all connections are end-to-end encrypted and may
carry any number of concurrent streams. Dialing by public key also makes them mutually
authenticated, because each endpoint's public key is its TLS identity.

Overview

An iroh endpoint is created and controlled by the Endpoint. Each endpoint
has a unique SecretKey, whose public key is the endpoint's identity, the
EndpointId. Connections are authenticated against this key, which means an
EndpointId can't be impersonated.

A connection is usually established with the help of a relay server. When an
endpoint is created it connects to the closest relay and designates it as its
home relay. Other endpoints reach it first through this relay, then both
sides use QUIC NAT traversal to establish a direct connection. In the rare
cases where a direct connection is not possible, traffic keeps flowing over the
relay.

Relay servers only forward encrypted packets addressed to Endpoint IDs, they
cannot read any traffic between endpoints.

Endpoints can also connect directly without a relay, as long as the accepting
endpoint is directly reachable at one of its addresses.

To discover addressing information for an endpoint, iroh uses
address lookup services. With address lookup, you can connect to other
endpoints with only their EndpointId. Addressing information will then
be resolved on-demand.

The N0 preset installs the DNS/Pkarr address lookup service, which uses
servers hosted by n0 to provide global lookup for endpoints.

Example

This is an echo protocol: the accepting side copies back whatever it receives.
The full, commented version is in echo.rs.

text
/* Detailed source-code truncated for AI context efficiency. */

More examples live in iroh/examples. Run them with
cargo run --example NAME. Details for each are in the file itself.

Compose protocols

Instead of writing your own, you can build on protocols that already exist on
top of iroh:

  • iroh-blobs for BLAKE3-based content-addressed blob transfer, scaling from
    kilobytes to terabytes.
  • iroh-gossip for publish-subscribe overlay networks that scale down to what
    an average phone can handle.
  • and many more.

To use iroh from other languages, see iroh-ffi.

Development

For notes on iroh's structured events and how to build the documentation, see
DEVELOPMENT.md.

License

This project is licensed under either of

at your option.

Contribution

See CONTRIBUTING.md
for how to get involved.

Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in this project by you, as defined in the Apache-2.0 license,
shall be dual licensed as above, without any additional terms or conditions.


Iroh Docs Local Relays (`iroh/docs/local_relays.md`)

Using a local iroh-relay

It's easy to set up a iroh-relay that runs locally on your machine.

Using cargo:

shell
$ cargo run --bin iroh-relay --features="iroh-relay" -- --dev

This will bind the iroh-relay to [::]3340 and run it over HTTP.

To connect to this iroh-relay when doing your normal iroh commands, adjust the iroh configuration file to read:

toml
# iroh.config.toml:
[[relays]]
url = "http://localhost:3340"

If you want to give a specific port for the iroh-relay to bind to, you can create a iroh-relay config file and pass that file in using the --config_path flag. You need to retain a secret_key, so it is recommended to run iroh-relay --config-path [PATH] once to generate a secret key and save it to the config file before doing further edits to the file.

To change the port you want to listen on, change the port in the addr field:

text
# iroh-relay.toml

secret_key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
addr = "[::]:12345"
hostname = "my.relay.network"
enable_relay = true

Check the iroh-relay file's Config struct for documentation on each configuration field.

If you change the local iroh-relay server's configuration, however, be sure to adjust the associated fields in your iroh config as well.


Iroh Docs Relays (`iroh/docs/relays.md`)

Relays

When an Iroh endpoint starts up, it does a latency test to see which known relay endpoint it is β€œclosest to”. That relay server is considered the Iroh endpoint's home relay server.

An endpoint may be connected to multiple relay servers, but it will advertise its home relay endpoint as the one best used to hole-punch or relay packets through.

You do not need to know an endpoint's relay server in order to connect to them directly, if there are no firewalls or NATs between the two endpoints trying to connect. However, to have any hole punching, you must know at least one relay server to which that endpoint is connected.

We currently run 3 relays.


--- METRICS ---