# Yggdrasil: an encrypted IPv6 overlay that routes itself

> Yggdrasil is an early-stage Go implementation of a fully end-to-end encrypted IPv6 overlay network that builds its own routing tree from the peers you configure. It is aimed at people who want IPv6 connectivity and encryption between machines without running an IPv6 provider, and this article covers what it does, how to run it, and where it stops being the right tool.

**yggdrasil-network/yggdrasil-go** — An experiment in scalable routing as an encrypted IPv6 overlay network

- Repository: https://github.com/yggdrasil-network/yggdrasil-go
- Website: https://yggdrasil-network.github.io
- Stars: 5,433 · Forks: 351
- Language: Go
- License: NOASSERTION
- Published: 2026-09-22 · Updated: 2026-09-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/yggdrasil-network-yggdrasil-go

## What Yggdrasil gives you that plain WireGuard does not

WireGuard gives you a tunnel between endpoints you already know. Yggdrasil gives you an IPv6 address that other nodes can reach without either side knowing the other's location in advance. The README describes it as "a fully end-to-end encrypted IPv6 network" that is "self-arranging", and states plainly that IPv6 Internet connectivity is not required because it also works over IPv4. That combination is the point: you run one daemon per host, it creates a TUN adapter with an IPv6 address, and any IPv6-capable application on that host can talk to any other Yggdrasil node. The target user is someone who wants private IPv6 reachability across machines that sit behind NAT, on residential links, or on networks that will not hand out IPv6 prefixes. It is not a VPN in the usual sense: there is no central server, and no single peer sees all traffic. The README calls the project "early-stage", which is a fair warning about how much operational certainty you should expect.

## How the routing tree and peer links fit together

The daemon builds a spanning tree over the peer links you give it, and addresses are derived from node keys rather than assigned by a coordinator. The repository topics list a routing algorithm and a spanning tree, and the README says the network is self-arranging, so the topology is discovered from the peers each node is configured to contact. Traffic enters through the TUN adapter as IPv6 packets, gets encrypted end to end, and is forwarded hop by hop across the tree. The module list in go.mod shows the routing core is pulled in as github.com/Arceliar/ironwood rather than living entirely in this repository, which matters if you intend to audit the algorithm: the Go code here is the daemon, the platform plumbing, the config handling and the link transports. Those transports are visible in the dependency list too: quic-go for QUIC links, coder/websocket for WebSocket links, and the WireGuard packages for the Windows TUN path. The README does not document rollback behaviour, nor does it describe what happens to established connections when the tree changes, so treat topology churn as an area to test yourself rather than something the documentation settles.

## Installing Yggdrasil and running it for the first time

The README points to the project's Installation page for pre-built packages and notes that platform-specific wrappers, scripts and tools live in the contrib folder. If you build from source instead, you need Go 1.22 or later according to the README, though go.mod declares go 1.25.0, so a recent toolchain is the safer assumption. Clone the repository and run the build script:

```bash
./build
```

The build script honours GOOS and GOARCH, so cross-compiling is a matter of setting them, for example GOOS=linux GOARCH=mipsle ./build. Next, generate a configuration. The README offers two forms: HJSON, which is human-friendly and includes comments, and plain JSON for programmatic use.

```bash
./yggdrasil -genconf > /path/to/yggdrasil.conf
```

You then edit that file to add or remove peers and to change listen addresses or multicast addresses. Once peers are in place, start the daemon against the static file:

```bash
./yggdrasil -useconffile /path/to/yggdrasil.conf
```

If you would rather not keep a config file, the README documents an auto-configuration mode that uses sane defaults and random keys at each startup:

```bash
./yggdrasil -autoconf
```

Expect to need elevated privileges. The README says you will likely need to run it as a privileged user or under sudo unless you have permission to create TUN/TAP adapters, and notes that on Linux you can instead give the binary the CAP_NET_ADMIN capability. After it starts, the visible result is a TUN interface carrying an IPv6 address; other Yggdrasil nodes are then reachable over IPv6 from that host.

## The peer list is the operational burden

Auto-configuration is convenient, but it generates random keys at each startup, which means your node identity and therefore your address change between runs. For anything you intend to reach repeatedly, a static config file and a stable key are the practical choice, and that file is also where the real work sits: you must add peers. The README says only that you edit the file to add or remove peers and to modify listen addresses or multicast addresses. It does not supply a public peer directory in the repository, and it does not describe how to evaluate whether a peer is trustworthy or well connected. In practice this means bootstrapping is a manual, social process, and the quality of your connectivity depends on the peers you pick. A node with one dead peer on a laptop that moves between networks is a node that may not reach anything. This is the difference between Yggdrasil and a hosted overlay: nothing is provisioned for you, and no support contract covers a peer that stops answering.

## Where Yggdrasil is the wrong choice

If you need a documented, stable interface between your application and the routing layer, Yggdrasil is a poor fit. The README labels the project early-stage, and the routing core is an external module pinned to a pseudo-version in go.mod, so the algorithm can move independently of this daemon. There is no documented rollback procedure in the README, no stated compatibility guarantee for the wire protocol across releases, and no description of how existing sessions behave when the spanning tree changes. For a production service that needs predictable latency and a support path, that is a real gap. Yggdrasil also assumes you want IPv6 and an overlay address per host; if your requirement is a small number of fixed site-to-site tunnels with tight firewall policy, a direct WireGuard configuration is simpler to reason about and easier to audit. Finally, if your environment forbids TUN/TAP adapters or the CAP_NET_ADMIN capability, the README's own instructions do not give you a path forward.

## Compared with running WireGuard directly

The honest alternative is WireGuard, and the difference is not speed, it is who does the addressing and discovery. With WireGuard you write a config that names each peer's endpoint and allowed IPs; if a peer moves, you update the config or rely on a dynamic DNS name. With Yggdrasil you write a config that names peers to connect to, and the overlay derives addresses from keys and routes between them, so a peer that moves does not need its address rewritten. That is a genuine convenience for a mesh of machines on changing networks, and it is why the README can promise that IPv6-capable applications work without changes. The cost is that you have handed routing decisions to a spanning tree you did not design, and you cannot express per-connection policy the way a WireGuard AllowedIPs list does. If your topology is two or three fixed sites, WireGuard's explicitness is worth more than Yggdrasil's self-arrangement. If your topology is a shifting set of hosts that all need to reach each other, the trade flips.

## Maintenance cost, licence and what to check before upgrading

The last push to the repository was on 2026-06-19, and the most recent release in the list is v0.5.14 from the same date, preceded by v0.5.14-RC.1 on 2026-06-14 and v0.5.13 on 2026-02-24. That is a steady release cadence rather than a dormant project, but it is also a project that ships release candidates, so pinning a specific version and reading CHANGELOG.md before moving is the sensible pattern. Because the routing core is an external dependency, an upgrade of this daemon can pull in a different ironwood revision, so check go.mod diffs as well as the changelog. On licensing, the README states the code is released under LGPLv3 with an added exception taken from godeb, and that under certain circumstances the exception permits distributing binaries linked with this code without distributing Minimal Corresponding Source or Minimal Application Code. The README directs you to LICENSE for the details, and the repository's licence field is not a standard identifier, so read that file rather than assuming the exception covers your distribution model.

## Conclusion

Adopt Yggdrasil when you want an encrypted IPv6 address on a host and are willing to maintain a peer list: generate a config with ./yggdrasil -genconf, add peers, and run it under CAP_NET_ADMIN. Do not adopt it if you need a documented, stable routing contract or per-connection policy control; the README calls the project early-stage, and the routing implementation now lives in the Arceliar/ironwood module rather than in this repository. Verify first that the peers you intend to use are reachable and that you accept the licence exception's terms, since the code ships under LGPLv3 with an added exception whose scope is defined in LICENSE.

## FAQ

### Is the Yggdrasil network safe?

The README describes Yggdrasil as a fully end-to-end encrypted IPv6 network, so traffic between nodes is encrypted in transit. What it does not document is how to evaluate the peers you connect to, and the peer list is something you maintain yourself. Treat peer selection as your responsibility rather than something the project vets for you.

### How does the Yggdrasil network work?

Each host runs the daemon, which creates a TUN adapter with an IPv6 address and connects to the peers named in its configuration. The network is self-arranging and routes over a spanning tree built from those peer links, with addresses derived from node keys rather than assigned centrally. The README states that IPv6 Internet connectivity is not required because it also works over IPv4.

### How do I install Yggdrasil on Ubuntu?

The README does not give distribution-specific steps; it points to the project's Installation page for pre-built packages and notes that platform-specific wrappers and scripts live in the contrib folder. Building from source requires Go, then ./build, and running the daemon needs root, sudo, or the CAP_NET_ADMIN capability on Linux.

### How do I add peers to Yggdrasil?

Generate a configuration with ./yggdrasil -genconf, then edit the resulting yggdrasil.conf file to add or remove peers and to change listen addresses or multicast addresses. The README gives no public peer directory, so the peers you list are ones you obtain yourself.

### Does Yggdrasil need IPv6 from my ISP?

No. The README states that Yggdrasil does not require IPv6 Internet connectivity and that it also works over IPv4. The overlay itself carries IPv6 traffic between nodes.

## Sources

- [Issues](https://github.com/yggdrasil-network/yggdrasil-go/issues)
- [Project website](https://yggdrasil-network.github.io)
- [README](https://github.com/yggdrasil-network/yggdrasil-go/blob/develop/README.md)
- [Releases](https://github.com/yggdrasil-network/yggdrasil-go/releases)
- [yggdrasil-network/yggdrasil-go on GitHub](https://github.com/yggdrasil-network/yggdrasil-go)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/yggdrasil-network-yggdrasil-go
