I got Thinkleet.net Off-Grid running and wrote up the short version: what it is, how to connect, done. This is the long version. If you actually want to build one of these yourself, RNode and all, this is the post that gets into why it works the way it does instead of just telling you which buttons to press.
Reticulum, Explained Like You Already Know What a Public Key Is
Reticulum is Mark Qvist's networking stack, and the thing that makes it worth understanding instead of just using is that it throws out almost everything TCP/IP assumes. No IP addresses. No DNS. No routing tables you maintain by hand. No assumption that a "network" is one continuous physical thing. Every participant on a Reticulum network is identified by a cryptographic Identity, a public/private keypair generated locally the first time a program runs. Nobody assigns it to you. Nobody can take it away. It's just math you happened to generate.
From an Identity, a program derives one or more Destinations: named endpoints an Identity can send to or receive on, each with its own hash derived from the Identity's public key plus an application namespace. NomadNet's page-serving destination, for instance, lives under the nomadnetwork.node aspect. LXMF messaging destinations live under a different one. Same Identity, different mailboxes, and nothing about the addressing scheme cares whether the underlying link is a TCP socket, a LoRa radio, a packet radio TNC, or a USB serial cable to a homebrew board sitting on your desk. Reticulum's interfaces abstract all of that away, and the same Destination hash means the same thing no matter which interface a packet arrived on.
Discovery happens through announces: a periodic broadcast that says "this Identity, and these Destinations, exist, and here's how to build an encrypted link to them." Every node that hears an announce can cache the path. Nodes that run with enable_transport = True also relay announces onward and answer path requests from other nodes that haven't heard one yet, which is how a network with no central authority still lets a brand-new node find its way to a Destination on the other side of the planet. This is the part that took me longest to internalize: there's no "connecting to the network." You're just listening, and eventually you hear enough to route.
Installing It
Reticulum ships as a Python package. On anything with Python 3 and pip:
pip install rnsCurrent release as of this writing is RNS 1.5.0, shipped August 22nd, and it's a substantial one. Priority-based ingress queueing on the transport core, per-interface protocol violation tracking, in-flight path request batching, a pile of rnstatus improvements for actually seeing what your node is doing traffic-wise. None of it changes how you configure an interface, but it's worth knowing the stack is under genuinely active development and not something that shipped once and went quiet.
First run generates a default config at ~/.reticulum/config, with empty [reticulum], [logging], and [interfaces] sections. Everything after this point is editing that file.
RNode: The Part With Actual Radio Hardware
NomadNet, LXMF, all of it, none of it requires radio hardware. You can run the entire stack over TCP, which is exactly what Thinkleet.net Off-Grid does right now. But the point of Reticulum is links that don't need the internet, and for LoRa that means an RNode.
RNode isn't a specific product. It's an open firmware and protocol spec that turns a supported LoRa development board into a KISS-style radio modem Reticulum can talk to over serial, TCP, or Bluetooth LE. Officially supported boards as of the current firmware line include the LilyGO T-Beam and T-Beam Supreme, T3S3, T-Deck, and LoRa32 v1/v2/v2.1, Heltec's LoRa32 v2/v3/v4 and T114, the RAK4631, the dual-transceiver OpenCom XL, and the LilyGO T-Echo, most running SX1262/SX1268 or SX1276/SX1278 radio chips. Boards in the $15 to $40 range, easy to find, and you're not locked into buying from any one vendor since the firmware is open and the hardware requirements are just "supported chip, enough flash."

Flashing one is a single command once Reticulum is installed:
rnodeconf --autoinstallIt walks you through picking the connected device, downloads the matching firmware, flashes it, and provisions it. rnodeconf -i after that shows you what you've got: firmware version, hardware model, radio chip. rnodeconf -u updates firmware later without re-flashing from scratch. It's genuinely one of the better hardware bring-up experiences I've had, and I've bring-up'd a lot of janky hardware for this blog.
Configuring the Interface
Once the RNode is flashed, it's just another interface block in ~/.reticulum/config:
[[RNode LoRa Interface]]
type = RNodeInterface
enabled = yes
port = /dev/ttyUSB0
frequency = 915000000
bandwidth = 125000
txpower = 17
spreadingfactor = 8
codingrate = 5frequency and txpower are the two that will get you a visit from your regulator if you get them wrong. 915 MHz is the US ISM band; check your own country's rules before touching this. spreadingfactor and codingrate trade throughput for range, same tradeoff every LoRa deployment makes: SF7 is fast and short-range, SF12 is glacial and can punch through a lot more path loss. bandwidth does something similar in the other direction. None of these are Reticulum-specific quirks, they're LoRa PHY parameters that Reticulum just exposes directly instead of hiding.
port doesn't have to be a serial device. RNode firmware also supports WiFi, so port = tcp://10.0.0.1 or a hostname works for a board that's not physically tethered to the machine running Reticulum, and port = ble:// connects to a paired Bluetooth LE RNode. Useful if the radio needs to live somewhere with better antenna placement than your server closet.
If you don't have LoRa hardware yet and just want to see traffic flowing, AutoInterface uses link-local IPv6 multicast to find other Reticulum instances on the same LAN with zero configuration, which is the fastest way to watch two machines talk to each other before you've bought anything.
Running a Site: NomadNet Nodes and Micron
NomadNet does two unrelated things under one roof. It's an LXMF messaging client, and it's a page server and browser for a text-only web built on a markup language called Micron. Enabling the node side is a config toggle:
[node]
enable_node = True
node_name = Your Node Name Here
announce_interval = 360
announce_at_start = True
node_announce_interval = 720Pages live as .mu files under NomadNet's storage directory, and Micron is deliberately primitive compared to HTML: headings, links, basic text formatting, no images, no CSS, no JavaScript. That's not a missing feature. A LoRa link at SF9 moves data in the low kilobits per second. An HTML page with a hero image would take longer to load than most people are willing to stand around for. Micron exists because the constraint is real, not because nobody got around to building something richer.
The Easy Entry: Mirroring a Ghost Blog
Hand-writing Micron pages for every post is not a thing I was going to do twice a week. What actually runs Thinkleet.net Off-Grid is reticulum-offgrid-mirror, a small project that watches a Ghost blog's RSS feed, converts each article's HTML to Micron, and writes it straight into a NomadNet node's pages directory. If you're already running Ghost, this is the fast path.
The mechanics: RSS only ever exposes the newest handful of posts, so the sync script backfills anything RSS never carried with a sitemap pass, and it keeps a small JSON state file so already-imported posts don't get reconverted every cycle. Once a post is in, it stays listed on the index even after it rolls off the live feed. Site-specific details, feed URL, sitemap URL, node title, intro text, the CSS classes needed to find an article's title and body when backfilling from a raw page, are all environment variables, not code changes, so pointing it at a different Ghost install is a docker-compose edit, not a fork.
The repo ships two real deployment examples instead of one canonical docker-compose file, because how you reach the wider Reticulum network varies. examples/nepamesh joins a sibling transport container's network namespace directly. examples/thinkleet, what my own setup is closer to, runs fully standalone with its own Reticulum config and an outbound TCPClientInterface to a public transport node. Pick whichever matches whether you already have a transport node running on the same host.
One operational gotcha worth knowing before you hit it yourself: NomadNet only scans its pages directory once, at startup. A sync that adds a brand-new page won't be servable until you restart the nomadnet container. Updates to existing pages don't need this, only genuinely new ones.
Communicating Off-Grid: LXMF Isn't Chat
The messaging half of NomadNet runs on LXMF, and the mental model that trips people up is expecting it to behave like a chat app. It doesn't. LXMF is store-and-forward. You compose a message to someone's Identity, and it either delivers directly if you have a live path to them right now, or it hands off to a propagation node, a peer that's agreed to hold messages for later pickup, the way an old BBS mail door held messages for whoever dialed in next. Neither party needs to be online at the same moment. That's the entire point on a network where "online" can mean "within LoRa range of a relay, sometime today."
This is a genuinely different communication model than real-time messaging, and it's the right one for the medium. You're not going to get sub-second delivery over a 915 MHz link running SF10 through three hops of forest. You're going to get delivery, eventually, without needing every intermediate node and both endpoints to be simultaneously reachable. For off-grid use, that's the trade you want.
Why a Backhaul Is Still Doing the Work Right Now
Here's the honest state of my own setup. Thinkleet.net Off-Grid's Reticulum instance runs a TCPServerInterface on port 4242 and a TCPClientInterface out to NEPAMesh's transport node. Both of those are internet links. There is currently no RNodeInterface configured, no radio hardware bridging this node onto LoRa. Reach it today and you're reaching it over the exact infrastructure this whole project is nominally an alternative to.

That's not a design flaw, it's just where the build is at. Reticulum's whole architecture makes this a non-issue to fix later: adding an RNode to the same Reticulum instance is one more interface block in the same config file, and every Destination the node already serves, every LXMF address, every mirrored article, becomes reachable over LoRa the moment that interface comes up, with zero changes to NomadNet, zero changes to the sync script, zero changes to anything except one config stanza and a board sitting in a USB port. The TCP backhaul isn't a placeholder implementation I'll rip out. It's one interface among what will eventually be several, and Reticulum was built specifically so that adding the next one doesn't touch the others.
An RNode is on the list. When it's flashed and the interface block goes in, I'll write that post too, and Thinkleet.net Off-Grid will mean it a little more literally.