# How to Configure TLS and Crypto Providers in Iroh Endpoints

> Configure TLS and crypto providers in Iroh endpoints using rustls, CaTlsConfig, and TlsConfig for secure connections. Learn how to specify root CAs and custom verification.

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

---

**Iroh endpoints use the `rustls` TLS stack, configured through the `CaTlsConfig` and `TlsConfig` types in [`iroh-relay/src/tls.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/tls.rs), allowing you to specify root certificates, custom verification logic, and crypto providers via `default_provider()` when establishing secure connections.**

The iroh networking library delegates all TLS operations to the `rustls` crate, exposing a unified configuration API through the `tls` module. When you configure TLS and crypto providers in iroh endpoints, you create a `CaTlsConfig` that defines certificate verification behavior, then combine it with a crypto provider to build a `rustls::ClientConfig` that the endpoint consumes.

## Core TLS Configuration Types

The TLS implementation in iroh centers on two primary types defined in [`iroh-relay/src/tls.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/tls.rs).

### CaTlsConfig

The `CaTlsConfig` struct controls how the client verifies server certificate chains. It stores a `mode` enum and an optional list of extra root certificates, supporting five distinct verification strategies:

- **EmbeddedWebPki**: Uses the built-in Mozilla root store (`webpki_roots::TLS_SERVER_ROOTS`)
- **System**: Delegates to the OS certificate store when the `platform-verifier` feature is enabled
- **ExtraRootsOnly**: Trusts only explicitly supplied root certificates
- **CustomServerCertVerifier**: Accepts a custom `rustls::client::ServerCertVerifier` implementation
- **InsecureSkipVerify**: Bypasses verification (test builds only)

### TlsConfig

The `TlsConfig` type bundles a socket address with either a `CaTlsConfig` (for clients) or a `CertConfig` containing a `rustls::ServerConfig` (for servers). This structure is attached to iroh endpoints such as relay clients or DNS resolvers.

## Configuring Certificate Verification for Clients

### Using Embedded Mozilla Roots

By default, iroh trusts the Mozilla root certificate store. Create this configuration using `CaTlsConfig::embedded()`:

```rust
use iroh::tls::CaTlsConfig;

let ca_cfg = CaTlsConfig::embedded();

```

### Leveraging the OS Certificate Store

On platforms supporting the `platform-verifier` feature, delegate verification to the operating system:

```rust
let ca_cfg = CaTlsConfig::system();

```

### Trusting Custom Root Certificates

For private CAs or self-signed certificates, supply DER-encoded certificates directly:

```rust
use iroh::tls::CaTlsConfig;
use rustls::pki_types::CertificateDer;

let my_root: CertificateDer<'static> = // ... load your certificate
let ca_cfg = CaTlsConfig::custom_roots(vec![my_root]);

```

Even when `system()` is unavailable (such as on Android), the `EmbeddedWebPki` mode loads the Mozilla roots and appends your custom roots.

### Implementing Custom Verification Logic

For advanced scenarios, provide a custom `ServerCertVerifier`:

```rust
let ca_cfg = CaTlsConfig::custom_server_cert_verifier(|| {
    // Return your custom verifier implementation
    Box::new(MyCustomVerifier)
});

```

## Selecting Crypto Providers

### The default_provider() Function

Iroh exports `default_provider()` from [`iroh-relay/src/tls.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/tls.rs) to access the global `rustls::crypto::CryptoProvider`. This returns either the `ring` or `aws-lc-rs` implementation depending on your feature flags:

```rust
use iroh::tls::default_provider;

let crypto_provider = default_provider();

```

## Building Client Configurations for Endpoints

To apply TLS settings to an endpoint, convert your `CaTlsConfig` into a `rustls::ClientConfig` using the `client_config()` method. This method builds the configuration by calling `dangerous().with_custom_certificate_verifier(...)` internally when necessary:

```rust
use iroh::{tls::{CaTlsConfig, default_provider}, util::RelayBuilder};

let ca_cfg = CaTlsConfig::embedded();
let client_cfg = ca_cfg.client_config(default_provider())
    .expect("TLS client config creation failed");

let relay = RelayBuilder::new()
    .tls_config(client_cfg)
    .build();

```

## Server-Side TLS Configuration

For server endpoints (such as relay servers), construct a `TlsConfig` containing a `CertConfig::Manual` with a `rustls::ServerConfig`. The implementation in [`iroh/tests/patchbay/util.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/tests/patchbay/util.rs) demonstrates this pattern using `self_signed_tls_certs_and_config()`:

```rust
// Example pattern from iroh/tests/patchbay/util.rs
let (tls_config, cert) = self_signed_tls_certs_and_config();
// The server stores this as: relay.tls = Some(tls_config);

```

## Test-Only Insecure Configuration

For testing environments, iroh provides `CaTlsConfig::insecure_skip_verify()`, which creates a `make_dangerous_client_config()` helper that trusts any server certificate. This is restricted to test builds via `#[cfg(test)]` or `test-utils` feature flags:

```rust
use iroh::tls::CaTlsConfig;

let ca_cfg = CaTlsConfig::insecure_skip_verify();
let client_cfg = ca_cfg.client_config(default_provider()).unwrap();

```

**Warning**: Never use this mode in production; the crate enforces this restriction through conditional compilation.

## Integration Points

The TLS configuration connects to several iroh subsystems:

- **Relay Client**: The relay crate calls `tls::CaTlsConfig::client_config()` to obtain a `ClientConfig` for the underlying QUIC or hyper transport
- **DNS-over-HTTPS**: The resolver in [`iroh-dns-server/src/http/tls.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-dns-server/src/http/tls.rs) builds `rustls::ClientConfig` using the same patterns
- **Re-exports**: The top-level `iroh` crate re-exports these symbols from [`iroh/src/tls/mod.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/tls/mod.rs) for convenient access

## Summary

- **Iroh uses rustls** for all TLS operations, with configuration centralized in [`iroh-relay/src/tls.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/tls.rs)
- **CaTlsConfig** controls verification via `embedded()`, `system()`, `custom_roots()`, or custom verifiers
- **default_provider()** returns the active crypto implementation (ring or aws-lc-rs)
- **client_config()** converts CaTlsConfig into a rustls ClientConfig for endpoint consumption
- **TlsConfig** handles server-side configuration with CertConfig::Manual
- **Insecure skip verification** is available only in test builds via `insecure_skip_verify()`

## Frequently Asked Questions

### How do I configure iroh to use my company's internal CA?

Load your CA certificate in DER format and pass it to `CaTlsConfig::custom_roots()`. This mode trusts only your specified roots, ignoring the Mozilla and OS stores. The configuration is created in [`iroh-relay/src/tls.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/tls.rs) and accepts a `Vec<CertificateDer<'static>>`.

### What is the difference between CaTlsConfig and TlsConfig?

`CaTlsConfig` defines certificate verification behavior for clients (whether to trust Mozilla roots, OS stores, or custom certificates), while `TlsConfig` bundles the certificate configuration with a socket address and is used by both clients and servers. Servers use `TlsConfig` with `CertConfig::Manual` containing a `rustls::ServerConfig`.

### Which crypto providers does iroh support?

Iroh supports the `ring` and `aws-lc-rs` crypto providers through rustls. The `default_provider()` function returns whichever implementation is enabled via feature flags, allowing you to configure endpoints to use hardware-accelerated cryptography where available.

### Can I disable TLS certificate verification in production?

No. The `insecure_skip_verify()` method is gated behind `#[cfg(test)]` or the `test-utils` feature flag. The source code in [`iroh-relay/src/tls.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/tls.rs) explicitly restricts this dangerous configuration to test builds only, preventing accidental deployment of insecure endpoints.