The /api/v1/admin endpoint only returns the /64 subnet. Users were
copy-pasting the subnet straight into Compose Message and getting
HTTP 422 from the daemon (\"invalid IP address syntax\"). The full
host part (lower 64 bits) is logged once at boot:
INFO mycelium: Node overlay IP: 43d:956e:7877:d933:eecc:b305:21ff:77f9
Capture it from stdout, surface as a new daemonStatus.overlayIp
field, and render it on Status above the subnet card with the hint
\"use this when sending messages\".
The line carries ANSI colour escapes from tracing's compact format,
so push_log strips SGR sequences before scanning. Hand-rolled to
avoid pulling a regex crate.
Also rebuilds the .deb release artifact.
mycellium-ui
Cross-platform desktop GUI for Mycelium — Threefold's end-to-end encrypted IPv6 overlay network.
The app embeds the official mycelium binary as a Tauri sidecar and pilots it through its HTTP API on a loopback ephemeral port. Root privileges (required to create the TUN interface) are obtained via pkexec.
Status
v1, Linux-only. Implements the full docs/api.yaml surface of mycelium v0.6.1: admin, peers (CRUD), routes (selected/fallback/queried), messages (send/receive/reply/status), topics (default + whitelist + sources + forward), pubkey lookup.
Architecture
┌──────────────────────────────────────────────────────────────┐
│ WebView (Vue 3 + TS + Tailwind + radix-vue + Pinia) │
│ Status / Peers / Routes / Messages / Topics / Settings │
└────────────────┬─────────────────────────────────────────────┘
│ invoke() / Tauri events
┌────────────────┴─────────────────────────────────────────────┐
│ Tauri core (Rust, tokio + reqwest) │
│ • sidecar.rs — supervises mycelium via pkexec │
│ • api/* — typed REST client │
│ • poller.rs — emits peers://, stats://, routes://, messages://incoming │
└────────────────┬─────────────────────────────────────────────┘
│ HTTP loopback :ephemeral
┌────────────────┴─────────────────────────────────────────────┐
│ mycelium daemon (sidecar binary, runs as root via pkexec) │
│ TUN0 ◄─► overlay network │
└──────────────────────────────────────────────────────────────┘
There is no Unix socket / named pipe IPC — the daemon's own HTTP API is the integration point.
Prerequisites (Debian / Ubuntu)
sudo apt install -y \
libwebkit2gtk-4.1-dev libjavascriptcoregtk-4.1-dev \
libsoup-3.0-dev libayatana-appindicator3-dev librsvg2-dev \
build-essential curl wget file libssl-dev libgtk-3-dev libxdo-dev \
pkg-config policykit-1
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
Then Node 20+ and pnpm 10+.
Setup
# 1. Install JS deps
pnpm install
# 2. Fetch the mycelium sidecar binary for your target triple
bash scripts/fetch-mycelium.sh # uses MYCELIUM_VERSION (default v0.6.1)
# or: MYCELIUM_VERSION=v0.6.1 bash scripts/fetch-mycelium.sh
# 3. Run in dev
pnpm tauri dev
The first start triggers a pkexec dialog asking you to authenticate; the polkit policy installed by the .deb caches the auth for the user session.
Build
pnpm tauri build # → src-tauri/target/release/bundle/{deb,appimage}/
The .deb declares Depends: policykit-1 and ships the polkit policy under /usr/share/polkit-1/actions/tech.threefold.mycellium-ui.policy. The AppImage relies on pkexec being present on the host — on systems without polkit, fall back to running with sudo after disabling the sidecar's pkexec wrapper.
Layout
src/ # Vue 3 frontend
views/ # one file per nav item
components/ # shadcn-style UI primitives + dialogs
stores/ # Pinia: node, peers, routes, messages, topics, config
lib/ # api wrapper, events, base64 + format helpers
src-tauri/
src/
sidecar.rs # spawn + supervise mycelium
elevation.rs # pkexec command builder
poller.rs # 3 background loops (peers, routes, inbox long-poll)
api/ # REST client modules (admin, peers, routes,
# messages, topics, pubkey)
commands.rs # #[tauri::command] handlers, 1:1 with REST
error.rs # AppError + Serialize-as-string for invoke()
binaries/ # gitignored; populated by scripts/fetch-mycelium.sh
packaging/polkit/ # XML policy bundled into the .deb
scripts/fetch-mycelium.sh
.github/workflows/ci.yml # pnpm typecheck + cargo fmt/clippy/test
Verification matrix
| Test | How |
|---|---|
| Sidecar starts under pkexec | pnpm tauri dev, daemon visible in ps, splash disappears in <10 s |
| Peers connect | Add tcp://188.40.132.242:9651 from the Peers page; state turns to alive within ~10 s |
| Routes propagate | Routes/Selected becomes non-empty after ~30 s |
| Live event stream | Sidebar status dot tracks ready/idle, peers table updates without manual refresh |
| Bidirectional messages | Two instances on different VMs, exchange via Compose → Inbox |
| Identity regen | Settings → Regenerate; restart daemon; new IP appears on Status |
.deb install |
Fresh Ubuntu LTS / Debian 12; daemon spawns under polkit on first start |
Known limitations (v1)
- Linux only. Windows is reachable (sidecar via
runas/ Wintun driver) but not implemented. - Auto-start at login isn't wired — the desktop entry installed by the
.debis the manual launcher. - The TOML config editor in Settings only exposes
peers,tunName,noTun. Other keys (metricsApiAddress, etc.) are passed-through if you edit the file directly at~/.local/share/tech.threefold.mycellium-ui/mycelium.tomland restart the daemon. message_statusis forwarded as opaque JSON; the upstream schema isn't pinned in the spec, so we don't strongly type it.