Skip to content
Export

Architecture

Purpose of this document

This page explains how Reticulum-Go is structured, describing layers, control flow, persistence, and deployment patterns.

For package-level detail see Package map. For wire-level behavior see Transport and Interfaces.

Layered model

Reticulum-Go follows the same conceptual layers as Python Reticulum:

+-------------------------------------------------------------+
|  Application (your code, examples, control API clients)     |
+-------------------------------------------------------------+
|  Destination, Link, Resource, Channel, Buffer               |
+-------------------------------------------------------------+
|  Transport (routing, path table, announces, relay)        |
+-------------------------------------------------------------+
|  Interface (UDP, TCP, Auto, I2P, Backbone, WebSocket, QUIC) |
+-------------------------------------------------------------+
|  OS sockets, SAM, multicast, shared-instance multiplexer    |
+-------------------------------------------------------------+

Each layer depends downward only. Interfaces know nothing about application names. Destinations do not open raw sockets.

Runtime components

Daemon (cmd/reticulum-go)

The daemon is the long-running process most operators deploy. On startup it:

  1. Loads configuration from ~/.reticulum-go/config (or --config)
  2. Creates a node.Node which owns transport and interfaces
  3. Starts transport and registers each enabled interface
  4. Optionally attaches to a shared instance (share_instance)
  5. Applies the runtime sandbox (pkg/sandbox) unless disabled
  6. Optionally starts the control API on localhost
  7. Handles SIGHUP on Unix to hot-reload interface blocks

Shutdown on SIGINT or SIGTERM stops interfaces and flushes path persistence where configured.

Node (pkg/node)

Node is the embedder-facing orchestration type. It wires:

  • transport.Transport for routing
  • interfaces.Interface instances from config
  • sharedinstance.Instance when sharing one Reticulum process on a host
  • Optional discovery.InterfaceDiscovery when discover_interfaces is enabled
  • Network lifecycle hooks (OnNetworkAvailable, OnNetworkLost, RefreshPaths, ReloadInterfaces)

Library authors typically construct node.New(cfg) and call Start() rather than reimplementing transport registration.

Transport (pkg/transport)

Transport is the routing engine. It maintains:

  • A path table mapping destination hashes to next-hop interface and hop count
  • Registered destinations and their packet receivers
  • Link table entries for established sessions
  • Announce handlers and ingress or egress rate limits
  • Optional on-disk persistence for paths and known destinations

Every interface registers a callback that feeds inbound bytes into Transport.HandlePacket.

Interfaces (pkg/interfaces)

Interfaces translate between Reticulum packets and a physical medium. They handle:

  • IFAC mask and unmask on ingress and egress (pkg/common)
  • HDLC framing for TCP and backbone clients
  • Reconnect loops for TCP, UDP (opt-in), I2P, and backbone clients
  • Platform-specific socket options (IPv6 preference, bind addresses)

Factory entry point: interfaces.NewFromConfigWithContext.

Shared instance (pkg/sharedinstance)

When share_instance = yes, only one Reticulum process on a host should own the real interfaces. Other processes connect as clients over TCP or a Unix socket and multiplex packets through the owner. This mirrors Python behavior and uses msgpack RPC compatible with RNS 1.3.4 layouts.

Go CLI tools such as rgostatus dial this RPC. On Linux, Python rnsd defaults to a Unix abstract socket unless shared_instance_type = tcp. Setup for mixed Go and Python tooling is in CLI utilities.

Storage (internal/storage)

The daemon persists ratchets, identity blobs, destination tables, and related artifacts under ~/.reticulum-go/storage/. Library embedders can use the same paths or keep tables in memory with in_memory_path_table and in_memory_known_destinations.

Set in_memory_storage = yes (or RETICULUM_IN_MEMORY_STORAGE=1) for fully ephemeral operation: no transport identity file, no blackhole directory, no split-resource staging on disk, and no ~/.reticulum-go bootstrap. Empty ConfigPath with no RETICULUM_STORAGE_PATH also stays off disk. Soft caps (max_in_memory_*, soft_memory_limit) bound RAM growth under explicit in-memory storage.

Inbound packet flow

Wire bytes
    |
    v
Interface read loop
    |
    v
ProcessIncoming (IFAC verify, frame decode)
    |
    v
packetCallback -> Transport.HandlePacket
    |
    +-- PacketTypeAnnounce  -> path table update, handler dispatch
    +-- PacketTypeLink      -> link state machine
    +-- PacketTypeProof     -> proof handling
    +-- PacketTypeData      -> forward, relay, or deliver to Destination.Receive

Key functions (for code navigation):

  • BaseInterface.ProcessIncoming in pkg/interfaces/interface.go
  • Transport.HandlePacket in pkg/transport/transport.go
  • Transport.handleTransportPacket for data context routing

Outbound packet flow

Application sends via Destination or Link
    |
    v
Transport.SendPacket
    |
    v
Path lookup (may rewrap as header type 2 for multi-hop)
    |
    v
Packet.Serialize
    |
    v
Interface.ProcessOutgoing (IFAC mask)
    |
    v
Wire bytes

If no path exists, transport may emit path requests according to configuration and watched destinations.

Concurrency model

  • Each interface runs its own read loop (or shares a backbone hub poller).
  • Transport uses internal locking and channels to serialize table updates and forwarding.
  • Links run session goroutines for keepalive, request/response, and channel outlets.
  • Hot reload takes reloadMu on Node to swap interfaces without tearing down unrelated state.

Backbone I/O can consolidate many TCP sockets behind one epoll, kqueue, or io_uring hub (pkg/backbone). Configure with backbone_io in [reticulum].

Deployment patterns

Standalone node

One reticulum-go process with local interfaces. Suitable for gateways, radios, and servers.

[Internet or LAN] <--> UDP/TCP Interface <--> reticulum-go <--> Your app

Shared instance

Multiple processes, one interface owner. Useful when a single radio or tunnel must be shared.

App A ----\
App B -----+---- TCP/Unix shared instance ---- reticulum-go (interface owner)
App C ----/

Embedded library

A Go service links pkg/node directly. No daemon. The service loads config, starts Node, and registers destinations in-process.

Browser WASM

reticulum-wasm compiles transport and a WebSocket interface. JavaScript calls reticulum.init, connect, announce, and related functions exposed by pkg/wasm.

Control API sidecar

Non-Go applications talk HTTP and WebSocket to pkg/controlapi on localhost while the daemon owns transport. See Control API.

librns in-process

Native hosts link librns.so and call include/rns.h. Same stack as pkg/node, no separate daemon. Linux first. Odin hosts can use bindings/odin. See librns.

Firecracker microvm

microvm/ packages a static guest rootfs and a host vsock bridge for nested or isolated nodes. Default networking keeps clearnet on the host and pipes the guest over Firecracker vsock. See Firecracker microvm.

Persistence and state

State Default location Notes
Config ~/.reticulum-go/config INI format, Python-compatible keys
Path table storage/destination_table Optional RAM-only mode
Known destinations storage/known_destinations Loads Python-format files
Identities storage/identities/ Per-hash blobs
Ratchets storage/ratchets/ Forward secrecy material
Blackhole table storage/blackhole msgpack
Transport identity storage/transport_identity Used when transport enabled

Security boundaries

Cryptography is centralized in pkg/cryptography and pkg/identity. IFAC adds an optional outer authentication layer on interface frames. The runtime sandbox limits filesystem and privilege exposure after startup. Neither replaces correct key handling or network segmentation.

See Cryptography and Security.

Extension points

Extension Mechanism
Custom crypto for tests cryptography.SetProvider
Hardware signing identity.NewIdentityWithSigner with cryptography.Ed25519Signer
Embedder lifecycle node.Node hooks and control API lifecycle routes
New interface types Implement interfaces.Interface, register in fromconfig.go
Non-Go clients Control API (out-of-process), librns (in-process C ABI), bindings/odin, or bindings/dart (FFI and Control API)

Adding a new interface type or changing on-wire layouts requires coordinated updates across implementations and crossref vectors.

What this stack does not include

  • IP routing or DNS replacement
  • Built-in application protocols (LXMF, Nomadnet, and similar live in separate projects)
  • RNode firmware or serial radio drivers
  • Post-quantum algorithms

Those may integrate over Reticulum destinations and links but are out of scope for this repository.

R
Reticulum-Go

A Go implementation of the Reticulum Network Stack. Building the future of resilient, sovereign communications.

Implementation License: Apache-2.0

Follow Development

Links

Quad4 Software

Backed by Quad4 Software. Building privacy-first, secure, efficient software.

quad4.io
© 2026 Quad4 Software. All rights reserved.
Deployed using Coolify