57 | )
58 | }
59 |
--------------------------------------------------------------------------------
/src/app/docs/concepts/discovery/page.mdx:
--------------------------------------------------------------------------------
1 | # Discovery
2 |
3 | Discovery is the glue that connects a [Node Identifier](/docs/concepts/endpoint#node-identifiers) to something we can dial. Discovery services resolve NodeIds to either a home Relay URL or direct-dialing information. {{className: 'lead'}}
4 |
5 |
6 | More details on discovery in the discovery module [documentation](https://docs.rs/iroh/latest/iroh/discovery/index.html)
7 |
8 |
9 | Node discovery is an automated system for an [Endpoint](/docs/concepts/endpoint) to retrieve addressing information. Each iroh node will automatically publish their own addressing information with configured discovery services. Usually this means publishing which [Home Relay](/docs/concepts/relay#home-relay) a node is findable at, but they could also publish their direct addresses.
10 |
11 | ## Discovery Services
12 |
13 | There are four different implementations of the discovery service in iroh, all of which map NodeIds to addresses:
14 |
15 | | | Discovery Implementation | Description |
16 | | --- | --- | --- |
17 | | 1 | [DNS](#dns-discovery) | uses a custom Domain Name System server |
18 | | 2 | [Local](#local-discovery) | uses an mDNS-like system to find nodes on the local network |
19 | | 3 | [Pkarr](#pkarr-discovery) | uses Pkarr Servers over HTTP |
20 | | 4 | [DHT](#dht-discovery) | uses the BitTorrent Mainline DHT |
21 |
22 | By Default, iroh uses the DNS discovery system to resolve NodeIds to addresses. And can be configured to use any of the other discovery systems.
23 |
24 | ## DNS Discovery
25 | DNS performs node lookups via the standard DNS systems. To publish to this DNS server a PkarrPublisher is needed. Number 0 runs a public instance of the DNS discovery system
26 |
27 |
28 | DNS Discovery has has it's own [blog post](/blog/iroh-dns)!
29 |
30 |
31 | ## Local Discovery
32 | Local discovery adds the ability to scan local networks for other iroh nodes, using Local Swarm Discovery. This is useful for local networks, or for bootstrapping a network before a relay is available.
33 |
34 | Local Discovery is _not_ enabled by default, and must be enabled by the user. You'll need to add the `discovery-local-network` feature flag to your `Cargo.toml` to use it.
35 |
36 | ```toml
37 | [dependencies]
38 | # Make sure to use the most recent version here instead of nn. (at the time of writing: 0.32)
39 | iroh = { version = "0.nn", features = ["discovery-local-network"] }
40 | ```
41 |
42 | Then configure your endpoint to use local discovery concurrently with DNS discovery:
43 |
44 | ```rust
45 | use iroh::Endpoint;
46 |
47 | let ep = Endpoint::builder()
48 | .discovery_n0()
49 | .discovery_local_network()
50 | .bind()
51 | .await?;
52 | ```
53 |
54 | ## Pkarr Discovery
55 | The Pkarr resolver can perform lookups from designated [pkarr relay servers](https://github.com/Pubky/pkarr#servers) using HTTP. Read more about the pkarr project [here](https://github.com/Pubky/pkarr?tab=readme-ov-file#pkarr).
56 |
57 | ## DHT Discovery
58 | DHT discovery uses the [BitTorrent Mainline](https://en.wikipedia.org/wiki/Mainline_DHT) distributed hash table (DHT) to publish & resolve NodeIds.
59 |
60 | DHT Discovery is _not_ enabled by default, and must be enabled by the user. You'll need to add the `discovery-pkarr-dht` feature flag to your `Cargo.toml` to use it.
61 |
62 | ```toml
63 | [dependencies]
64 | # Make sure to use the most recent version here instead of nn. (at the time of writing: 0.32)
65 | iroh = { version = "0.nn", features = ["discovery-pkarr-dht"] }
66 | ```
67 |
68 | Then configure your endpoint to use DHT discovery concurrently with DNS discovery:
69 |
70 | ```rust
71 | use iroh::Endpoint;
72 |
73 | let ep = Endpoint::builder()
74 | .discovery_n0()
75 | .discovery_dht()
76 | .bind()
77 | .await?;
78 | ```
79 |
--------------------------------------------------------------------------------
/src/app/docs/concepts/endpoint/page.mdx:
--------------------------------------------------------------------------------
1 | # Endpoints
2 |
3 | An _endpoint_ is the main API interface to create connections to, and accept connections from other iroh nodes. The connections are peer-to-peer and encrypted, a [Relay](/docs/concepts/relay) server is used to make the connections reliable. Endpoints have a `NodeID` (the public half of an Ed25519 keypair) and the private key used to sign and decrypt messages.
4 |
5 | Generally, an application will have a single endpoint instance. This ensures all the connections made share the same peer-to-peer connections to other iroh nodes, while still remaining independent connections. This will result in more optimal network behaviour.
6 |
7 | Somewhere in a program that uses iroh for direct connections, you'll see code like this:
8 |
9 | ```rust
10 | use iroh::Endpoint;
11 |
12 | #[tokio::main]
13 | async fn main() {
14 | let endpoint = Endpoint::builder().bind().await.unwrap();
15 | // ...
16 | }
17 | ```
18 |
19 | Breaking that down the `builder` sets up configuration for the endpoint, and `bind` creates the endpoint and starts listening for incoming connections. The `await` keyword is used to wait for the endpoint to be created in an asynchronous context.
20 |
21 | Once you have an endpoint, you can use it to create connections to other nodes, or accept incoming connections from other nodes.
22 |
23 | ## Node Identifiers
24 |
25 | Each endpoint in iroh has a unique identifier (`NodeID`) created as a cryptographic key. This can be used to globally identify a node. Because `NodeIDs` are cryptographic keys, they are also the mechanism by which all traffic is always encrypted for a specific node only.
26 |
27 | See the [NodeID](https://docs.rs/iroh/latest/iroh/type.NodeId.html) documentation for more info.
28 |
29 | ## Connections
30 |
31 | Because we're in a peer-2-peer context, either node might be operating as the "server", so we use `connect` and `accept` to distinguish between the two. The `connect` method is used to create a new connection to a remote node, while `accept` is used to accept incoming connections from a remote node.
32 |
33 | Connections are full-fledged QUIC connections, giving you access to most features of QUIC / HTTP3, including bidirectional and unidirectional streams.
34 |
35 |
36 | Due to the light-weight properties of QUIC streams a stream can only be accepted once the initiating peer has sent some data on it.
37 |
38 |
39 | ## Building on Endpoints
40 |
41 | Endpoints are a low-level primitive that iroh exposes on purpose. For some projects like [dumbpipe](https://dumbpipe.dev), endpoints are 95% of what you need to connect any two devices on the planet. For others, like [iroh-blobs](/proto/iroh-blobs), endpoints are the foundation that higher-level protocols are built on. Most projects will not work with endpoints beyond constructing one and feeding it to one or more [protocols](/docs/concepts/protocol).
42 |
--------------------------------------------------------------------------------
/src/app/docs/concepts/page.mdx:
--------------------------------------------------------------------------------
1 | import { Resources, Resource } from '@/components/Resources';
2 |
3 | # Concepts
4 |
5 |
6 |
13 |
20 |
27 |
--------------------------------------------------------------------------------
/src/app/docs/concepts/protocol/page.mdx:
--------------------------------------------------------------------------------
1 |
2 | # Protocols
3 |
4 | Iroh is organized into _protocols_: Composable networking software built on iroh connections. {{className: 'lead'}}
5 |
6 |
7 | The foundation of iroh is direct connections, which protocols use to extend up to higher-level functionality. When integrating iroh into an application you can use protocols to quickly add functionality, or write your own protocol(s) to maintain total control over how your application communicates.
8 |
9 | ## ALPN identifiers
10 |
11 | Iroh builds on QUIC connections, and uses [application level protocol negotiation](https://datatracker.ietf.org/doc/html/rfc7301) (ALPN, a widely used and well specified TLS extension) to run multiple protocols on the same QUIC endpoint. An ALPN identifier is the string that identifies the protocol and is used for protocol negotiation between endpoints. For example, the [iroh-blobs](/proto/iroh-blobs) protocol ALPN is [`/iroh-bytes/4`](https://github.com/n0-computer/iroh-blobs/blob/124820698cd85691e0d72aeed6e1ac028886b34a/src/protocol.rs#L353).
12 | This makes sure that an endpoint that accepts a connection can gracefully indicate whether it supports the requested protocol.
13 | [In the future](https://github.com/n0-computer/iroh/issues/2949) you'll be able to use multiple ALPN identifiers when connecting as a way to negotiate e.g. protocol versions. For example, you would connect using `/iroh-bytes/5` as well as `/iroh-bytes/4`, and the other side could respond with `/iroh-bytes/4` to indicating it doesn't have support for `/iroh-bytes/5`.
14 |
15 |
16 | ## The Accept Loop
17 |
18 | The accept loop is the main loop of an iroh server. It listens for incoming connections, and then processes them. The accept loop is the entry point for all iroh protocols, and is where you can add your own protocol to the iroh stack.
19 |
20 | Coming from the world of HTTP servers, the accept loop is similar to the main loop of an HTTP server. The main difference is that the accept loop is more flexible, as it can run multiple protocols on the same endpoint. Normally HTTP servers hide the raw accept loop from you, and instead route to the correct handler based on the URL. In iroh, the accept loop is exposed to you, and you can use it to route to the correct protocol based on the ALPN.
21 |
--------------------------------------------------------------------------------
/src/app/docs/concepts/router/page.mdx:
--------------------------------------------------------------------------------
1 |
2 | ## Router
3 |
4 | To make composing protocols easier, iroh includes a _router_ for composing together multiple protocols. {{className: 'lead'}}
5 |
6 | The router implements the [accept loop](/docs/concepts/protocol#the-accept-loop) on your behalf, and routes incoming connections to the correct protocol based on the [ALPN](/docs/concepts/protocol#alpns). We recommend using the router to compose protocols, as it makes it easier to add new protocols to your application.
7 |
8 | We use the term _router_ because it mimics what an HTTP server would do with an URL-based router.
9 |
10 | ```rust
11 | use anyhow::Result;
12 | use iroh::protocol::Router;
13 | use iroh::Endpoint;
14 | use iroh_blobs::net_protocol::Blobs;
15 | use iroh_blobs::util::local_pool::LocalPool;
16 |
17 |
18 | #[tokio::main]
19 | async fn main() -> Result<()> {
20 | // Build an endpoint, defaulting to the public n0 relay network
21 | let endpoint = Endpoint::builder().discovery_n0().bind().await?;
22 |
23 | // configure the blobs protocol to run in-memory
24 | let blobs = Blobs::memory().build(&endpoint);
25 |
26 | // Build our router and add the blobs protocol,
27 | // identified by its ALPN. Spawn the router to start listening.
28 | let router = Router::builder(endpoint)
29 | .accept(iroh_blobs::ALPN, blobs)
30 | .spawn();
31 |
32 | // get our own address. At this point we have a running router
33 | // that's ready to accept connections.
34 | let addr = router.endpoint().node_addr().await?;
35 |
36 | // Wait for exit
37 | tokio::signal::ctrl_c().await?;
38 |
39 | // Gracefully close the endpoint & protocols.
40 | // This makes sure that remote nodes are notified about possibly still open connections
41 | // and any data is written to disk fully (or any other shutdown procedure for protocols).
42 | router.shutdown().await?;
43 |
44 | Ok(())
45 | }
46 | ```
47 |
48 | You can add whatever protocols you need to the router, multiplexing them all over the same endpoint.
49 |
--------------------------------------------------------------------------------
/src/app/docs/examples/page.mdx:
--------------------------------------------------------------------------------
1 | import { Examples } from '@/components/Examples'
2 |
3 | # Examples
4 |
5 | Learn by examining practical code examples. We try to collage together examples to show a broad range of platforms & techniques while working with iroh.{{className: 'lead'}}
6 |
7 |
8 | The [iroh examples repo](https://github.com/n0-computer/iroh-examples) has a grab bag of extra examples. Post an issue there if you have a request for a specific example, or [join the discord](https://iroh.computer/discord).
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/app/docs/examples/todos/page.mdx:
--------------------------------------------------------------------------------
1 |
2 | # TODOs example
3 |
4 | https://github.com/n0-computer/iroh-tauri-todomvc
5 |
6 | ## Tauri
7 |
--------------------------------------------------------------------------------
/src/app/docs/layout.jsx:
--------------------------------------------------------------------------------
1 | 'use client';
2 |
3 | import Link from 'next/link';
4 | import {usePathname} from 'next/navigation';
5 | import {motion} from 'framer-motion';
6 |
7 | import {Footer} from '@/components/Footer';
8 | import {Prose} from '@/components/Prose';
9 | import {Header} from '@/components/Header';
10 | import {Logotype} from '@/components/Logotype';
11 | import {Navigation} from '@/components/Navigation';
12 | import {SectionProvider} from '@/components/SectionProvider';
13 |
14 | export const navItems = [
15 | {
16 | title: 'Getting Started',
17 | links: [
18 | {title: 'Overview', href: '/docs/overview'},
19 | {title: 'Quickstart', href: '/docs/quickstart'},
20 | {title: 'Tour', href: '/docs/tour' },
21 | {title: 'Examples', href: '/docs/examples'},
22 | ],
23 | },
24 | { title: 'Concepts',
25 | links: [
26 | {title: 'Endpoint', href: '/docs/concepts/endpoint'},
27 | {title: 'Relay', href: '/docs/concepts/relay'},
28 | {title: 'Discovery', href: '/docs/concepts/discovery'},
29 | {title: 'Protocol', href: '/docs/concepts/protocol'},
30 | {title: 'Router', href: '/docs/concepts/router'},
31 | {title: 'Ticket', href: '/docs/concepts/tickets'},
32 | ],
33 | },
34 | {title: 'Resources',
35 | links: [
36 | {title: 'Protocol Registry', href: '/proto'},
37 | {title: 'Write your own Protocol', href: '/docs/protocols/writing'},
38 | {title: 'Awesome List', href: 'https://github.com/n0-computer/awesome-iroh'},
39 | {title: 'FAQ', href: '/docs/faq' },
40 | {title: 'Wasm/Browser Support', href: '/docs/wasm-browser-support' },
41 | ],
42 | },
43 | ];
44 |
45 | export default function DocsLayout({children, sections = {}}) {
46 | const pathname = usePathname();
47 | sections = sections[pathname] || [];
48 |
49 | return (
50 |
51 |
77 |
78 | );
79 | }
80 |
--------------------------------------------------------------------------------
/src/app/docs/overview/page.mdx:
--------------------------------------------------------------------------------
1 | export const metadata = {
2 | title: 'Overview',
3 | description:
4 | 'A high-level description of what iroh is',
5 | };
6 |
7 |
8 | # Overview
9 |
10 | Iroh lets you establish direct peer-to-peer connections whenever possible, falling back to relay servers if necessary.
11 | This gives you fast, reliable QUIC connections that are authenticated and encrypted end-to-end. {{className: 'lead'}}
12 |
13 |
14 | ## Iroh is "dial by public key"
15 |
16 | In the iroh world, you dial another node by its `NodeId`, a 32-byte ed25519 public key. Unlike IP addresses, this ID is globally unique, and instead of being assigned, you can cheaply generate as many as you want yourself. It also doesn't change when you change networks.
17 | You won't have to think about NATs getting in your way, iroh traverses them for you.
18 | Basing connections on asymmetric public keys is what allows iroh to *always* end-to-end encrypt and authenticate connections.
19 |
20 |
21 | ## Peer to peer
22 |
23 | Iroh is built on peer-to-peer QUIC using both relays and holepunching.
24 |
25 | Peers must know the NodeId of a peer before connecting to it.
26 | They verify this NodeId during the connection handshake to provide end-to-end encryption and authentication.
27 |
28 | Peer to peer connectivity is established with the help of a relay server.
29 | On startup peers register their NodeId with a home relay server.
30 | The relay server provides assistance to traverse firewalls,
31 | NATs or others alike.
32 | If no direct connection can be established,
33 | the connection is relayed via the server.
34 |
35 | Peers can also connect directly without using a relay server.
36 | For this,
37 | however,
38 | the listening peer must be directly reachable by the connecting peer via one of it's addresses.
39 |
40 |
41 | ## Iroh is built on QUIC
42 |
43 |
44 | This gives iroh super-powers:
45 | - encryption & authentication
46 | - stream multiplexing
47 | - no head-of-line blocking issues
48 | - stream priorities
49 | - one shared congestion controller
50 | - an encrypted, unreliable datagram transport
51 | - zero round trip time connection establishment if you've connected to another node before
52 |
53 | A single QUIC connection can power all of your protocol's complex interactions:
54 | - Stream both video and audio without video packet loss affecting audio. Prioritize audio by increasing that stream's priority.
55 | - Use the unreliable datagram transport for your game's state and input networking. Also re-use the same connection for streaming assets or real-time audio or video.
56 | - Avoid unnecessary network round-trips when your phone comes back from suspension with zero round trip time connection establishment.
57 |
58 |
59 | ## The higher level: Give your users agency back
60 |
61 | Iroh bootstraps a new internet: Your user's home computer is as inter-connected as a virtual private server.
62 | There might not be a need for intermediaries if their powerful smartphone can accept incoming connections like any other service.
63 |
64 | This gives users back power and agency to use their devices the way they want to.\
65 | No need to fight for static IP addresses from your ISP.\
66 | No need to buy domain names to participate in the internet.\
67 | No need to set up complicated TLS certificates to get what should be a *baseline* feature: Encryption.
68 |
69 | ## Want to see where iroh's headed?
70 |
71 | See [our roadmap](/roadmap) to find out what's planned.
72 |
--------------------------------------------------------------------------------
/src/app/docs/page.mdx:
--------------------------------------------------------------------------------
1 | import {Resources, Resource} from '@/components/Resources'
2 | import {HeroPattern} from '@/components/HeroPattern'
3 |
4 | export const metadata = {
5 | title: 'Documentation',
6 | description:
7 | 'Learn about Iroh and how to integrate into your own project.',
8 | }
9 |
10 | export const sections = [
11 | {title: 'Resources', id: 'resources'},
12 | ]
13 |
14 |
15 |
16 | # Iroh Documentation
17 |
18 | Iroh lets you establish direct peer-to-peer connections whenever possible, falling back to relay servers if necessary.
19 | This gives you fast, reliable connections that are authenticated and encrypted end-to-end using QUIC. {{className: 'lead'}}
20 |
21 |
22 |
23 |
24 |
25 | ## Getting started {{anchor: false}}
26 |
27 | The best place to start is by reading the overview, a high level look at the problems iroh solves. {{className: 'lead'}}
28 |
29 |
30 |
36 |
37 |
38 |
39 |
46 |
53 |
60 |
61 |
--------------------------------------------------------------------------------
/src/app/docs/reference/glossary/page.mdx:
--------------------------------------------------------------------------------
1 | # Glossary
2 |
3 | A set of commonly used terms in the iroh ecosystem.{{className: 'lead'}}
4 |
5 | | Term | Definition |
6 | | ---- | ---------- |
7 | | [**Blob**](/docs/layers/blobs) | A piece of data stored in the iroh network. Blobs are immutable, content-addressed (refer by hash), and opaque. |
8 | | [**Document**](/docs/layers/document) | A mutable piece of data stored in the iroh network. Documents are content-addressed (refer by hash), and can be read and written to. |
9 | | **DocID** | A unique identifier for a document in an iroh network. A docID is the public half of a keyPair. |
10 | | **NodeID** | A unique identifier for a node in an iroh network. A nodeId is a keyPair |
11 | | [**Ticket**](/docs/concepts/tickets) | A single serialized token containing everything needed to kick off an interaction with another node running iroh. |
12 |
--------------------------------------------------------------------------------
/src/app/docs/tour/1-endpoints/page.mdx:
--------------------------------------------------------------------------------
1 | import { PageLink } from '@/components/PageNavigation';
2 |
3 | # 1. Endpoints
4 |
5 | The journey of a connection starts with an endpoint. An endpoint is one of the two termination points for a connection. It’s one of the tin cans that the wire is connected to. Because this is peer-2-peer, endpoints both _initiate_ *and* _accept_ connections. The endpoint handles both.
6 |
7 | Let's first add iroh to our project. From the project root run `cargo add iroh` to install the latest version:
8 |
9 | ```bash
10 | $ cargo add iroh
11 | Updating crates.io index
12 | Adding iroh v0.32.1 to dependencies
13 | Features:
14 | + metrics
15 | - discovery-pkarr-dht
16 | - discovery-local-network
17 | - examples
18 | - test-utils
19 | Updating crates.io index
20 | Locking 432 packages to latest compatible versions
21 | ```
22 |
23 | We're also going to need a few supporting libraries so let's add those as well:
24 |
25 | ```bash
26 | cargo add tokio anyhow rand
27 | ```
28 |
29 | In the end your `Cargo.toml` file's `[dependencies]` section should look something like this. It's ok if the version numbers are slightly different:
30 |
31 | ```toml
32 | [dependencies]
33 | anyhow = "1.0.95"
34 | iroh = "0.32.1"
35 | rand = "0.8.5"
36 | tokio = "1.43.0"
37 | ```
38 |
39 | ## Starting an Endpoint
40 |
41 | With our dependencies added, open up `src/main.rs` and add the following code:
42 |
43 | ```rust
44 | #[tokio::main]
45 | async fn main() -> anyhow::Result<()> {
46 | // Create an endpoint
47 | let builder = iroh::Endpoint::builder();
48 |
49 | // bind it to a socket
50 | let endpoint = builder.bind().await?;
51 |
52 | // print this endpoint's node id
53 | println!("node id: {:?}", endpoint.node_id());
54 |
55 | // exit the program
56 | Ok(())
57 | }
58 | ```
59 |
60 |
61 | Then save and run your program with `cargo run`. You should see output similar to this:
62 |
63 | ```bash
64 | b5 at number-0 in ~/code/iroh-tour (main●)
65 | $ cargo run
66 | Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.80s
67 | Running `/Users/b5/.cargo/build/debug/iroh-tour`
68 | node id: PublicKey(95224c92856163add8a9cb68a81183aa5d9881c4def58625a9f4266a0743b479)
69 | ```
70 |
71 |
72 | This code just prints it's ID & exits. For a more complete example, check out the [connect example](https://github.com/n0-computer/iroh/blob/main/iroh/examples/connect.rs)
73 |
74 |
75 | The non-setup part of this program adds up to 3 lines of code, and one of them is a print statement! The first line constructs an endpoint. 99% of apps will have a single endpoint in the entire app, so you’ll build the endpoint once, and refer to it a bunch. Then we call *bind* to ask the operating system for a networking port. This calling bind will kick off work in the background that we’ll talk about in a bit.
76 |
77 | Those three lines are the beating heart of adding iroh to an app. Once the node ID prints we have an active endpoint that's ready to connect & (if configured to) accept connections. Everything else builds up from here.
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/src/app/docs/tour/3-discovery/page.mdx:
--------------------------------------------------------------------------------
1 | import { PageLink } from '@/components/PageNavigation';
2 |
3 | # 3. Discovery
4 |
5 | Discovery is the glue that connects a [Node Identifier](/docs/concepts/endpoint#node-identifiers) to something we can dial. There are a few different types of discovery services, but for all of them you put a `NodeID` in, and get back either the home relay of that node, or IP addresses to dial.
6 |
7 | There are different implementations of the discovery service in iroh, the most popular of which are DNS & Local Discovery. DNS uses the same domain name system that connects "example.com" to an IP address to map node ids to relay servers, and local discovery uses your local network to find nodes to talk to on local WiFi, even if that WiFi network doesn’t have a wider internet connection.
8 |
9 | ### DNS Discovery
10 |
11 | First, let's add the n0 DNS discovery service as a default:
12 |
13 | ```rust
14 | use iroh::{Endpoint, RelayMode};
15 |
16 | #[tokio::main]
17 | async fn main() -> anyhow::Result<()> {
18 | let builder = Endpoint::builder()
19 | .relay_mode(RelayMode::Default)
20 | .discovery_n0();
21 |
22 | let endpoint = builder.bind().await?;
23 |
24 | println!("node id: {:?}", endpoint.node_id());
25 | Ok(())
26 | }
27 | ```
28 |
29 | Now when this endpoint boots up, it will list itself on the n0 DNS service. From here we can pass along the node identifier, and other nodes can use the n0 DNS service to find the home relay of this node.
30 |
31 | ### Local Discovery
32 |
33 | Local discovery has the extra trick of being able to actually find new nodes on the local network. Before we can do that, we need to add the `discovery-local-network` feature to our `Cargo.toml` file:
34 |
35 | ```
36 | cargo add iroh --features discovery-local-network
37 | ```
38 |
39 | This will change our `Cargo.toml` file `[dependencies]` section to look like this:
40 |
41 | ```toml
42 | [dependencies]
43 | anyhow = "1.0.95"
44 | iroh = { version = "0.32.1", features = ["discovery-local-network"] }
45 | rand = "0.8.5"
46 | tokio = "1.43.0"
47 | ```
48 |
49 | And with that we can set up local discovery:
50 |
51 | ```rust
52 | use iroh::{Endpoint, RelayMode, SecretKey};
53 |
54 | #[tokio::main]
55 | async fn main() -> anyhow::Result<()> {
56 | let builder = Endpoint::builder()
57 | .relay_mode(RelayMode::Default)
58 | .discovery_n0()
59 | .discovery_local_network()
60 |
61 | let endpoint = builder.bind().await?;
62 | println!("node id: {:?}", endpoint.node_id());
63 | Ok(())
64 | }
65 | ```
66 |
67 | Here we’ve added discovery to the endpoint constructor, passing in our two discovery services, and that’s it, iroh will now use these two services to get something it can dial for a given node ID.
68 |
69 |
70 | For an example of this in action, check out the [local discovery example](https://github.com/n0-computer/iroh/blob/main/iroh/examples/locally-discovered-nodes.rs).
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/src/app/docs/tour/4-protocols/page.mdx:
--------------------------------------------------------------------------------
1 | import { PageLink } from '@/components/PageNavigation';
2 |
3 | # 4. Protocols
4 |
5 | At this point, we’re connected, yay! Now we just have to… do something… with that connection. That’s where protocols come in.
6 |
7 | Protocols are modules you compose together to add functionality to connections. Protocols exist for file transfer, game server sync, message broadcasting, document collaboration, all kinds of stuff. You can use off-the-shelf protocols to quickly add functionality, work directly with QUIC streams & build a fully custom protocol that does exactly what you want, or fork an existing protocol to get what you need.
8 |
9 | Coming from the world of HTTP client/server models, protocols are kinda like request handlers, but they can go beyond request/response creating multiple streams of data and usually code up both initiating & accepting protocol connections in the same.
10 |
11 | Protocols are an ever-growing topic, but to give you a basic let's add the [blobs](/proto/iroh-blobs) protocol. First we need to add it to our depdendencies:
12 |
13 | ```
14 | cargo add iroh-blobs --features=rpc
15 | ```
16 |
17 | then adjust our code:
18 |
19 | ```rust
20 | use iroh::{protocol::Router, Endpoint};
21 | use iroh_blobs::net_protocol::Blobs;
22 |
23 | #[tokio::main]
24 | async fn main() -> anyhow::Result<()> {
25 | let endpoint = Endpoint::builder().discovery_n0().bind().await?;
26 |
27 | let blobs = Blobs::memory().build(&endpoint);
28 |
29 | // build the router
30 | let router = Router::builder(endpoint)
31 | .accept(iroh_blobs::ALPN, blobs.clone())
32 | .spawn();
33 |
34 | router.shutdown().await?;
35 |
36 | Ok(())
37 | }
38 | ```
39 |
40 |
41 | This code doesn't actually _do_ anything with the blobs protocol. For a real-world example, check out [sendme](https://github.com/n0-computer/sendme)
42 |
43 |
44 | This code sets up everything we need to both provide data we have locally when others request it, and ask other nodes that run the blobs protocol for data. Starting at the top, we first construct the endpoint, then we construct an instance of the blobs protocol, then add a _router_ (more on that in a minute) that listens for blobs protocol connections.
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/src/app/docs/tour/5-routers/page.mdx:
--------------------------------------------------------------------------------
1 | import { PageLink } from '@/components/PageNavigation';
2 |
3 | # 5. Routers
4 |
5 | Most apps will use more than one protocol. A router let’s you stack protocols on top of iroh's peer-to-peer connections. Routers handle the *accept* side of an iroh endpoint, but the connection initiation side is still handled by the protocol instance itself.
6 |
7 | Since we've already set up a router when adding iroh blobs, we can add another protocol to the router with a few lines of code. Let's add iroh gossip, first by installing the dependency:
8 |
9 | ```
10 | cargo add iroh-gossip
11 | ```
12 |
13 | Then we can setup gossip & add it to our router:
14 |
15 | ```rust
16 | use iroh::{protocol::Router, Endpoint};
17 | use iroh_blobs::net_protocol::Blobs;
18 | use iroh_gossip::{net::Gossip, ALPN};
19 |
20 | #[tokio::main]
21 | async fn main() -> anyhow::Result<()> {
22 | let endpoint = Endpoint::builder().discovery_n0().bind().await?;
23 |
24 | let blobs = Blobs::memory().build(&endpoint);
25 |
26 | let gossip = Gossip::builder().spawn(endpoint.clone()).await?;
27 |
28 | // build the router
29 | let router = Router::builder(endpoint)
30 | .accept(iroh_blobs::ALPN, blobs.clone())
31 | .accept(iroh_gossip::ALPN, gossip.clone())
32 | .spawn();
33 |
34 | router.shutdown().await?;
35 | Ok(())
36 | }
37 | ```
38 |
39 | The amount of code is small, but the conceptual shift is a nice-to-have, wrapping an endpoint in a router makes the design intent of iroh clear: set up an endpoint, pull in protocols, feed them to the router, and bind your way to glory.
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/src/app/docs/tour/6-conclusion/page.mdx:
--------------------------------------------------------------------------------
1 | import { PageLink } from '@/components/PageNavigation';
2 |
3 | # 6. Things iroh doesn’t do out of the box
4 |
5 | Before we go, let’s talk through a little of what iroh *doesn’t* cover:
6 |
7 | ### Magically keep nodes online
8 | First, iroh doesn’t magically ensure the device you’re trying to dial is online. It doesn’t buffer messages & wait until you turn your phone back on. The technical term for this is “network churn”, and programming around the reality that nodes can come online & go offline whenever they want is the core concern of all distributed systems programming.
9 |
10 | ### Obscure your IP address
11 | Second, iroh doesn’t obscure your IP address. nodes accepting connections will know your IP address. This is one of the biggest reason we think that iroh should be a library that users build into apps that have an in-built sense of trust. Keep in mind: sharing IP addresses is common practice in the wild, nearly all of major video conferencing tools do this. Video games do this. Heck, Spotify used to do this. And keep in mind, seeing your IP address is a thing traditional servers *always* have access to.
12 |
13 | ### Peer Signaling
14 | Lastly, iroh doesn’t yet come with a built-in peer signaling mechanism, that is, a way to get alice’s node id to bob. This seems like a massive oversight, but it’s on purpose: different apps have different opinions about how peers should learn about each other. In some cases it’s as simple as storing NodeIDs in an app database & passing them out as API responses. In other cases it’s local discovery only, or using tickets to encode dialing details + protocol invocations in a single string. We'll talk through patterns for peer signaling in future docs.
15 |
16 | ## Conclusion
17 |
18 | This concludes the iroh tour! Now that you understand a bit of iroh here are some next steps:
19 | * check the [examples](/docs/examples)
20 | * [join the discord](https://iroh.computer/discord)
21 | * have a look through the iroh [awesome list](https://github.com/n0-computer/awesome-iroh)
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/app/docs/tour/page.mdx:
--------------------------------------------------------------------------------
1 | import { PageLink } from '@/components/PageNavigation';
2 |
3 | # A Tour of iroh
4 |
5 | Let's take a tour of iroh! This tutorial will touch on 5 core concepts and a few supporting ideas that will get you familiar with what iroh does and how it works.
6 |
7 | We're going to do this tutorial in rust, so the first thing we'll need to do is confirm you have a working rust environment. If you don't, you can install it by following the instructions at https://www.rust-lang.org/tools/install for your operating system.
8 |
9 | Once you're up & running, let's create a new rust project by running the following command in your terminal:
10 |
11 | ```bash
12 | cargo new iroh-tour
13 | ```
14 |
15 | This will create an empty rust project in a new directory called `iroh-tour`. Change into that directory and open it in your favorite code editor. You should be able to run it from the project root, run it with `cargo run` and see something like this:
16 |
17 | ```bash
18 | $ cargo run
19 | Compiling iroh-tour v0.1.0 (/Users/b5/code/iroh-tour)
20 | Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.69s
21 | Running `/Users/b5/.cargo/build/debug/iroh-tour`
22 | Hello, world!
23 | ```
24 |
25 | ## Overview
26 |
27 | Here's a high level overview of how everything fits together:
28 |
29 | Iroh is a library for establishing the most direct QUIC connection possible between two devices. Every _endpoint_ uses the public half of a cryptographic keypair to identify itself. Assuming at least one configured _relay server_ is reachable, an endpoint keeps exactly one TCP connection to a “home relay” that other nodes use for connection establishment, and as a fallback transport. Iroh uses a suite of _discovery services_ to resolve home relays & endpoint IDs. Connections between endpoints use QUIC ALPNs to distinguish between _protocols_, while _routers_ automate the endpoint accept loop for protocol multiplexing.{{ className: 'lead' }}
30 |
31 | This paragraph touches on five key points worth understanding in iroh:
32 |
33 | * [Endpoints](/docs/tour/1-endpoints)
34 | * [Relays](/docs/tour/2-relays)
35 | * [Discovery](/docs/tour/3-discovery)
36 | * [Protocols](/docs/tour/4-protocols)
37 | * [Routers](/docs/tour/5-routers)
38 |
39 | We'll touch on each of these on the tour, and by the end you should have a good understanding of how they all fit together. The code we'll be writing here will build & execute, but it won't _do_ much. We'll link to examples and other resources along the way so you can explore further.
40 |
41 |
50 |
--------------------------------------------------------------------------------
/src/app/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0-computer/iroh.computer/3befb7792ea49b0bfdeceaf4b9895d4937e56597/src/app/favicon.ico
--------------------------------------------------------------------------------
/src/app/layout.jsx:
--------------------------------------------------------------------------------
1 | import glob from 'fast-glob';
2 | import Script from 'next/script';
3 |
4 | import {Providers} from '@/app/providers';
5 | import '@/styles/tailwind.css';
6 |
7 | export const metadata = {
8 | metadataBase: new URL('https://www.iroh.computer'),
9 | title: {
10 | template: '%s - Iroh',
11 | default: 'docs, guides, and examples',
12 | },
13 | openGraph: {
14 | title: 'iroh',
15 | description: 'less net work for networks',
16 | images: [{
17 | url: '/api/og?title=iroh&subtitle=less net work for networks',
18 | width: 1200,
19 | height: 630,
20 | alt: 'iroh. less net work for networks',
21 | type: 'image/png',
22 | }],
23 | type: 'website'
24 | }
25 | };
26 |
27 | export default async function RootLayout({children}) {
28 | let pages = await glob('**/*.mdx', {cwd: 'src/app'});
29 | let allSectionEntries = await Promise.all(
30 | pages.map(async (filename) => [
31 | '/' + filename.replace(/(^|\/)page\.mdx$/, ''),
32 | (await import(`./${filename}`)).sections,
33 | ]),
34 | );
35 | let allSections = Object.fromEntries(allSectionEntries);
36 |
37 | return (
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
Iroh Protocols are pluggable extensions that build on direct connections. Like HTTP server middleware on steroids! Mix & match for fast, flexible, functionality.
42 | Iroh is a dial-any-device networking library that just works. Compose from an ecosystem of ready-made protocols to get the features you need, or go fully custom on a clean abstraction over dumb pipes. Iroh is open source, and already running in production on hundreds of thousands of devices.
43 | To get started, take a look at our docs, dive directly into the code, or chat with us in our discord channel.
44 |