Iroh Relay Modes Explained: Disabled, Default, Staging, and Custom Configurations

Iroh provides four distinct relay modes—Disabled, Default, Staging, and Custom—that control how nodes connect through relay servers when direct connections fail.

The Iroh networking stack, maintained in the n0-computer/iroh repository, uses the RelayMode enum to determine whether and how endpoints utilize relay infrastructure for NAT traversal and fallback routing. These modes are defined in [iroh/src/endpoint.rs](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs) and allow developers to tune connectivity behavior from completely offline P2P setups to globally distributed production deployments.

The Four Iroh Relay Modes

The RelayMode enum (lines 1912–1925 in iroh/src/endpoint.rs) specifies exactly how an endpoint resolves relay addresses. Each variant maps to a different relay infrastructure strategy.

Disabled Mode

RelayMode::Disabled prevents the endpoint from adding any relay transport, forcing the node to attempt only direct IP connections.

This mode is optimal for peer-to-peer deployments on trusted LANs or air-gapped environments where relay traffic—typically tunneled over HTTPS—must be avoided entirely. When disabled, hole-punching through NATs relies solely on direct IP discovery without relay assistance.

Default Mode

RelayMode::Default activates the production relay map that ships with Iroh, commonly referred to as the "number 0" relays.

This is the standard configuration for most applications, providing immediate access to a globally distributed set of relay servers maintained by the Iroh team. The default map requires no additional configuration and handles hole-punching and fallback routing automatically.

Staging Mode

RelayMode::Staging directs the endpoint to use a separate staging relay fleet intended for testing and development.

This mode activates when explicitly configured or when the environment variable IROH_FORCE_STAGING_RELAYS is set. Staging relays allow integration testing against non-production infrastructure without polluting production relay metrics or capacity.

Custom Mode

RelayMode::Custom(RelayMap) accepts a user-defined RelayMap containing specific RelayUrl entries.

This mode supports self-hosted relay infrastructure or curated subsets of public relays. The provided RelayMap must contain at least one valid relay URL, and Iroh will treat these entries identically to the built-in production map for hole-punching and routing decisions.

Under the Hood: How Relay Modes Are Processed

Internally, the RelayMode implementation includes a helper method relay_map() starting at line 1934 in iroh/src/endpoint.rs. This method converts the enum variant into a concrete RelayMap instance:

  • Disabled returns an empty map
  • Default and Staging resolve to their respective built-in configurations
  • Custom returns the user-supplied map directly

The endpoint builder later transforms this map into a TransportConfig::Relay entry, inserting it into the transport list used during connection establishment.

Configuring Iroh Relay Modes in Practice

To select a relay mode, use the relay_mode() builder method on the Endpoint before calling bind(). Below are complete examples for each configuration.

Using Default Production Relays

use iroh::{Endpoint, RelayMode, endpoint::presets};

let ep = Endpoint::builder(presets::N0)
    .relay_mode(RelayMode::Default)
    .bind()
    .await?;

Disabling Relays for Direct-Only Connections

use iroh::{Endpoint, RelayMode, endpoint::presets};

let ep = Endpoint::builder(presets::N0)
    .relay_mode(RelayMode::Disabled)
    .bind()
    .await?;

Targeting Staging Infrastructure

use iroh::{Endpoint, RelayMode, endpoint::presets};

let ep = Endpoint::builder(presets::N0)
    .relay_mode(RelayMode::Staging)
    .bind()
    .await?;

Deploying Custom Relay Infrastructure

use iroh::{Endpoint, RelayMode, RelayMap, endpoint::presets};
use iroh_base::RelayUrl;

let my_map = RelayMap::from(vec![
    RelayUrl::from_str("https://my-relay.example.com")?,
    RelayUrl::from_str("https://another-relay.example.org")?,
]);

let ep = Endpoint::builder(presets::N0)
    .relay_mode(RelayMode::Custom(my_map))
    .bind()
    .await?;

When to Use Each Iroh Relay Mode

Select your relay configuration based on deployment constraints and network topology:

  • Use Disabled for LAN-only clusters, offline-first applications, or compliance environments forbidding external relay connections.
  • Use Default for production workloads requiring global reachability without operational overhead of relay management.
  • Use Staging when running CI/CD pipelines, pre-production validation, or when testing relay protocol changes.
  • Use Custom when operating private infrastructure, complying with data residency requirements, or implementing relay topology optimizations.

Summary

  • Iroh relay modes are controlled by the RelayMode enum in iroh/src/endpoint.rs, supporting four distinct variants.
  • Disabled blocks all relay traffic, enforcing direct IP connections only.
  • Default connects to the production "number 0" relay fleet for global hole-punching.
  • Staging routes through test relays, activated via configuration or the IROH_FORCE_STAGING_RELAYS environment variable.
  • Custom(RelayMap) allows self-hosted relay URLs, requiring at least one valid entry in the provided map.
  • The relay_map() method at line 1934 converts enum variants into transport configurations that the endpoint builder applies during initialization.

Frequently Asked Questions

What is the difference between RelayMode::Default and RelayMode::Staging?

RelayMode::Default connects to the production relay infrastructure maintained by the Iroh team, providing global coverage for hole-punching. RelayMode::Staging connects to a separate test relay fleet used for development and CI/CD validation, preventing test traffic from affecting production capacity.

Can I use multiple relay modes simultaneously in one application?

No, an Iroh Endpoint accepts exactly one RelayMode configuration during initialization. However, the Custom variant accepts a RelayMap containing multiple relay URLs, allowing you to specify redundant relay endpoints within a single mode configuration.

What happens if I specify RelayMode::Custom with an empty relay map?

Iroh requires the RelayMap in RelayMode::Custom to contain at least one valid RelayUrl. Providing an empty map will result in a configuration error during endpoint initialization, as the transport layer requires at least one relay endpoint for the mode to function.

Does RelayMode::Disabled affect direct connection attempts?

No, RelayMode::Disabled only removes relay transport from the endpoint's available strategies. Direct IP connections—including hole-punching attempts via other mechanisms—continue to function normally. This mode simply prevents the endpoint from using HTTPS-based relay servers as a fallback or discovery mechanism.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →