Repository navigation
07 desktop linux
Short answer: yes. You cannot ship a single "browser binary" — the client is a browser app — but you can ship a native Debian package that bundles the app and runs it in a Chromium engine. Several routes exist; the right one depends on one constraint.
The mixnet client (@nymproject/mix-tunnel / mix-fetch) is a
Chromium-oriented WASM bundle: WebAssembly, Web Workers started from a blob
URL, and possibly SharedArrayBuffer (which requires cross-origin isolation).
Whatever runtime you pick must be Chromium-based, or you must verify the WASM
client works on it.
| Engine | Used by | Risk |
|---|---|---|
| Chromium / Blink | Chrome, Chromium, Electron, Brave, Edge, Android WebView | ✅ the compatibility target |
| Gecko | Firefox (supports WASM/Workers; no SharedArrayBuffer without special headers) |
|
| WebKit / WebKitGTK | Tauri, Wails, Safari, GNOME Web |
Because Linux Mint 22.3 ships apt and the user very likely already has Chrome
or Chromium, the system-Chromium .deb is both the smallest and the safest.
| Option | Artifact | Size | Chromium guaranteed | Effort | Status |
|---|---|---|---|---|---|
| PWA install | none (desktop entry) | 0 | user's browser | trivial | works today |
System-Chromium .deb |
nysiris_*.deb |
~1 MB + web/dist
|
uses system Chromium | low | implemented |
| Electron |
.deb + AppImage |
~150 MB installed | ✅ bundled | medium | scaffold provided |
| Tauri |
.deb + AppImage |
~5–15 MB | ❌ WebKitGTK; needs verification | medium | documented |
| Flatpak | .flatpak |
depends on runtime | ✅ if Electron/Chromium runtime | medium | documented |
| AppImage | single executable | depends | depends on choice | medium | documented |
Architecture:
/usr/bin/nysiris wrapper
/usr/lib/nysiris/
nysiris-launcher std-only Rust: loopback static server + browser launcher
web/ built PWA (web/dist)
/usr/share/applications/nysiris.desktop
/usr/share/icons/hicolor/scalable/apps/nysiris.svg
The launcher:
- binds 127.0.0.1 only (never
0.0.0.0), - sets
Cross-Origin-Opener-Policy: same-originandCross-Origin-Embedder-Policy: require-corpsoSharedArrayBufferis available (loopback is a secure context), -
refuses path traversal, including percent-encoded
%2e%2e, - serves an SPA fallback to
index.htmlfor extension-less routes, - opens the app in a Chromium
--appwindow (no tabs, no URL bar), falling back throughchromium → chromium-browser → google-chrome → google-chrome-stable → brave-browser → microsoft-edge → xdg-open.
./build.sh web # build web/dist (npm, network)
./build.sh desktop # -> dist/nysiris_0.1.0_amd64.deb
./build.sh desktop --app-version 1.2.3 # custom version
sudo apt install ./dist/nysiris_0.1.0_amd64.deb
nysiris # or launch from the menu
sudo apt remove nysiris # uninstallcargo run -p nysiris-launcher -- --root web/dist
cargo run -p nysiris-launcher -- --root web/dist --no-open --port 8737dpkg-deb --info dist/nysiris_0.1.0_amd64.deb
dpkg-deb --contents dist/nysiris_0.1.0_amd64.debThe launcher's parser, MIME mapping and traversal rejection are covered by unit
tests that run in ./build.sh check.
Use when you cannot assume the user has Chromium, or you want one artifact that guarantees Blink.
./build.sh desktop --electron # deb + AppImage
./build.sh desktop --electron --app-version 1.2.3or by hand:
cd desktop/electron
npm install
mkdir -p web && cp -r ../../web/dist/* web/
npm run dist # -> desktop/electron/dist/{*.deb,*.AppImage}Output: nysiris-desktop_<version>_amd64.deb (installs to
/opt/nysiris) and nysiris-<version>.AppImage (~125 MB;
self-contained, no install needed).
electron-builder 26 prints a
desktopNamewarning for window association, but its own schema rejects thedesktopNamekey. It is cosmetic (taskbar grouping) and safely ignored.
Debian metadata is mandatory. electron-builder's Debian packager refuses to
build without a maintainer, so package.json sets homepage,
author.email, linux.maintainer and an icon (build/icon.png, 512×512,
generated by scripts/gen-icons.py). Without these you get:
⨯ Please specify project homepage
Please specify author 'email' ...
It is required to set Linux .deb package maintainer.
Trade-off: ~150 MB installed (bundled Chromium) and its own update cadence.
desktop/electron/main.js starts a loopback server with the same COOP/COEP
headers and opens a hardened BrowserWindow (contextIsolation: true,
nodeIntegration: false, sandbox: true).
Tauri v2 produces tiny binaries and a .deb, but on Linux it renders with
WebKitGTK, not Blink. Before committing to it, confirm the Nym WASM client
works there:
- Serve
web/distwith the COOP/COEP headers above. - Point Tauri's window at it (or register a custom protocol that sets the headers; Tauri lets you control response headers).
- Test: WASM instantiates, the worker starts from its blob URL,
mixFetchcompletes, and messaging/SURB replies work.
If any of those fail on the target distro's WebKitGTK, use Electron or the
system-Chromium .deb instead. WebKitGTK versions differ across Mint/Ubuntu
releases, so testing on each supported release is essential.
-
Flatpak is available on Mint (
flatpakis installed). Ship the Electron build on a Chromium-based runtime, or a Tauri build on a GNOME runtime (same WebKitGTK caveat). You must publish a manifest and either host your own repo or submit to Flathub. This is the most portable "one artifact for every distro" route. -
AppImage is a single self-contained executable produced by
electron-builder(seenpm run dist) or Tauri. No root required; the userchmod +xand runs it. Good for handing someone a file; less good for managed installs.
For an internal repo, serve the .deb with a tiny Packages index:
mkdir -p repo
cp dist/nysiris_*.deb repo/
cd repo
dpkg-scanpackages . /dev/null | gzip -9 > Packages.gzThen clients add deb [trusted=yes] file:/path/repo ./ (or an HTTP URL) to
/etc/apt/sources.list.d/. For anything public, sign the repository with a GPG
key rather than using trusted=yes.
- It is not a system-wide proxy. Like the browser client, it routes only traffic
that goes through the app. For whole-device routing on Linux use
nym-socks5-client(SOCKS5 on127.0.0.1:1080) or NymVPN. - It does not reimplement mixnet crypto. The packaged app uses Nym's audited WASM client, exactly like the web build.
- A Tauri/WebKitGTK build is not validated until you run the checklist in §7.5 on each target release.
| Path | Purpose |
|---|---|
desktop/launcher/ |
std-only Rust launcher (static server + browser opener), unit-tested |
desktop/debian/ |
control, postinst, prerm, .desktop, icon, build-deb.sh
|
desktop/electron/ |
Electron alternative (package.json, main.js) |
scripts/cmd-desktop.sh |
./build.sh desktop implementation |
scripts/gen-icons.py |
regenerates web/public/icons/*.png (stdlib only) |
A blank window showing placeholder text.
The package bundled a non-production web/dist. Build the real app and rebuild:
./build.sh web
./build.sh desktop --app-version 0.1.1
sudo apt install ./dist/nysiris_0.1.1_amd64.debStuck at "bringing up mixnet tunnel" (no visible error).
Almost always a Content-Security-Policy problem: the Nym client compiles
WebAssembly, so script-src must include 'wasm-unsafe-eval'. With a bare
script-src 'self', Chrome/Firefox refuse WebAssembly.compile(), the
mix-tunnel worker throws CompileError, and setupMixTunnel never settles.
Diagnose it concretely with the bundled probe (header comment has the exact commands):
node scripts/probe-tunnel.mjs http://127.0.0.1:9222 127.0.0.1
# look for: [log.error] CompileError ... Content Security Policy
# success ends with: [smolmix] tunnel readyFix: add 'wasm-unsafe-eval' to script-src in web/index.html (and to any
server-sent CSP header). Do not use 'unsafe-eval'; WASM is the only thing
this needs to allow.
GET .../assets/index-*.js net::ERR_BLOCKED_BY_CLIENT (blank app).
A browser extension blocked the app's own JavaScript. This is the most common
desktop failure and it is silent: the page loads, the bundle does not, and the
window stays empty. The launcher prevents it by running the app in a dedicated
Chrome profile and passing --disable-extensions:
--user-data-dir=$XDG_DATA_HOME/nysiris/chrome-profile
--no-first-run --no-default-browser-check --disable-extensions
Extractors and content blockers are the usual culprits, and they also inject
window.ethereum/window.web3 into every page (the WELLDONE Wallet is not initialized / window.web3 is deprecated console spam). A dedicated profile
removes both problems. To use your own profile instead:
nysiris --profile ~/.config/google-chrome # not recommended
nysiris --allow-extensions # keep extensions in the app profileIf you launch Chrome manually for testing, do the same:
google-chrome --user-data-dir=/tmp/fly-profile --disable-extensions \
--app=http://127.0.0.1:<port>/frame-ancestors is ignored when delivered via <meta>.
Expected: that directive only works as an HTTP header. It was removed from the
meta CSP; the launcher sends X-Frame-Options: DENY instead. A web deployment
should set frame-ancestors (or X-Frame-Options) at the server.
Download error or resource isn't a valid image for a manifest icon.
The icons were missing from web/public/icons/. Generate them and rebuild:
python3 scripts/gen-icons.py
./build.sh web"Google Chrome opens" when I expected a standalone app.
By design: this package uses the system Chromium/Chrome engine in --app mode
(no tabs or URL bar) and does not bundle a browser. For a self-contained app,
use the Electron path (§7.4).
⚠️ Experimental / pre-audit. This repository is under active development and has not had an independent security audit. The Sphinx core incrates/is a reference implementation, never production crypto. Do not rely on it for high-stakes anonymity yet — see the threat model. Apache-2.0 © 2026 odelyzid (tribewarez). Report a security issue.
Nysiris docs
- Home
- 1. High-Level Architecture
- 2. Addressing & Routing Deep-Dive: how "DNS" works in Sphinx/Nym
- 3. Browser & Mobile Client (Web, Android, Desktop)
- 4. Hosting a Web Server / Service Reachable via the Nym Mixnet
- 5. Security Analysis & Recommendations
- 6. Implementation Roadmap
- 7. Desktop on Linux Mint / Debian
- 8. Hidden-Service Abstraction
- 9. nysiris-social: Metadata-Minimal Microblog + Encrypted DMs
- 10. Portal Layers: Data, Replication, Discovery, Reputation
- 11. UX Redesign — Calm, Private-by-Default Client
- 12. Windows build (MSYS2 / MSVC)
- 13. Hosting SDK &
nysirisCLI