How to Disable Relay Servers in Iroh: Complete Configuration Guide

To disable relay servers in Iroh, set RelayMode::Disabled on the Endpoint builder before calling bind(), or use the N0DisableRelay preset for a streamlined configuration.

The n0-computer/iroh repository provides flexible relay configuration through the RelayMode enum, allowing you to run peer-to-peer connections without relay infrastructure. This guide explains how to completely disable relay servers using the Rust API, with references to the actual source implementation in iroh/src/endpoint.rs.

Understanding RelayMode in Iroh

Iroh endpoints use RelayMode to determine whether relay servers should be contacted for NAT traversal. According to the source code in iroh/src/endpoint.rs, this enum includes a Disabled variant that completely shuts down relay functionality.

When you select RelayMode::Disabled, the endpoint neither listens for nor dials any relay servers. The builder translates this variant into an empty RelayMap, ensuring all relay-related traffic is omitted from the connection logic. This means your application will rely exclusively on direct peer-to-peer connectivity.

Methods to Disable Relay Servers

You must explicitly configure the relay mode before calling bind() on the builder. The default configuration (Endpoint::builder(presets::N0)) uses production relays, so disabling requires intentional override.

Using the Builder Method

Call .relay_mode(RelayMode::Disabled) directly on the endpoint builder to suppress relay usage:

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

#[tokio::main]
async fn main() -> iroh::Result<()> {
    let endpoint = Endpoint::builder(Empty)
        .relay_mode(RelayMode::Disabled)
        .bind()
        .await?;
    
    // Endpoint now operates without relay servers
    Ok(())
}

This approach gives you full control over the configuration while explicitly signaling that no relay fallback should be attempted.

Using the N0DisableRelay Preset

For a more concise configuration, use the N0DisableRelay preset, which applies standard N0 defaults while overriding the relay mode to disabled:

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

#[tokio::main]
async fn main() -> iroh::Result<()> {
    let endpoint = Endpoint::builder(N0DisableRelay)
        .bind()
        .await?;
    
    Ok(())
}

As implemented in iroh/src/endpoint/presets.rs (lines 172-184), this preset simply forwards to the standard N0 preset and then invokes .relay_mode(RelayMode::Disabled), providing identical behavior to the manual builder approach.

Code Examples

Minimal Builder with Relays Disabled

This example creates a bare endpoint with no relay infrastructure:

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

#[tokio::main]
async fn main() -> iroh::Result<()> {
    let ep = Endpoint::builder(Empty)
        .relay_mode(RelayMode::Disabled)
        .bind()
        .await?;

    // Connections will only succeed via direct addresses
    Ok(())
}

Production Preset Without Relays

When you need other N0 defaults but must disable relays for compliance or security reasons:

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

#[tokio::main]
async fn main() -> iroh::Result<()> {
    let ep = Endpoint::builder(N0DisableRelay).bind().await?;
    Ok(())
}

Post-Quantum Key Exchange Example

The repository includes a practical example in iroh/examples/pq-only-key-exchange.rs that disables relays to prevent interference with post-quantum TLS settings:

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

let server = Endpoint::builder(Empty)
    .crypto_provider(pq_provider)
    .alpns(vec![ALPN.to_vec()])
    .relay_mode(RelayMode::Disabled)
    .bind()
    .await?;

This demonstrates real-world usage where relay infrastructure must be bypassed for specific cryptographic requirements.

Implementation Details

The RelayMode enum definition resides in iroh/src/endpoint.rs (lines 1900-1924), where the Disabled variant is declared alongside Default and Custom options. When the builder processes this mode, it converts it into an empty RelayMap within the TransportConfig, effectively removing all relay server addresses from the endpoint's dial logic.

The preset implementation in iroh/src/endpoint/presets.rs (lines 172-184) provides the N0DisableRelay struct, which implements the EndpointBuilder trait by wrapping the standard N0 preset and appending the relay mode override.

Summary

  • RelayMode::Disabled in iroh/src/endpoint.rs provides the canonical way to disable relay functionality
  • Call .relay_mode(RelayMode::Disabled) on any endpoint builder before bind() to create an empty RelayMap
  • Use the N0DisableRelay preset to combine production defaults with disabled relays
  • When relays are disabled, connections fail rather than falling back to relay servers if direct paths are unavailable
  • The iroh/examples/pq-only-key-exchange.rs file demonstrates production usage of this configuration

Frequently Asked Questions

What happens if a direct connection fails when relays are disabled?

If you disable relay servers using RelayMode::Disabled and no direct path exists between peers, the connection attempt will fail immediately. Unlike the default configuration, which falls back to relay servers to facilitate NAT traversal, the disabled mode enforces strict direct connectivity only.

Can I switch between enabled and disabled relay modes after binding?

No, you must set the relay mode during the builder phase before calling bind(). Once the endpoint is bound, the RelayMode is converted into the internal TransportConfig and cannot be modified without creating a new endpoint instance.

Does disabling relays affect the crypto provider or ALPN settings?

Disabling relays only affects the RelayMap and connection establishment logic. All other endpoint configuration options—including crypto providers, ALPN protocols, and address families—remain independent and fully configurable when using RelayMode::Disabled.

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 →