# iroh Endpoint Builder Pattern and Configuration Options: A Complete Guide

> Master the iroh Endpoint builder pattern and configuration options. Learn how to collect network, identity, and transport settings for a live Endpoint. Our guide provides complete details.

- Repository: [number zero/iroh](https://github.com/n0-computer/iroh)
- Tags: how-to-guide
- Published: 2026-07-05

---

**The `iroh::endpoint::Builder` implements a chainable builder pattern that collects optional network, identity, and transport settings and finalizes them into a live `Endpoint` through a single `bind` call.**

The `iroh` crate in the `n0-computer/iroh` repository exposes its core networking primitive via the `Endpoint` type, configured through the builder API defined in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs). Understanding the iroh Endpoint builder pattern and its configuration options is essential for customizing peer-to-peer connections, whether you need to tweak socket binding, swap crypto providers, or disable relay fallback entirely.

## How the iroh Endpoint Builder Pattern Works

An `Endpoint` requires a large amount of runtime information, including crypto providers, transport configuration, and relay settings. The `iroh::endpoint::Builder` holds a **partial configuration** and exposes a chainable API so you can override only the values you care about.

You create the builder through `Endpoint::builder(preset)`, passing a preset such as `presets::N0` or `presets::Empty`. Each configuration method takes `&mut self` and returns `Self`, enabling fluent chaining. When you are ready, `Builder::bind` validates the collected state—for example, ensuring a **crypto provider** is present—and then constructs the actual networking resources.

## Core Endpoint Builder Configuration Options

As implemented in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs), the builder surfaces methods across several functional categories. Below are the key chainable methods and what they control.

### Preset Initialization

- **`new(preset)`**, **`preset(preset)`**, **`empty()`** — Initialize the builder with a bundled configuration or start from a clean slate. For example, `presets::N0` selects a default crypto provider, relay map, and DNS/PKARR address-lookup services, while `presets::Empty` leaves every option unset.

### Network Transports and Socket Binding

- **`bind_addr`** and **`bind_addr_with_opts`** — Bind the endpoint to specific IP sockets. `bind_addr_with_opts` accepts a `BindOpts` struct for advanced control such as prefix length.
- **`clear_ip_transports`** and **`clear_relay_transports`** — Remove the built-in IPv4/IPv6 or relay transports so you can define custom behavior.

The underlying transport primitives are defined in [`iroh/src/socket/transports.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/socket/transports.rs), and socket allocation is handled by [`iroh/src/socket/bind.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/socket/bind.rs).

### Identity and Application Protocols

- **`secret_key`** — Set the **secret key** that determines the endpoint’s `EndpointId`. If omitted, `bind` generates one automatically.
- **`alpns`** — Provide a list of **ALPN** identifiers the endpoint will accept during connection negotiation.

### Relay Configuration and Address Discovery

- **`relay_mode`** — Choose a relay strategy: `Default`, `Staging`, `Custom`, or `Disabled`. This controls whether and how the endpoint uses relay servers for NAT traversal.
- **`address_lookup`**, **`clear_address_lookup`**, **`addr_filter`**, **`clear_addr_filter`**, **`user_data_for_address_lookup`** — Register or remove services that publish and discover the endpoint’s addresses, such as PKARR and DNS. Trait definitions for these services live in [`iroh/src/address_lookup/mod.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/address_lookup/mod.rs).
- **`external_addr`** — Manually advertise additional publicly reachable socket addresses beyond those discovered automatically.

### Transport Tuning, DNS, and Proxy Settings

- **`transport_config`** — Override the default `QuicTransportConfig` to adjust max streams, flow-control windows, and other QUIC parameters.
- **`dns_resolver`** *(non-WASM targets only)* — Supply a custom DNS resolver for relay hostnames and address lookups.
- **`proxy_url`** and **`proxy_from_env`** — Force all HTTP(S) traffic, including relay communication, through a proxy server.
- **`ca_tls_config`** — Set trusted CA certificates for TLS connections to relays or DoH resolvers.
- **`keylog`** and **`max_tls_tickets`** — Enable TLS pre-master-key logging for debugging and adjust the TLS ticket cache size.

### Crypto Providers, Hooks, and Advanced Extensions

- **`crypto_provider`** — Select the Rustls crypto implementation, such as `ring` or `aws-lc-rs`. This is required unless a crate feature supplies a default.
- **`hooks`** — Install an `EndpointHooks` implementation to intercept connection establishment events.
- **`portmapper_config`** — Enable or disable UPnP, PCP, and NAT-PMP for automatic gateway port mapping.
- **`net_report_config`** — Tune the optional net-report component that probes relays to detect NAT behavior, latency, and captive portals.
- **`add_custom_transport`** *(unstable feature)* — Register a user-defined transport implementation.
- **`path_selector`** *(unstable feature)* — Replace the default biased-RTT path selector with a custom algorithm.

## What `Builder::bind` Does Under the Hood

When you invoke `bind`, the builder executes a strict validation and construction sequence defined in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs):

1. **Generates a `SecretKey`** if you did not provide one via `secret_key`.
2. **Validates that a `crypto_provider`** is present; otherwise, construction fails.
3. **Builds TLS server and client configs**, a QUIC `StaticConfig`, and a socket options struct from the accumulated state.
4. **Calls `socket::EndpointInner::bind`** to allocate sockets and start the underlying QUIC endpoint.
5. **Installs address-lookup services** and applies any address filter you configured.

This encapsulation keeps the public `Endpoint` API clean while ensuring that every fully built instance is in a valid state.

## Practical iroh Endpoint Builder Examples

### Default N0 Preset

The `presets::N0` preset bundles a crypto provider, a default relay map, and standard DNS/PKARR address-lookup services. It is the fastest way to spin up an endpoint:

```rust
use iroh::{Endpoint, endpoint::presets};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let ep = Endpoint::builder(presets::N0).bind().await?;
    println!("Running as {}", ep.id().fmt_short());
    Ok(())
}

```

This example uses `Endpoint::builder` followed immediately by `bind`, relying entirely on the N0 defaults defined in [`iroh/src/endpoint/presets.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint/presets.rs).

### Custom Transports and ALPN

To bind specific addresses and restrict accepted protocols, start from `presets::Empty` and layer on exactly what you need:

```rust
use iroh::{Endpoint, endpoint::presets, endpoint::BindOpts};
use std::sync::Arc;

let ep = Endpoint::builder(presets::Empty)
    .crypto_provider(Arc::new(rustls::crypto::ring::default_provider()))
    .clear_ip_transports()
    .bind_addr_with_opts("127.0.0.1:0", BindOpts::default().set_prefix_len(24))?
    .bind_addr_with_opts("[::1]:0", BindOpts::default().set_prefix_len(48))?
    .alpns(vec![b"my-protocol".to_vec()])
    .bind()
    .await?;

```

Here, `clear_ip_transports` removes defaults before `bind_addr_with_opts` attaches IPv4 and IPv6 listeners. The `alpns` call restricts the endpoint to a single application protocol.

### Custom Address Lookup Service

You can integrate your own address discovery logic by implementing the `AddressLookupBuilder` trait and registering it with the builder:

```rust
struct MyLookup;

impl iroh::address_lookup::AddressLookupBuilder for MyLookup {
    fn into_address_lookup(
        self,
        _ep: &iroh::Endpoint,
    ) -> Result<
        Box<dyn iroh::address_lookup::AddressLookup>,
        iroh::address_lookup::AddressLookupFailed,
    > {
        // ...implementation...
        todo!()
    }
}

let ep = Endpoint::builder(presets::Minimal)
    .address_lookup(MyLookup)
    .bind()
    .await?;

```

The builder stores this service and installs it during `bind` so the endpoint can publish or resolve addresses through your custom backend.

### Disable Relays for Direct Connections

If your deployment guarantees direct IP connectivity, disable relay fallback entirely:

```rust
let ep = Endpoint::builder(presets::Minimal)
    .relay_mode(iroh::RelayMode::Disabled)
    .clear_relay_transports()
    .bind()
    .await?;

```

Setting `relay_mode` to `RelayMode::Disabled` and clearing relay transports ensures the endpoint never attempts relayed communication.

## Summary

- The **`iroh::endpoint::Builder`** implements a classic builder pattern in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs), collecting partial configuration through chainable methods and producing a finalized `Endpoint` via `bind`.
- **Presets** such as `presets::N0` supply sensible defaults, while `presets::Empty` lets you opt into every setting manually.
- Key configuration areas include **socket binding**, **`secret_key`** and **`alpns`**, **`relay_mode`**, **`address_lookup`** services, **`transport_config`**, and **`crypto_provider`**.
- The **`bind`** method validates required state—especially the crypto provider—generates missing secrets, builds TLS/QUIC internals, and starts the socket layer inside `socket::EndpointInner::bind`.

## Frequently Asked Questions

### What is the difference between `presets::N0` and `presets::Empty`?

`presets::N0` bundles a default crypto provider, relay map, and DNS/PKARR address-lookup services so you can call `bind` immediately. `presets::Empty` starts from a blank slate, requiring you to manually configure the crypto provider, transports, and any discovery logic before the endpoint can start.

### Is `crypto_provider` always required when using the iroh Endpoint builder?

Yes, a crypto provider must be present before `bind` succeeds. If you use a preset like `N0` that includes one, or if a crate feature supplies a default, you do not need to call `crypto_provider` explicitly. Otherwise, you must set it yourself.

### Can I run an iroh endpoint without any relay servers?

Yes. Call `.relay_mode(iroh::RelayMode::Disabled)` and `.clear_relay_transports()` on the builder. This removes relay fallback and forces the endpoint to rely solely on direct IP connections.

### How does `Builder::bind` validate configuration before spawning the endpoint?

Inside [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs), `bind` first ensures a `crypto_provider` is present and generates a `SecretKey` if none was supplied. It then constructs TLS and QUIC configurations, calls `socket::EndpointInner::bind` to open sockets, and finally installs any address-lookup services and filters. If any required state is missing, construction fails before network resources are allocated.