Bundled Reticulum runtime (rnsd + presence_bridge)
Python source: electron/resources/presence_bridge.py (single source of truth, tracked in Git).
npm run bundle:reticulum and packaged apps place a copy under this folder as presence_bridge.py next to the frozen binaries.
End users do not install Python. Ship PyInstaller one-file executables built on the same OS and CPU architecture you release for:
rnsd/rnsd.exepresence_bridge/presence_bridge.exe
Build the binary (before electron:make*)
From the electron/ directory, with Python 3.9+ on PATH:
npm run bundle:reticulum
This runs scripts/run-build-rnsd-frozen.mjs, which invokes scripts/build-rnsd-frozen.py using python3, python, or on Windows py -3.
This writes:
- Linux / macOS:
resources/reticulum/rnsdandresources/reticulum/presence_bridge - Windows:
resources/reticulum/rnsd.exeandresources/reticulum/presence_bridge.exe
and a small BUNDLE_READY marker. The build uses the current Python, bootstraps pip if needed, installs rns + lxmf (for AutoInterface discovery) + pyinstaller into the current user site-packages, and writes scratch files under electron/.build/rnsd-frozen/ (gitignored).
Repeat on each platform you ship (Linux x64, Windows, macOS, Linux arm64, etc.); do not copy a binary built on one OS onto another.
Debian / Ubuntu: no python3-pip / python3-venv package is required for the frozen build path anymore, but you still need a normal Python 3.9+ install and network access the first time.
Packaging commands
The packaging scripts now bundle a native Reticulum binary before packaging and enforce that you build on the matching host OS/arch:
npm run electron:make-lin→ only on Linux x64npm run electron:make-lin-docker→ any host with Docker; builds Linux x64 AppImage + deb inside Debian 11 (bullseye) (~glibc 2.31) for broader compatibility than CI (ubuntu-22.04, ~2.35). Useslinux/amd64(Apple Silicon works via emulation, slower).npm run electron:make-lin-docker-appimage→ same Dockerized Linux x64 build path, but emits only the AppImage for faster testing.npm run electron:make-arm→ only on Linux arm64npm run electron:make-arm-docker→ native Linux arm64, or another host with Docker/Podman plus QEMU/binfmt arm64 emulation; builds Linux arm64 AppImage + deb inside Debian 11 (bullseye) (~glibc 2.31).npm run electron:make-arm-docker-appimage→ same Dockerized Linux arm64 build path, but emits only the AppImage for faster testing.npm run electron:make-win→ only on Windowsnpm run electron:make-mac→ only on macOSnpm run electron:make-local/npm run electron:pack→ current host only
npm run electron:make-all now intentionally fails with guidance, because a single local machine must not embed one OS's rnsd into another OS's app package.
For automated cross-platform builds use the GitHub Actions workflow:
.github/workflows/electron_cross_platform_builds.yml
Runtime (Electron)
The main process spawns rnsd with --config pointing at userData/reticulum (writable). The Reticulum bridge prefers the bundled presence_bridge executable and falls back to Python only in development. Logs also go to userData/logs/reticulum.log.
The managed config keeps local AutoInterface discovery enabled and also ships a default list of public TCPClientInterface hubs so matching qortal-hub namespaces can discover each other across the Internet without manual config edits. When the private mesh gateway is enabled, the managed Qortal Hub Mesh Listen interface is emitted on the same qortal-hub Reticulum network segment and publishes IFAC details inside the encrypted discovery payload for trusted peers.
Default WAN bootstrap
The app now treats worldwide Reticulum reachability as a built-in feature:
- LAN discovery still uses
AutoInterface - WAN bootstrap uses one or more curated public TCP hubs from the managed config
- A custom Reticulum config under
userData/reticulum/configis still preserved and overrides the managed default
The default hub list is curated in-app rather than scraped at runtime. That keeps startup deterministic and lets us rotate or expand endpoints later without redesigning the config format.
Reachability status
The bridge polls Reticulum interface stats and surfaces a coarse reachability state to the app:
hub-connectedwhen at least one configured TCP hub is onlinedisconnectedwhen WAN hubs are configured but currently offlinelan-onlywhen only local discovery is available
When WAN connectivity appears after startup, the bridge re-announces the local presence and call destinations so remote peers can discover the node without restarting the app.
Fallbacks (development)
- System Python: with
electron:start/ dev mode, if there is no frozen binary and no venv, the app triespython3/pythononPATHwhenpip install rns lxmfhas been run (no env var required). - Venv:
electron/resources/reticulum-runtime/venv/fromnpm run bundle:reticulum-venv(optional). - Force system Python in packaged builds:
QORTAL_RETICULUM_SYSTEM=1. - Disable system Python in dev (only frozen / venv):
QORTAL_RETICULUM_NO_SYSTEM=1.
First run in development (npm run electron:start)
If RNS is not already available, the Electron main process shows a small “Setting up networking” window and runs scripts/ensure-reticulum-for-dev.mjs, which:
- Downloads PyPA
get-pip.pyand runs it with--user --break-system-packageson Linux/macOS when the distro is PEP 668 “externally managed” (e.g. Ubuntu 24.04+), so bootstrap works withoutpython3-pip/python3-venv. - Runs
python3 -m pip install --user rns lxmf(same flag first on Linux/macOS).
Needs Python 3.9+ on PATH and network once. A frozen resources/reticulum/rnsd skips this entirely.
Skip: QORTAL_RETICULUM_SKIP_ENSURE=1.
You can still run node scripts/ensure-reticulum-for-dev.mjs manually from electron/ (verbose pip output unless RETICULUM_ENSURE_QUIET=1).
Disable
Set environment variable QORTAL_RETICULUM_DISABLE=1.
References
- Using Reticulum on your system
- PyPI:
rns,lxmf