Skip to main content
When you click Run Diagnostics in the dashboard, the platform dials back into your endpoint using the capability token your app granted. Your ClientHost receives the request, runs the diagnostics locally (probing UDP connectivity, NAT behavior, relay latency, and port mapping), and returns the report to n0des for display.

Integrating Net Diagnostics Into Your App

To add net diagnostics support to your own iroh application, you need to:
  1. Connect to the n0des platform with an iroh_n0des::Client
  2. Grant the NetDiagnosticsCap::GetAny capability to n0des so it can request diagnostics from your endpoint
  3. Run a ClientHost so n0des can dial back into your endpoint
See the net_diagnostics example in the iroh-n0des repository for a complete working example of this integration.

1. Update Cargo.toml

Add the following to your Cargo.toml:
[dependencies]
iroh-n0des = { version = "...", features = ["net_diagnostics", "client_host"] }

2. Get Your API Secret

Go to your project’s Settings page and copy the API secret. In your terminal, export it as an environment variable or config file, or hardcode it in your app (not recommended for production):
export N0DES_API_SECRET=<your-api-secret>

3. Connect to n0des and Grant Capability

Here’s a minimal integration:
use anyhow::Result;
use iroh::{Endpoint, protocol::Router};
use iroh_n0des::{
    ApiSecret, Client, ClientHost, CLIENT_HOST_ALPN, API_SECRET_ENV_VAR_NAME,
    caps::NetDiagnosticsCap,
};

async fn setup_net_diagnostics(endpoint: &Endpoint) -> Result<Router> {
    // Get your secret somehow, either from an environment variable or config file
    let secret = ApiSecret::from_env_var(API_SECRET_ENV_VAR_NAME)?;

    // The remote_id is the id of the endpoint we'll be sending the network
    // report to, derived from the secret's address
    let remote_id = secret.addr().id;

    // Build the client
    let client = Client::builder(endpoint)
        .api_secret(secret)?
        .build()
        .await?;

    // Grant the GetAny capability so the platform can request diagnostics
    // from this endpoint on demand
    let client2 = client.clone();
    tokio::spawn(async move {
        client2
            .grant_capability(remote_id, vec![NetDiagnosticsCap::GetAny])
            .await
            .unwrap();
    });

    // Set up a ClientHost so the platform can dial back into this endpoint
    let host = ClientHost::new(endpoint);
    let router = Router::builder(endpoint.clone())
        .accept(CLIENT_HOST_ALPN, host)
        .spawn();

    Ok(router)
}

Troubleshooting

The capability grant (NetDiagnosticsCap::GetAny) authorizes the platform to request diagnostics from your endpoint. Without this grant, the Run Diagnostics button will be disabled in the dashboard even if the endpoint is online.