Reticulum up close: a network stack where the address is a key
Reticulum is not a messenger, not a VPN and not a "network for shady business". It is a complete network stack in which the address is a key fingerprint, encryption has no off switch, and the carrier can be a LoRa radio, a piece of wire or ordinary TCP. This note takes it apart layer by layer: from the bits in the packet header to the board on the desk. The radio physics underneath is in the LoRa deep dive.
What problem it solvesβ
To understand Reticulum, first look at the assumptions the ordinary internet rests on. It is not universal β it is optimised for a particular world. Reticulum is built for the opposite one.
The name is Latin: reticulum, "little net". Its author, Mark Qvist, started from a simple question: what must a network have if you take away providers, address registries, certificate authorities and the assumption that the channel is always wide? It turned out almost everything had to be rewritten β from addressing to the packet format. The author dedicated the protocol itself to the public domain back in 2016; the reference Python implementation is distributed under its own Reticulum License.
| the ordinary internet assumes | Reticulum assumes | what follows |
|---|---|---|
| The channel is fast and cheap: megabits, millisecond latency | The channel may be 250 bit/s with latency in seconds | A packet is 500 bytes. Every extra header byte costs real time on air |
| Addresses are handed out by a hierarchy: IANA β regional registry β provider β DHCP | Addresses are computed by the nodes themselves from their own key | No registration, no lease, and no way to take an address away |
| DNS gives names, certificate authorities give trust | No DNS, no CA. The address is the credential | Addresses are exchanged outside the network: a QR code, a slip of paper, an announcement on air |
| Nodes are always online, connections are the norm | A node may come on once a day | Store-and-forward is needed, not just live sessions |
| The carrier is Ethernet or Wi-Fi, frames are large | The carrier is anything that can move a byte: radio, wire, a pipe, TCP | The stack deliberately knows nothing about the physics beneath it |
Reticulum is not a replacement for the everyday internet and does not compete with it on speed. It competes with the situation where there is no network at all β or there is one, but it belongs to someone else, is slow and is controlled. Those are different contests.
Three ideas that hold everything upβ
There will be plenty of detail below, but all of it grows out of exactly three decisions.
idea one
The address is a key fingerprint
Not "I was given an address" but "I computed the hash of my public key, and that is my address". It follows at once that forging an address is the same as forging a key, and nobody can take it away, because nobody gave it in the first place.
idea two
Encryption is not optional
The stack has no "unencrypted" mode for an ordinary destination. No need to enable TLS, buy a certificate or agree on keys: whoever knows the address already knows the public key, because the address is made from it.
idea three
The stack does not care what it rides on
It needs one thing from the carrier: "take this block of bytes and try to deliver it". Radio, a serial cable, a TCP connection, a sound card β all the same. So one network can ride partly over LoRa and partly over the internet.
Since the address already contains the key and encryption is built in, Reticulum needs no handshake just to send something. A packet can be encrypted for a stranger and thrown into the air without asking anything or waiting for a reply. This mode will be called "opportunistic" below.
Identity and address: where <a4f1β¦> comes fromβ
The most important five minutes of the whole text: once it is clear how an address comes out of a key, the rest is just consequences.
An identity is two key pairsβ
On the first run of any Reticulum application an Identity is created β not a login and not an account, just two generated sets of keys:
X25519
For key exchange
Lets two parties compute a shared secret without ever sending it over the air. The key that encrypts the content is derived from it.
Ed25519
For signatures
Lets you prove a packet really comes from this sender. A signature is 64 bytes; it cannot be forged without the private key.
The public halves of both keys together are exactly 64 bytes. That is all the network needs to know about a participant.
Then β two rounds of hashingβ
Four destination types
| type | what it means |
|---|---|
| SINGLE | Addressed to one identity, encrypted for its public key β only it can read it. This type is used almost everywhere |
| GROUP | A shared symmetric key handed out to members in advance. Whoever has the key reads everything |
| PLAIN | No encryption at all. For service things where there is nothing to hide β a beacon, a public relay |
| LINK | The address of a live session β see the Link section below. Exists only while the session is alive |
Numbers worth remembering
- keys β 32 + 32 = 64 bytes of public part
- hash β SHA-256 truncated to 128 bits = 16 bytes
- name β hash of the application name, 10 bytes
- signature β 64 bytes (Ed25519)
- address β 16 bytes = 32 hex characters
About collisions. 128 bits is about 3.4 Γ 10Β³βΈ possible addresses. They do not coincide by chance, and finding one on purpose is serious work in its own right.
Packet anatomy: all 500 bytesβ
The packet shows the whole philosophy. When the channel gives 250 bit/s, every header byte is real milliseconds on air and real milliamps from the battery. So the header is indecently ascetic: two bytes of control fields β and straight to the address.
What is inside the first byteβ
Eight bits holding everything the stack must know about a packet before it even starts parsing it:
Four packet types β and that is the whole protocolβ
| type | code | what for |
|---|---|---|
| DATA | 0x00 | The data itself. Everything that is not a control packet is DATA |
| ANNOUNCE | 0x01 | "I exist, here is my key". The only way to get into other nodes' path tables |
| LINKREQUEST | 0x02 | A request for a session with ephemeral keys |
| PROOF | 0x03 | Cryptographic proof: "I received this". A delivery confirmation that cannot be forged |
In TCP/IP the IPv4 header is 20 bytes, TCP another 20, and that is before any TLS. Here the overhead is 19 bytes for everything together, address and cryptographic context included. On a 250 bit/s channel the difference between 19 and 60 bytes is the difference between "arrived" and "did not make it".
How a node is found: announceβ
The address is computed β but the network knows nothing about it. There is no DNS, no registry, no server to "sign up" with. There is exactly one mechanism: the node shouts an announce into the air, and everyone who hears it remembers which way to go to reach it.
An announce carries: the destination address, 64 bytes of public keys, the application name hash, a random hash (so two identical announces do not look the same), a signature β and optionally a small piece of application data, such as the name a messenger will show in its list.
| node | who it learned to reach | forward via | hops | when it learned |
|---|---|---|---|---|
| B | a4f1c8e0β¦88d29d2c | the source (directly) | 1 | +1.9 s |
| C | a4f1c8e0β¦88d29d2c | B | 2 | +3.5 s |
| D | a4f1c8e0β¦88d29d2c | B | 2 | +3.5 s |
| E | a4f1c8e0β¦88d29d2c | C | 3 | +5.1 s |
| F | a4f1c8e0β¦88d29d2c | E | 4 | +6.7 s |
| G | a4f1c8e0β¦88d29d2c | E | 4 | +6.7 s |
And if there is no path yet?
Then a path request for the wanted address goes into the network, and nodes that know it reply. It is the flip side of announce: announce says "I am here", a path request asks "where is this one?". That is why a messenger sometimes thinks for a few seconds before the first message to a new contact β it is looking for the way.
Paths do not last for ever
An entry has an expiry time. If a node has not been heard from for a long time, the path is forgotten, and next time the way has to be found again. So nodes that want to be found repeat their announce now and then, while those who do not want extra attention stay quiet and walk the network themselves.
An announce is public by design, otherwise the node could not be found. So anyone within earshot sees that such an address exists and sees its public key. The content of messages stays closed, but the fact "this node is on the network" does not. Reticulum never promised anonymity.
Transport: who actually relaysβ
A detail almost everyone misses: not every node relays other people's traffic. By default a node serves only itself.
For a node to become a transport node, enable_transport = Yes must be set explicitly in its configuration. Such a node takes on the postman's job: it keeps path tables, moves packets from interface to interface and stitches a radio segment to an internet segment. Transport nodes are what turn a set of isolated islands into a network.
ordinary node
Only for itself
Receives and sends its own packets. It sees other people's but does not carry them. This is the phone in your pocket.
transport node
The network's postman
Forwards other people's traffic, keeps paths, connects different carriers. Usually something running round the clock: a Raspberry Pi, a VPS, a box in the attic with an antenna.
propagation node
Also holds the mail
A transport node that has additionally agreed to store messages for those who are not on the network right now. More on it in the LXMF section.
Interface modes β a tool few people know aboutβ
Every interface can be given a mode, and that changes how announces spread through it and how paths are built. This is how a narrow radio link avoids being flooded with control traffic from a wide internet channel.
| mode | behaviour | typical case |
|---|---|---|
| full | Everything by default: announces go both ways, paths are built freely | A home network, an ordinary link |
| access point | An interface for "clients" that relay nothing themselves | An entry point for nearby phones |
| point-to-point | A dedicated link between exactly two nodes | A radio bridge between two hills |
| roaming | A link that comes and goes; the stack takes that into account | A node in a car, a phone on the move |
| boundary | A border between segments: not everything is let through | The junction of slow radio and fast internet |
An interface can be given an Interface Access Code β a shared secret. Then nodes without the code do not merely fail to join: they do not even recognise the traffic as Reticulum. That is how several independent networks that cannot see each other coexist on one frequency.
Link: a session with keys that will later vanishβ
So far it has been about single packets: encrypt for someone's public key, throw it into the air, forget. That works, but it has a weak spot: if someone records all the air and one day obtains the recipient's private key, they can decrypt everything recorded retroactively. Link was invented against exactly that.
what else a link is for
Delivery confirmation
A PROOF is not a "tick in a messenger" but cryptographic proof: only whoever really received the packet could have signed it. "Delivered" cannot be forged.
what else a link is for
You can introduce yourself
By default the sender on a link is anonymous even to the other party. If you wish, you can explicitly identify β sign the session with your permanent identity. It is a separate action, not a side effect.
what else a link is for
Large transfers
Resources (next section) ride on top of a link: there is room there for progress, retries and requests for missing parts.
For a short message, setting up a session is a waste of airtime. Then the opportunistic mode works: one packet, encrypted for the recipient's permanent key, thrown into the network with no handshake. Cheap, but no confirmation and no forward secrecy. For this case Reticulum added ratchets β keys that are "turned" regularly so that single packets cannot be read retroactively either.
Resources: when there is more data than 500 bytesβ
A photo, a file, a page with pictures do not fit in one packet. There is a separate mechanism for that β the Resource. It does not just cut data into pieces: it survives losses without starting over.
Interfaces: what it really rides onβ
The stack knows nothing about physics. It only knows an "interface" β a thing that can take a block of bytes and try to deliver it; the rest is driver detail. So one node can hold radio, cable and TCP at the same time, and for the network it is all one seamless fabric.
AutoInterface
LAN, zero configuration
Finds others via IPv6 multicast on the same network. Enable it on two laptops on the same Wi-Fi β and they already see each other. The fastest way to try Reticulum with no hardware at all.
Speed: as fast as the local network
TCPClient / TCPServer
Over the ordinary internet
Connects two network segments over TCP. That is how the public testnet nodes work: a local radio island joins the worldwide network with one line in the config.
Speed: whatever the channel gives
RNodeInterface
LoRa radio over USB
The very case the whole thing was started for: no provider, no wire. The board connects as an ordinary serial device, and the stack sets the frequency, bandwidth and spreading factor itself.
Speed: 0.25β5.5 kbit/s
KISS / AX.25
Good old amateur radio
Reticulum can ride on an ordinary TNC and an amateur radio β including on HF, where the signal goes around the planet. Indecently slow, but range is measured in continents.
Speed: 300β9600 baud
SerialInterface / Pipe
Bytes over any wire
Two devices joined by a cable. Or a pair of wired modems. Or even someone else's program that can move a byte stream β Reticulum will ride on that too.
Speed: whatever you set
I2PInterface
When you also need to hide
Reticulum rides inside I2P. The node has no public IP, no domain and no port that can be blocked β and its addressing stays its own.
Speed: slow, but inconspicuous
Hardware: RNode and radio physicsβ
This is where software ends and things no code can get around begin: the antenna, the terrain and the laws of radio propagation.
What an RNode isβ
An RNode is an open radio modem design: a microcontroller plus a LoRa chip, flashed with special firmware. It is built from cheap development boards (T-Beam, Heltec, RAK and others). To the stack it is just a serial device; to its owner, a standalone node that runs on a battery and asks nobody for anything.
Why LoRa hears what "cannot be heard"β
LoRa sends data not as a steady tone but as a whistle of rising frequency β a chirp. The receiver knows the exact shape of that whistle, so it pulls it out even when the signal is weaker than the noise on air. The price is time: the more "stretched" the whistle (the higher the spreading factor), the farther it is heard and the slower data goes. In detail β in the LoRa deep dive.
| spreading factor | speed, 125 kHz | range | a 500-byte packet on air |
|---|---|---|---|
| SF7 | β 5.5 kbit/s | shortest | under a second |
| SF9 | β 1.8 kbit/s | medium | β 2 seconds |
| SF12 | β 250 bit/s | longest | β 16 seconds |
The numbers are approximate: speed also depends on bandwidth and coding rate, and time on air on the overhead. But the order is right: going from SF7 to SF12 costs roughly a twentyfold slowdown.
How much really gets throughβ
The most common disappointment looks like this: a LoRa network is up, a photo is sent β and it takes an hour. Here are honest numbers so that does not happen. The size slider shows any case of your own.
| what is sent | SF12 Β· 250 bit/s | SF7 Β· 5.5 kbit/s | verdict |
|---|---|---|---|
| Text message, 1 KiB | β 33 s | β 1.5 s | Comfortable even in the slowest mode |
| Nomad Network page, 8 KiB | β 4.4 min | β 12 s | Readable if the page is text |
| Voice note, 1 min compressed, 15 KiB | β 8 min | β 22 s | Tolerable at SF7, not at SF12 |
| Photo, 200 KiB | β 1 h 49 min | β 5 min | Only when really needed and there is no hurry |
| Video | β | β | No. And there will not be: it is not a matter of optimisation |
The conclusion is not "LoRa is bad" but "LoRa is for text". The long-range mode does not exist to move megabytes but to get a message 30 kilometres across a mountain where nothing else works.
LXMF: mail that can wait for the recipientβ
Reticulum by itself has no notion of a "message" β it carries packets. Messengers on top of it speak a separate format, LXMF. That is what makes sure a message waits for a person who switches their radio on once a day.
What is inside an LXMF message
- to β the destination address (16 bytes)
- from β the sender's address
- signature β so the sender cannot be spoofed
- content β time, title, text and arbitrary fields; attachments go here too
Message states in the client are not decoration: "sent" means "went into the network", and "delivered" is set only when a PROOF comes back.
How spam is fought here
Classic filters are impossible: a node cannot see the content. So LXMF uses "stamps": the sender has to spend a little computation for their message to be accepted. For a living person it is unnoticeable, for a mailing to a million addresses ruinously expensive.
Plus the usual: known contacts can be exempt from stamps, strangers can be asked for a more expensive one.
What Reticulum does not doβ
The quickest way to be disappointed in a tool is to expect from it what it never promised.
- β Does not anonymise. Announces are public, destination addresses are visible to transport nodes, and on shared radio you can see who went on air and when. The content is closed, the fact of communication is not.
- β Has no global names. There is nothing like DNS. The other party's address has to come from somewhere: a QR code, a slip of paper, an announcement on air, a shared directory node.
- β Does not guarantee delivery by itself. A guarantee appears only where there is a PROOF or a resource with retries. A packet sent "opportunistically" can simply vanish.
- β Does not carry the ordinary web. HTTP and the browser will not come here: a 500-byte MTU is another world. Instead of the web there is Nomad Network with its own lightweight page markup.
- β Does not replace the everyday internet. Streaming, calls, clouds β no. Text, positions, small files, device control β yes.
And it is not Meshtastic β the most common confusion, because their hardware is the same.
Reticulum and Meshtastic: same board, different ideasβ
| question | Meshtastic | Reticulum |
|---|---|---|
| What it is | A finished product: group chat and GPS over LoRa | A general-purpose network stack on which people write their own applications |
| Carrier | LoRa only | Anything: LoRa, radio, wire, TCP, I2P |
| Routing | Managed flooding within a small group of nodes | Path tables, up to 128 hops, stitching different carriers together |
| Address | 4 bytes from the board's MAC address | A 16-byte hash of a key, globally unique |
| Encryption | Channel key for groups; per-node keys for private messages | End-to-end to a specific identity, always |
| Who it suits | "Switch on and it works" for a group in the mountains | Those building their own network or an application for it |
Both projects are alive and both run on the same cheap boards: Meshtastic gives a ready-made scenario, Reticulum a construction kit. You can try both on one board just by changing the firmware.
Practice: up and running in an eveningβ
The cheapest way to understand it is to run it. The first step needs no hardware at all: two computers on the same Wi-Fi are enough.
Step 1 β install the stack
# the stack itself and its utilities
pip install rns
# the daemon: holds interfaces and paths
rnsd
# what the interfaces are doing right now
rnstatus
# the path to an address and how many hops
rnpath <hash>
# ping a transport node
# (it must have respond_to_probes enabled)
rnprobe rnstransport.probe <hash>
# fetch a file from a remote node
rncp --fetch ~/file.txt <hash>
Step 2 β the config
It lives in ~/.reticulum/config. Here is a node that is on the local network, on radio and on the worldwide network at once:
[reticulum]
enable_transport = No
share_instance = Yes
[interfaces]
[[Default Interface]]
type = AutoInterface
interface_enabled = True
[[LoRa]]
type = RNodeInterface
interface_enabled = True
port = /dev/ttyUSB0
frequency = 867200000
bandwidth = 125000
txpower = 7
spreadingfactor = 8
codingrate = 5
[[Public hub]]
type = TCPClientInterface
interface_enabled = True
target_host = amsterdam.connect.reticulum.network
target_port = 4965
Frequency and power are set according to your region's rules β that is not advice but the law. Current public entry points are in the project documentation: they change.
Step 3 β flash a board when you get to radio. Connect the board over USB, then follow the utility's prompts:
rnodeconf --autoinstall
What to put on topβ
messenger
Sideband
Android, iOS, desktop. The simplest way in: after installation an identity is generated and you see the contacts that have announced themselves on the network.
web interface
MeshChat
A handy browser dashboard: messages, files, a node map, interface status.
terminal
Nomad Network
A text interface in the spirit of a BBS: pages with their own markup, files, boards. The best feel of "another network".
Glossaryβ
- Identity β a pair of key pairs (X25519 + Ed25519), a persona. A file worth guarding: it cannot be recovered from anywhere.
- Destination β an address: 16 bytes of hash of the identity and the application name. What you give to the other party.
- Aspect β part of the application name, e.g.
lxmf.delivery. Determines who inside the node gets the packet. - Announce β the "I exist, here is my key" packet. The only way into other nodes' path tables.
- Path β a table entry: "to reach this address, hand it to this neighbour". It has an expiry time.
- Transport node β a node explicitly allowed to relay other people's traffic. Without them the network falls apart into islands.
- Link β a session with one-time keys. Gives forward secrecy, delivery confirmation and resources.
- Proof β a signed proof of receipt. "Delivered" cannot be forged.
- Resource β the mechanism for data larger than a packet: compression, slicing, a hashmap, targeted retries.
- Interface β a carrier driver: AutoInterface, TCP, RNode, KISS, Serial, I2P. The stack essentially does not tell them apart.
- IFAC β an interface access code. Other nodes do not even recognise the traffic as Reticulum.
- MTU / MDU β the packet size ceiling (500 bytes) and what remains for payload after the header.
- LXMF β the message format on top of Reticulum. What messengers actually speak.
- Propagation node β a node that holds encrypted mail while the recipient is offline. It has no keys.
- RNode β an open LoRa modem design: a cheap board plus firmware. To the stack, an ordinary serial device.
- Spreading factor β how "stretched" the radio signal is. Higher means heard farther and slower data.
The speeds here are calculated; specific configuration parameters are worth checking against the project documentation.
- LoRa up close β the physical layer: chirps, spreading factor, time on air, range
- Meshtastic up close β a ready-made chat on "raw" LoRa: managed flooding, channels, node roles
- Four internets β Reticulum, I2P, Yggdrasil and Nostr side by side: who sits on which floor
