# How to Configure Custom Relay Servers in iroh Using RelayMode::Custom

> Learn to configure custom iroh relay servers using RelayMode::Custom. Route traffic through your own infrastructure with a custom relay map for enhanced control and performance.

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

---

**Use `RelayMode::Custom(RelayMap)` when building your iroh `Endpoint` to route traffic through self-hosted relay servers instead of the default infrastructure.**

When direct peer-to-peer connections fail, the iroh networking layer relies on relay servers to forward traffic between nodes. The `RelayMode` enum in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs) controls this behavior, allowing you to configure custom relay servers using `RelayMode::Custom` for complete infrastructure control.

## Understanding RelayMode Variants

The `RelayMode` enum in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs) defines four distinct strategies for relay discovery:

- **`RelayMode::Disabled`** – Restricts connections to direct peer-to-peer paths only, with no relay fallback.
- **`RelayMode::Default`** – Automatically uses the production relay map from `crate::defaults::prod::default_relay_map()`.
- **`RelayMode::Staging`** – Uses the staging relay map from `crate::defaults::staging::default_relay_map()` for testing environments.
- **`RelayMode::Custom(RelayMap)`** – Accepts a user-supplied `RelayMap` containing your own set of `RelayUrl` endpoints.

The `RelayMap` type is simply a collection of `RelayUrl`s that the endpoint queries when establishing relayed connections.

## Configuring Custom Relay Servers

To configure custom relay servers, construct a `RelayMode::Custom` variant using the helper method `RelayMode::custom(iter)`, which accepts any iterator of `RelayUrl`s.

### Building the RelayMap

Parse your relay URLs and pass them to `RelayMode::custom()`:

```rust
use iroh::{RelayMode, RelayUrl};

let custom_relays = [
    "https://my-relay-1.example.com/".parse::<RelayUrl>()?,
    "https://my-relay-2.example.com/".parse::<RelayUrl>()?,
];

let relay_mode = RelayMode::custom(custom_relays);

```

### Applying to the Endpoint Builder

Pass the configured `RelayMode` to the builder before binding:

```rust
use iroh::{Endpoint, presets};

let endpoint = Endpoint::builder(presets::Minimal)
    .relay_mode(relay_mode)
    .bind()
    .await?;

```

## Practical Implementation Examples

### Basic Custom Relay Configuration

```rust
use iroh::{Endpoint, RelayMode, RelayUrl, presets};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let urls = vec![
        "https://relay-1.example.com/".parse::<RelayUrl>()?,
        "https://relay-2.example.com/".parse::<RelayUrl>()?,
    ];
    
    let endpoint = Endpoint::builder(presets::Minimal)
        .relay_mode(RelayMode::custom(urls))
        .bind()
        .await?;
        
    Ok(())
}

```

### Loading Relays from Environment Variables

As demonstrated in [`iroh/examples/connect.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/examples/connect.rs), you can dynamically configure relays from environment variables:

```rust
use std::{env, str::FromStr};
use iroh::{Endpoint, RelayMode, RelayUrl, presets};

async fn build_endpoint() -> Result<Endpoint, Box<dyn std::error::Error>> {
    let urls = env::var("RELAY_URLS")?;
    let relay_urls: Vec<RelayUrl> = urls
        .split(',')
        .map(|s| RelayUrl::from_str(s.trim()))
        .collect::<Result<Vec<_>, _>>()?;

    let endpoint = Endpoint::builder(presets::Minimal)
        .relay_mode(RelayMode::custom(relay_urls))
        .bind()
        .await?;
        
    Ok(endpoint)
}

```

### Disabling Relays for LAN-Only Deployments

```rust
use iroh::{Endpoint, RelayMode, presets};

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

```

## Internal Implementation Details

When `Endpoint::builder` prepares the configuration, the `relay_mode()` method stores your chosen `RelayMode`. During connection establishment, iroh calls `relay_map()` on the mode to retrieve the appropriate `RelayMap`. For `RelayMode::Custom`, this returns your user-supplied map rather than the default production or staging maps.

The conversion happens in the `From<RelayMode> for Option<TransportConfig>` implementation in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs), which maps the `RelayMode` to the internal `TransportConfig::Relay` variant used by the networking layer. This design is validated in [`iroh/tests/patchbay/util.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/tests/patchbay/util.rs), which uses `RelayMode::Custom` in integration tests.

## Summary

- **`RelayMode::Custom`** enables self-hosted relay infrastructure in n0-computer/iroh via the `RelayMap` type.
- The helper method `RelayMode::custom(iter)` constructs a valid mode from any iterator of `RelayUrl`s.
- Set the mode using `.relay_mode()` on the `Endpoint` builder before calling `.bind()`.
- The configuration is defined in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs) alongside the conversion logic that produces the internal `TransportConfig`.

## Frequently Asked Questions

### What is the difference between RelayMode::Default and RelayMode::Custom?

`RelayMode::Default` automatically uses the production relay servers maintained by the iroh team (via `crate::defaults::prod::default_relay_map()`), while `RelayMode::Custom` requires you to supply your own relay URLs via a `RelayMap` for complete control over the relay infrastructure.

### Can I use multiple custom relay servers in iroh?

Yes. The `RelayMode::custom()` helper accepts any iterator, allowing you to pass multiple `RelayUrl` instances. The endpoint will use these relays for hole-punching and traffic forwarding when direct connections fail, as implemented in the `relay_map()` method.

### How do I disable relay servers entirely in iroh?

Use `RelayMode::Disabled` when configuring your endpoint. This prevents the endpoint from using any relay infrastructure, restricting connections to direct peer-to-peer paths only, which is useful for LAN-only deployments.

### Where is the RelayMode configuration stored in the iroh codebase?

The `RelayMode` enum and its conversion logic are defined in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs). This file also contains the `From<RelayMode> for Option<TransportConfig>` implementation that translates the high-level mode into the internal transport configuration used by the networking stack.