> Source: https://nexusatlas.dev/docs/concepts/architecture — Nexus Atlas developer documentation (Concepts). Converted from the HTML page; the page is canonical.

# Architecture & core tunnel

One daemon owns one TUN interface and a set of UDP sockets, one per underlay link. Everything between the TUN and the sockets — encryption, fragmentation, scheduling, probing — is designed around a single question: what happens when a link misbehaves? This page walks the data path and answers it at each stage.

## The data path

An application writes an IPv4 packet to the tunnel interface (`[interface] name`, e.g. `nexus0`). The daemon reads it, decides which peer owns the destination (longest-prefix match over each peer's `allowed_ips`), encrypts it for that peer, fragments it if it exceeds the link budget, hands the fragments to the scheduler, and the scheduler places them on a link. On the far side the same machinery runs in reverse. The inner MTU is `[interface] mtu` (default 1420 — 1500 minus tunnel overhead); packets above the fragment budget are split into fragments sharing an ID and reassembled at the peer, with a janitor expiring half-arrived buffers so they can never leak memory.

Two properties of the path are worth designing around:

- **All fragments of one packet ride one link.** The scheduler places packets, not fragments. Striping one packet's fragments across lossy links multiplies its loss probability (lose any fragment, lose the packet) and forces cross-path reordering — so it deliberately never happens. Cross-link distribution happens per packet, or per FEC shard in the [transport-class path](https://nexusatlas.dev/docs/concepts/qos), where parity makes it safe.

- **A wedged link cannot block the others.** Each link has its own send workers and a bounded queue (512 packets, drop-on-full, non-blocking): a saturated slow link sheds its own load instead of back-pressuring the TUN reader and stalling the whole bond.

## Encryption

Each peer relationship runs the **Noise IK** handshake — X25519 key agreement, ChaCha20-Poly1305 AEAD, BLAKE2s hashing — the same peer-reviewed construction family used by modern commercial VPNs. Node identity is a static Curve25519 keypair from `atlasd keygen`; decoded private keys live in zeroizing memory and a config file looser than mode 0600 draws a load-time warning.

- **Rekeying is make-before-break:** driven by `[crypto] rekey_interval_secs` (default 120) and/or `rekey_data_limit` (default 1 GiB), a fresh handshake is established beside the live session and both sides keep the previous keys warm for in-flight packets — measured at zero packet loss across rekeys in the end-to-end suite.

- **Simultaneous initiation is resolved deterministically** (no duelling sessions), stalled handshakes retry on a budget, and an initiator that goes unanswered for 10 seconds rolls its session and re-initiates — recovering from a lost handshake response without a restart.

- **Anti-replay** is a 1024-bit sliding window per session, checked after authentication. It doubles as the deduplication layer for the redundancy modes that intentionally send copies of a packet on several links.

- A protocol version byte is checked on every packet decode. There is no version negotiation: mixed protocol versions fail loudly at decode rather than corrupting silently, so plan fleet upgrades as an upgrade, not a drift.

## Links, endpoints and the art of staying reachable

Each `[[link]]` binds a UDP socket to a device (`SO_BINDTODEVICE`) and address. Peers are addressed positionally — `endpoint[i]` reaches the peer over link *i* — or explicitly via `endpoint_per_link` when each radio has its own point-to-point addressing. Then reality intervenes, and three mechanisms deal with it:

- **Endpoint roaming** (`[interface] endpoint_roaming`, default on, WireGuard semantics per link): an *authenticated* packet arriving from a new source address updates that peer's endpoint on that link. A node whose address changes mid-session — a vehicle re-associating to a different access point — keeps its tunnel without anyone restarting anything. Unauthenticated probes and keepalives can never steer an endpoint.

- **The rebind watchdog:** after three consecutive send errors a link's socket is torn down and rebuilt. A USB radio that un-enumerates and returns recovers without a daemon restart; if the configured bind address is temporarily gone, the rebind falls back to the device's current address and returns to the configured one the moment it reappears.

- **Persistent keepalive** (`[[peer]] persistent_keepalive`, seconds) keeps NAT pinholes and idle radio paths warm.

> **One rule worth memorising:** two links sharing the same `bind_device` and `bind_address` must set distinct `listen_port` values — the sockets both set `SO_REUSEPORT`, and the kernel would otherwise load-balance inbound datagrams between them, silently costing each link half its traffic. `atlasd config check` catches it.

## Address families

The *underlay* speaks both families: a link may bind an IPv6 address and peer endpoints may be bracketed IPv6 literals; probes, handshakes and roaming are family-agnostic, and a family-mismatched link/peer pair is warned about and skipped without disturbing other links. The *inner* tunnel data path is IPv4-only today — stated plainly on the [limitations page](https://nexusatlas.dev/limitations).

## Who is allowed to connect

Peers listed in the config are trusted by definition. What happens when a handshake arrives from an *unknown* key is the job of `[auth]` — default: reject. A hot-reloaded keyfile allowlist and an external decision hook are available for fleets that outgrow hand-edited peer lists, and every failure mode fails closed. The [peer authentication guide](https://nexusatlas.dev/guides/auth) covers all three providers.

## The operational surface around the tunnel

The daemon assumes it will run unattended and be asked awkward questions later. It writes a 1 Hz stats snapshot (`/tmp/atlas/<iface>.json`) that the CLI, dashboard and your tooling all read; keeps a persistent, size-capped [event journal](https://nexusatlas.dev/docs/api#journal) so "what happened at 14:32?" has an answer after the fact; feeds the systemd watchdog only while the data path is genuinely moving; and captures crashes locally — redacted, and never uploaded without an operator's explicit action. The details live in [Telemetry & observability](https://nexusatlas.dev/docs/concepts/telemetry).

## Embedding note

The engine is a library first: it can adopt an externally created TUN file descriptor and per-link sockets (the mechanism behind the Android `VpnService` port) and accepts a custom peer authenticator. If you are evaluating Atlas as a component rather than a daemon, raise it in your [access request](https://nexusatlas.dev/request-access) — the integration surface is broader than the config file.
