How to Configure iroh Node Settings Using the Builder API
You configure iroh node settings through the chainable Builder API in iroh::endpoint::Builder, applying methods like relay_mode(), alpns(), and secret_key() before calling bind() to instantiate the Endpoint.
The n0-computer/iroh library exposes all node configuration options through a type-safe Builder pattern defined in iroh/src/endpoint.rs. This design allows you to customize cryptographic identities, transport layers, relay connectivity, and application protocols before the node opens sockets or establishes TLS contexts.
Understanding the Builder Pattern Architecture
In iroh/src/endpoint.rs, the Builder struct serves as the central configuration interface. You initialize it through Builder::empty() for a blank slate or Builder::new(preset) to start with sensible defaults.
All configuration methods return Self, enabling fluent chaining:
let endpoint = iroh::endpoint::Builder::empty()
.secret_key(my_key)
.alpns(vec![b"my-protocol".to_vec()])
.bind()
.await?;
The node only materializes when you invoke bind(), which consumes the Builder and returns a ready-to-use Endpoint. Until that point, you are merely assembling configuration state.
Essential Node Configuration Parameters
Node Identity and Cryptography
The secret_key() method sets the cryptographic identity of your node. If omitted, the builder generates a fresh SecretKey automatically via Default::default(). You must also supply a crypto provider via the ecosystem or explicitly, or bind() will return BindError::InvalidCryptoProvider.
use iroh::SecretKey;
let secret = SecretKey::generate();
builder.secret_key(secret);
For debugging TLS handshakes, enable keylog(true) to generate key-log files compatible with Wireshark.
Application Protocol Configuration
Incoming connections require at least one ALPN (Application-Layer Protocol Negotiation) identifier. The alpns() method accepts a Vec<Vec<u8>>:
builder.alpns(vec![
b"my-app/1.0".to_vec(),
b"my-app/2.0".to_vec(),
]);
Without ALPNs configured, the node cannot accept incoming connections, though it can still dial outbound.
Relay and Connectivity Settings
Relay configuration determines how your node discovers and communicates with peers through NAT traversal. The relay_mode() method accepts variants from RelayMode:
RelayMode::Disabled— Default inBuilder::empty(); no relay assistanceRelayMode::Default— Uses production relay infrastructure defined iniroh/src/defaults.rsRelayMode::Custom— Specify your own relay URLs
// Production relays
builder.relay_mode(iroh::RelayMode::Default);
// Custom private relay (line 165‑68 in endpoint.rs)
let custom = vec![iroh::RelayUrl::from_str("https://relay.example.com")?];
builder.relay_mode(iroh::RelayMode::Custom(custom.into()));
For NAT traversal, the portmapper_config() method accepts PortmapperConfig to control STUN/TURN behavior, while net_report_config() configures periodic network diagnostics.
Transport Layer Customization
By default, the builder adds IPv4 and IPv6 transports automatically. To customize this:
use iroh::transport::QuicConfig;
builder
.clear_ip_transports() // Removes auto-added IPv4/IPv6 (line 503)
.add_custom_transport(QuicConfig::default().into()); // Line 813
This pattern allows injection of custom transport implementations alongside or replacing the standard QUIC configuration.
Security and TLS Configuration
When connecting to private relays with self-signed certificates, use ca_tls_config() to customize trust anchors:
use iroh::tls::CaTlsConfig;
// Development only: skip verification (line 713)
builder.ca_tls_config(CaTlsConfig::insecure_skip_verify());
For production, supply proper root anchors via CaTlsConfig::from_pem() or system defaults. The max_tls_tickets() parameter controls TLS session resumption limits, defaulting to DEFAULT_MAX_TLS_TICKETS from defaults.rs.
Address Discovery Services
To enable DNS-based peer resolution, attach an address lookup service:
use iroh::address_lookup::DnsAddressLookupBuilder;
builder.address_lookup(DnsAddressLookupBuilder::default());
This integrates with iroh/src/address_lookup.rs to resolve EndpointId values to network addresses dynamically.
Practical Configuration Examples
Minimal Node with Production Relays
This example uses the N0 preset from iroh::endpoint::presets, which bundles sensible defaults:
use iroh::{Endpoint, endpoint::presets};
#[tokio::main]
async fn main() -> iroh::Result<()> {
let ep = Endpoint::builder(presets::N0)
.alpns(vec![b"my-app".to_vec()])
.relay_mode(iroh::RelayMode::Default)
.bind()
.await?;
println!("Node ID: {}", ep.id());
Ok(())
}
Source: Endpoint::builder → presets::N0 (see presets module in iroh/src/endpoint.rs).
Custom Relay with Self-Signed TLS
For private infrastructure requiring insecure TLS verification:
use iroh::{Endpoint, RelayMode, RelayUrl, tls::CaTlsConfig};
use std::str::FromStr;
#[tokio::main]
async fn main() -> iroh::Result<()> {
let relay = RelayUrl::from_str("https://my.private.relay:443")?;
let ep = Endpoint::builder(iroh::endpoint::presets::N0)
.relay_mode(RelayMode::Custom(vec![relay].into()))
.ca_tls_config(CaTlsConfig::insecure_skip_verify())
.alpns(vec![b"demo".to_vec()])
.bind()
.await?;
println!("Running with custom relay, node ID {}", ep.id());
Ok(())
}
Source: RelayMode::Custom (line 165‑68) and ca_tls_config (line 713) in iroh/src/endpoint.rs.
DNS Address Lookup Integration
Enable resolution of human-readable addresses to EndpointId values:
use iroh::{Endpoint, address_lookup::DnsAddressLookupBuilder};
#[tokio::main]
async fn main() -> iroh::Result<()> {
let ep = Endpoint::builder(iroh::endpoint::presets::N0)
.alpns(vec![b"my-proto".to_vec()])
.address_lookup(DnsAddressLookupBuilder::default())
.bind()
.await?;
// Now connect using only the remote EndpointId
// let conn = ep.connect(remote_id, b"my-proto").await?;
Ok(())
}
Source: Builder::address_lookup (line 605) and DnsAddressLookupBuilder in iroh/src/address_lookup.rs.
Isolated QUIC Transport Configuration
Control exactly which network transports the node utilizes:
use iroh::{Endpoint, transport::QuicConfig};
#[tokio::main]
async fn main() -> iroh::Result<()> {
let ep = Endpoint::builder(iroh::endpoint::presets::N0)
.clear_ip_transports()
.add_custom_transport(QuicConfig::default().into())
.bind()
.await?;
Ok(())
}
Source: Builder::clear_ip_transports (line 503) and add_custom_transport (line 813) in iroh/src/endpoint.rs.
Key Source Files for Configuration Reference
| File | Purpose | Location |
|---|---|---|
iroh/src/endpoint.rs |
Core Builder type, all configuration methods, bind() logic |
endpoint.rs |
iroh/src/defaults.rs |
Default relay hostnames, ports, and DEFAULT_MAX_TLS_TICKETS |
defaults.rs |
iroh/src/address_lookup.rs |
DNS and PKARR lookup service traits and builders | address_lookup.rs |
iroh/src/tls.rs |
CaTlsConfig, crypto provider setup, and TLS context creation |
tls.rs |
iroh/src/portmapper.rs |
NAT traversal configuration and STUN/TURN behavior | portmapper.rs |
These files collectively define the complete configuration surface for iroh nodes according to the n0-computer/iroh source code.
Summary
- Use the
BuilderAPI: All configuration happens throughiroh::endpoint::Buildermethods chained beforebind(). - Set ALPNs: Required for accepting incoming connections via
alpns(). - Choose Relay Mode: Defaults to disabled; use
relay_mode(RelayMode::Default)for production relays defined indefaults.rs. - Configure TLS: Supply
ca_tls_config()for custom trust anchors or development overrides. - Customize Transports: Use
clear_ip_transports()andadd_custom_transport()to override default QUIC sockets. - Enable Discovery: Attach
address_lookupservices to resolve peers via DNS or PKARR.
Frequently Asked Questions
What is the default relay mode for iroh nodes?
By default, Builder::empty() initializes nodes with RelayMode::Disabled, meaning no relay servers are used for NAT traversal. You must explicitly call relay_mode(iroh::RelayMode::Default) to use the production relay infrastructure defined in iroh/src/defaults.rs.
How do I configure iroh to accept incoming connections?
You must configure at least one ALPN protocol using the alpns() method on the builder. Without ALPN identifiers, the node will reject incoming connection attempts even if bound successfully. Example: builder.alpns(vec![b"my-protocol".to_vec()]).
Can I use custom TLS certificates with iroh relays?
Yes. Use builder.ca_tls_config(CaTlsConfig::from_pem(...)) to supply custom root certificates for validating private relay servers. For development scenarios only, CaTlsConfig::insecure_skip_verify() disables certificate verification entirely, as implemented in iroh/src/tls.rs.
Where are the default relay URLs defined in the iroh source code?
Default relay hostnames and ports for production and staging environments are defined in iroh/src/defaults.rs. The N0 preset references these defaults automatically when you initialize the builder with Endpoint::builder(presets::N0).
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 →