# How to Disable Relay Servers in Iroh: Complete Configuration Guide

> Learn how to disable relay servers in Iroh with our complete configuration guide. Follow simple steps to modify your Endpoint builder for optimal network control.

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

---

**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`](https://github.com/n0-computer/iroh/blob/main/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`](https://github.com/n0-computer/iroh/blob/main/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:

```rust
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:

```rust
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`](https://github.com/n0-computer/iroh/blob/main/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:

```rust
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:

```rust
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`](https://github.com/n0-computer/iroh/blob/main/iroh/examples/pq-only-key-exchange.rs) that disables relays to prevent interference with post-quantum TLS settings:

```rust
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`](https://github.com/n0-computer/iroh/blob/main/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`](https://github.com/n0-computer/iroh/blob/main/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`](https://github.com/n0-computer/iroh/blob/main/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`](https://github.com/n0-computer/iroh/blob/main/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`.