RelayMode in iroh: How to Configure Relay Server Fallback
RelayMode is a configuration enum that tells an iroh Endpoint which relay servers to use for NAT hole-punching, automatically falling back through subsequent URLs when the primary relay is unreachable.
Relay servers enable connectivity when direct peer-to-peer paths are blocked by firewalls or NAT devices. In the n0-computer/iroh codebase, RelayMode acts as the central control mechanism that determines which relay infrastructure your application will utilize. This article explains the enum variants defined in iroh/src/endpoint.rs and demonstrates how to configure automatic fallback behavior across multiple relay servers.
What is RelayMode?
RelayMode is defined in [iroh/src/endpoint.rs](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs) and specifies the relay strategy for an Endpoint:
pub enum RelayMode {
/// Disable all relay functionality.
Disabled,
/// Use the production relay map shipped with iroh.
Default,
/// Use the staging relay map (useful for testing).
Staging,
/// Use a user‑supplied map of relay URLs.
Custom(RelayMap),
}
The four variants provide distinct operational modes:
Disabled– No relay servers are contacted. The endpoint can only connect to peers reachable via direct network paths.Default– Uses the production relay map returned bycrate::defaults::prod::default_relay_map().Staging– Uses the staging relay map viacrate::defaults::staging::default_relay_map(), ideal for CI environments and pre-production testing.Custom– Accepts a user-providedRelayMapcontaining one or moreRelayUrlentries that the endpoint will attempt in order.
The library provides a convenience function that selects between production and staging based on an environment variable:
/// If the `IROH_FORCE_STAGING_RELAYS` environment variable is non‑empty,
/// `RelayMode::Staging` is returned, otherwise `RelayMode::Default`.
pub fn default_relay_mode() -> RelayMode { … }
This helper is located at lines 66-73 of iroh/src/endpoint.rs and allows runtime configuration without code changes.
How Relay Server Fallback Works
When an endpoint is constructed with a RelayMode, the underlying RelayMap may contain multiple relay URLs. During connection establishment, the endpoint attempts these URLs sequentially; if the first relay is unreachable due to network errors or TLS failures, it automatically proceeds to the next entry. This fallback behavior is intrinsic to RelayMap—no additional logic is required from the developer.
This pattern mirrors the DNS fallback implementation found in [iroh-dns/src/dns.rs](https://github.com/n0-computer/iroh/blob/main/iroh-dns/src/dns.rs#L230-L250), where the library falls back to Google’s public DNS when the system resolver is unavailable. Both implementations follow the same design philosophy: attempt the configured resource first, then degrade gracefully to alternative options.
Configuring RelayMode in Practice
Using Environment-Driven Defaults
To respect the IROH_FORCE_STAGING_RELAYS environment variable and automatically select between production and staging:
let endpoint = iroh::Endpoint::builder(presets::Minimal)
.relay_mode(iroh::default_relay_mode())
.bind()
.await?;
Explicit Staging Configuration
For test suites or development environments that must use staging infrastructure regardless of environment variables:
let endpoint = iroh::Endpoint::builder(presets::Minimal)
.relay_mode(iroh::RelayMode::Staging)
.bind()
.await?;
Custom Relay Maps with Fallback Chains
To configure a primary relay with automatic fallback to a secondary server, provide multiple URLs in a RelayMap. The endpoint will try each in order:
use iroh::{RelayMode, RelayUrl};
let custom_map = iroh::RelayMap::from_iter([
"https://relay-primary.n0.iroh.link".parse::<RelayUrl>()?,
"https://relay-fallback.n0.iroh.link".parse::<RelayUrl>()?,
]);
let endpoint = iroh::Endpoint::builder(presets::Minimal)
.relay_mode(RelayMode::Custom(custom_map))
.bind()
.await?;
Disabling Relay Functionality
For LAN-only deployments or closed networks where relay assistance is unnecessary:
let endpoint = iroh::Endpoint::builder(presets::Minimal)
.relay_mode(RelayMode::Disabled)
.bind()
.await?;
Summary
- RelayMode controls relay server selection through four variants:
Disabled,Default,Staging, andCustom. - The
default_relay_mode()function selects staging when theIROH_FORCE_STAGING_RELAYSenvironment variable is set, otherwise uses production. - Fallback is automatic when using
RelayMode::Customwith multiple URLs—the endpoint tries each relay sequentially until one succeeds. - Source definitions reside in
iroh/src/endpoint.rs, with related fallback patterns demonstrated iniroh-dns/src/dns.rs.
Frequently Asked Questions
What is the default relay mode in iroh?
By default, iroh uses RelayMode::Default, which connects to the production relay infrastructure maintained by the project. However, if the IROH_FORCE_STAGING_RELAYS environment variable is non-empty, the default_relay_mode() function returns RelayMode::Staging instead, directing traffic to testing servers.
How does iroh handle relay server failures?
When configured with a custom relay map containing multiple URLs, the endpoint attempts each relay in the order provided. If a connection to the first URL fails due to network timeouts, DNS resolution errors, or TLS handshake failures, the endpoint automatically falls back to the next URL in the map without requiring application-level retry logic.
Can I run iroh without any relay servers?
Yes. Setting RelayMode::Disabled prevents the endpoint from contacting any relay servers. In this mode, the endpoint relies exclusively on direct peer-to-peer connections, which is suitable for LAN environments or networks where all peers have public IP addresses and open ports.
What is the difference between staging and production relay maps?
The production map (RelayMode::Default) uses the stable, publicly available relay infrastructure designed for production applications. The staging map (RelayMode::Staging) points to separate testing servers used for development, CI pipelines, and validating new iroh releases before they reach production.
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 →