Files
2026-06-09 10:12:34 +03:00
..
2026-03-30 23:04:52 +03:00
2026-06-09 10:12:34 +03:00

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.exe
  • presence_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/rnsd and resources/reticulum/presence_bridge
  • Windows: resources/reticulum/rnsd.exe and resources/reticulum/presence_bridge.exe

and a small BUNDLE_READY marker. The build uses the current Python, bootstraps pip if needed, installs rns + lxmf + 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 x64
  • npm run electron:make-lin-dockerany 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). Uses linux/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 arm64
  • npm run electron:make-arm-dockernative 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 Windows
  • npm run electron:make-mac → only on macOS
  • npm 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 ships a default list of public TCPClientInterface hubs so matching qortal-hub namespaces can discover each other across the Internet without manual config edits. It enables Reticulum remote interface discovery with a bounded autoconnect limit, but does not emit AutoInterface LAN discovery by default. 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:

  • WAN bootstrap uses one or more curated public TCP hubs from the managed config
  • Reticulum remote interface discovery is enabled with autoconnect_discovered_interfaces = 8
  • LAN AutoInterface discovery is intentionally disabled in the managed config
  • A custom Reticulum config under userData/reticulum/config is 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-connected when at least one configured TCP hub is online
  • disconnected when WAN hubs are configured but currently offline
  • lan-only when 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 tries python3 / python on PATH when pip install rns lxmf has been run (no env var required).
  • Venv: electron/resources/reticulum-runtime/venv/ from npm 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:

  1. Downloads PyPA get-pip.py and runs it with --user --break-system-packages on Linux/macOS when the distro is PEP 668 “externally managed” (e.g. Ubuntu 24.04+), so bootstrap works without python3-pip / python3-venv.
  2. 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