diff --git a/add-a-relay.mdx b/add-a-relay.mdx
index 2460798..122f723 100644
--- a/add-a-relay.mdx
+++ b/add-a-relay.mdx
@@ -3,7 +3,7 @@ title: "Use your own relay"
description: "Configure dedicated relays so your endpoints don't share infrastructure with the public network"
---
-import RelayEndpointConfig from '/snippets/relay-endpoint-config.mdx';
+import RelayPresetConfig from '/snippets/relay-preset-config.mdx';
By default, iroh endpoints use the public relays maintained by [n0.computer](https://n0.computer) to facilitate connections when direct peer-to-peer links aren't possible. The public relays are great for development and testing, but production deployments should run their own.
@@ -11,17 +11,23 @@ By default, iroh endpoints use the public relays maintained by [n0.computer](htt
Running dedicated relays gives you:
-- **Isolation**: your traffic isn't mixed with other developers on the shared public network
+- **Isolation**: your traffic isn't mixed with other applications
- **Performance**: relays close to your users reduce latency and improve NAT traversal success
-- **Capacity**: the public relays are rate-limited; your own relays have no rate limits and capacity you control
+- **Capacity**: the shared public infrastructure is rate-limited
- **Redundancy**: distribute relays across regions or cloud providers for failover
- **Compliance**: keep relayed traffic inside your own network or jurisdiction
-Iroh's relay architecture is uniquely suited to multi-relay deployments because relays are stateless. Clients automatically fail over between relays in your list, so adding capacity or surviving an outage is just a matter of running more relay processes. See [Dedicated Infrastructure](/deployment/dedicated-infrastructure) for the deeper architecture story.
+Iroh's relay architecture is uniquely suited to multi-relay deployments because
+relays are stateless. Clients automatically fail over between relays in your
+list, so adding capacity or surviving an outage is just a matter of running more
+relay processes. See [Dedicated
+Infrastructure](/deployment/dedicated-infrastructure) for the deeper
+architecture story.
## Get a relay
-You have two paths. Pick **managed** if you want a relay running today without ops work; pick **self-host** if you have infrastructure available and want full control over the deployment.
+You have two paths. Pick **managed** if you want a relay running today. But
+you're never locked in! You can always self-host later if you want.
+
+
+Relays you self-host outside of Iroh Services are configured directly with `RelayMode::Custom`; see [Dedicated Infrastructure](/deployment/dedicated-infrastructure).
## Recommended setup
diff --git a/concepts/relays.mdx b/concepts/relays.mdx
index 4891412..23e70f0 100644
--- a/concepts/relays.mdx
+++ b/concepts/relays.mdx
@@ -55,11 +55,31 @@ Dedicated relays are relay servers provisioned exclusively for your project, eit
They offer:
+- **Authenticated by default**: only your project's endpoints can connect, authenticated automatically with your API key. You can turn authentication off from the dashboard if you want any endpoint that has the URL to be able to use it.
- **Isolation**: no noisy neighbors; your traffic is yours alone
- **Uptime guarantees**: SLAs available via [Iroh Services](/iroh-services/relays)
- **Version locking**: stay on a specific iroh version or run blue/green deployments
- **Multi-region & multi-cloud**: deploy relays across regions and providers for resilience
+## Authentication
+
+Dedicated relays require authentication by default, so a relay only carries traffic for endpoints that belong to your project. Authentication is built in — there's nothing extra to wire up beyond your [API key](/iroh-services/access).
+
+Here's how it works:
+
+1. **Your relay knows your project.** When Iroh Services provisions a relay, it tells the relay which of your project's API keys are allowed to use it. This allow-set is kept in sync as you create or revoke keys.
+2. **Your endpoint presents a token, not the key itself.** When you build an endpoint with the `iroh_services::preset()` builder and your API key, the SDK mints a short-lived, signed access token scoped to that endpoint's identity. The endpoint presents this token when it connects to the relay. Your API key never leaves your application.
+3. **The relay verifies and admits.** The relay checks that the token was signed by one of your project's allowed keys and hasn't expired, then admits the connection. An endpoint with no token, an expired token, or a token from a revoked key is refused at the handshake.
+
+A few things worth knowing:
+
+- **Revocation is live.** Delete an API key and its access is withdrawn from your relays right away, including connections that are already open. The relay will kick off clients using that key, and they won't be able to reconnect until they have a valid token again.
+- **Authentication is a toggle, not a different relay.** Turning authentication off from the dashboard tells the relay to admit any endpoint without a token. Turn it back on and the token check resumes for new connections. See [Turn authentication off](/iroh-services/relays/managed#turn-authentication-off).
+- **Turning authentication off doesn't make a relay discoverable.** Your relay is never listed or advertised anywhere. With authentication off, any endpoint that already knows the relay's URL can use it, but it still has to know the URL.
+- **Authentication is about access, not privacy.** All relay traffic is end-to-end encrypted regardless. Authentication controls *who may use* your relay; it doesn't change what the relay can see (it still can't read your traffic).
+
+Self-hosted relays you run outside of Iroh Services manage their own access, so this is handled for you only on managed relays. See [API Keys](/iroh-services/access) for where your key comes from.
+
## Deploy your own relay
-For full deployment steps, see the [managed relay guide](/iroh-services/relays/managed).
+Managed relays from Iroh Services **supply authentication by default**, and
+your endpoints authenticate to them with your project's API key. For that flow,
+and full deployment steps, see the [managed relay
+guide](/iroh-services/relays/managed).
## Why use dedicated relays in production?
diff --git a/images/relay-auth-toggle.png b/images/relay-auth-toggle.png
new file mode 100644
index 0000000..cc0f4ec
Binary files /dev/null and b/images/relay-auth-toggle.png differ
diff --git a/iroh-services/access.mdx b/iroh-services/access.mdx
index 2c97e3d..e8c2db0 100644
--- a/iroh-services/access.mdx
+++ b/iroh-services/access.mdx
@@ -3,7 +3,7 @@ title: "API Keys"
description: "Authenticate your endpoint to Iroh Services to push metrics and connectivity reports"
---
-API keys authenticate your endpoint to Iroh Services. Iroh itself is permissionless (connections between endpoints don't need authorization), so API keys only come into play when an endpoint pushes data into your project.
+API keys authenticate your endpoint to Iroh Services. Iroh itself is permissionless — connections between two endpoints never need authorization — but the resources in your project belong to you. Your API key is what lets an endpoint push data into your project and connect to your project's dedicated relays.
## What API keys authorize
@@ -11,10 +11,11 @@ API keys are required for:
- Uploading metrics from endpoints to your project
- Sending network diagnostics reports from endpoints to your project
+- Connecting to your project's [dedicated relays](/iroh-services/relays/managed), which require authentication by default
API keys are **not** required for:
-- Synchronizing data across relays
+- Connecting through the public relays
- [NAT traversal](/concepts/nat-traversal) connections to other iroh endpoints
## Get an API key
@@ -44,10 +45,15 @@ let client = Client::builder(&endpoint)
.await?;
```
-In production, load the key from a config file or environment variable instead of hardcoding it.
+In production, load the key from a config file or environment variable instead
+of hardcoding it.
-For a full walkthrough (creating an endpoint, naming it, and verifying it on the dashboard) see the [Iroh Services quickstart](/iroh-services/quickstart).
+For a full walkthrough (creating an endpoint, naming it, and verifying it on the
+dashboard) see the [Iroh Services quickstart](/iroh-services/quickstart).
## What's next
-Today, API keys gate access to metrics and net diagnostics uploads. Future versions may support per-resource permissions and time-based access control. If your use case needs that today, [contact us](https://n0.computer/contact).
+Today, API keys gate metrics and net diagnostics uploads and access to your
+dedicated relays. Future versions may support per-resource permissions and
+time-based access control. If your use case needs that today, [contact
+us](https://n0.computer/contact).
diff --git a/iroh-services/relays/managed.mdx b/iroh-services/relays/managed.mdx
index 89c487d..7640b5f 100644
--- a/iroh-services/relays/managed.mdx
+++ b/iroh-services/relays/managed.mdx
@@ -3,13 +3,14 @@ title: "Managed Hosting"
description: "Deploy and configure dedicated relay infrastructure through Iroh Services"
---
-import RelayEndpointConfig from '/snippets/relay-endpoint-config.mdx';
+import RelayPresetConfig from '/snippets/relay-preset-config.mdx';
-Managed relays are dedicated relay servers provisioned through the Iroh Services platform and operated by n0.computer. Unlike the [public relays](/iroh-services/relays/public), managed relays are exclusively yours: no shared traffic, no rate limits, and with uptime SLAs.
+Managed relays are dedicated relay servers provisioned through the Iroh Services platform and operated by n0.computer. Unlike the [public relays](/iroh-services/relays/public), managed relays are exclusively yours: authenticated by default, no shared traffic, no rate limits, and with uptime SLAs.
## What you get
- **Fully managed**: n0.computer handles operations, maintenance, and upgrades
+- **Authenticated by default**: only your project's endpoints can connect, authenticated automatically with your API key
- **Isolation**: your traffic only; no noisy neighbors
- **Version locking**: pin to a specific iroh version or run blue/green deployments
- **Multi-region & multi-cloud**: deploy across regions and providers for resilience
@@ -41,7 +42,7 @@ Once deployed, your relay URL will appear in the dashboard. Copy it; you'll need
Set your endpoint to use your dedicated relay URLs instead of the public relays:
-
+
### 5. Verify connectivity
@@ -49,6 +50,36 @@ Go to your project's **Relays** page to confirm your endpoints are connecting th

+## Authentication
+
+Managed relays **require authentication by default** — only your project's endpoints can connect. There's nothing extra to set up: when you build your endpoint with the [`preset()`](#4-configure-your-endpoint) and your API key, it authenticates automatically. For how this works under the hood, see [relay authentication](/concepts/relays#authentication).
+
+## Turn authentication off
+
+If you want any endpoint that has your relay's URL to be able to use it — not
+just your project's endpoints — you can turn authentication off in your relay's
+**Settings → Network Settings → Access Control**. Use the **Who may connect**
+dropdown, then **Save**.
+
+In the dashboard this control is labeled **Private** (authentication on — only
+your project's API keys may connect) and **Public** (authentication off).
+"Public" here means no API key is required to connect; it does not make your
+relay discoverable.
+
+
+
+Turning authentication off doesn't list or advertise your relay anywhere; an
+endpoint still has to know the URL to use it. The relay also keeps reporting its
+traffic and metrics to your dashboard either way.
+
+Be careful turning authentication off: any iroh endpoint that learns the URL can
+then use the relay, so it may be subject to abuse. We recommend keeping
+authentication on for production deployments and only turning it off for testing
+or development.
+
+Public relays still report their traffic and metrics to your dashboard; they
+just don't require your API key to connect.
+
## Recommended setup
For production, deploy at least two relays in different geographic regions. If one relay becomes unreachable, iroh automatically falls back to the next one in your list, so your peers will still find each other.
diff --git a/iroh-services/relays/public.mdx b/iroh-services/relays/public.mdx
index 235ee9c..3ee2ca0 100644
--- a/iroh-services/relays/public.mdx
+++ b/iroh-services/relays/public.mdx
@@ -5,6 +5,8 @@ description: "Free shared relays for development and hobby use"
iroh includes a set of public relays provided by [n0.computer](https://n0.computer), available to all iroh users at no cost. No setup required; they work out of the box.
+Public relays are open to every iroh endpoint and need no authentication. This is different from [managed relays](/iroh-services/relays/managed), which require authentication by default so only your project's endpoints can use them.
+
Public relays are suitable for **development and hobby use only**. For production, use [managed relays](/iroh-services/relays/managed).
## Support policy
diff --git a/snippets/relay-preset-config.mdx b/snippets/relay-preset-config.mdx
new file mode 100644
index 0000000..beb7a5f
--- /dev/null
+++ b/snippets/relay-preset-config.mdx
@@ -0,0 +1,41 @@
+Your dedicated relays require authentication by default. Your endpoint
+authenticates to them with your project's API key. The `iroh_services::preset()` builder handles
+this for you: it mints a short-lived access token scoped to your endpoint's key
+and configures the endpoint to use your relays.
+
+Add the `iroh-services` crate to your project:
+
+```bash
+cargo add iroh-services
+```
+
+Then build a preset and bind your endpoint with it:
+
+```rust
+use iroh::Endpoint;
+
+#[tokio::main]
+async fn main() -> anyhow::Result<()> {
+ // Build a preset pointing at your dedicated relays, authenticated with
+ // your project's API key. In production, load the key from a config file
+ // or environment variable instead of hardcoding it.
+ let preset = iroh_services::preset()
+ .relays([
+ "YOUR_RELAY_URL_US",
+ "YOUR_RELAY_URL_EU",
+ ])?
+ .api_secret_from_str("YOUR_API_KEY")?
+ .build()?;
+
+ // Bind the endpoint with the preset, then wait until it's online to
+ // confirm it has an authorized connection to a relay.
+ let endpoint = Endpoint::bind(preset).await?;
+ endpoint.online().await;
+
+ Ok(())
+}
+```
+
+
+ Custom relay URLs are available on Pro and Enterprise projects. On a free project, pass your API key to the preset without `relays(...)` to authenticate against the public relays and surface your relay traffic on the dashboard.
+