syoul 9fe24c72cb fix(ui): only show overlay when starting, not on error
The overlay covered the whole window in error phase too, blocking
access to the sidebar and Settings page where the user needs to
read the sidecar logs to diagnose the failure.

Now in error phase the sidebar status dot turns red, the start
button is back in the sidebar, and the Settings page is reachable
to inspect the in-app log buffer.
2026-04-26 00:13:47 +02:00

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 .deb is 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.toml and restart the daemon.
  • message_status is forwarded as opaque JSON; the upstream schema isn't pinned in the spec, so we don't strongly type it.
Description
No description provided
Readme 53 MiB
Languages
Rust 39.8%
Vue 39.3%
TypeScript 17.3%
Shell 2.2%
CSS 1.1%
Other 0.2%