Symptom: each app restart that didn't go through Stop daemon left
an orphan mycelium running as root, claiming the TUN \"mycelium\",
UDP/9650 (multicast discovery) and TCP/8990 (JSON-RPC, hardcoded
in 0.6.1 — no flag). Subsequent starts panicked with EBUSY or
\"Address in use\" on whichever port the orphan held.
We can't SIGKILL the orphan from user-space (root process). Move
the cleanup into an elevated context that runs in the same pkexec
authentication as the daemon spawn:
/usr/bin/mycellium-bootstrap (new shell script in the .deb)
pkill -9 -x mycelium
ip link del mycelium / mycel0
exec /usr/bin/mycelium \"\$@\"
The polkit policy now annotates this exact path with
auth_admin_keep so a single password prompt covers every
subsequent restart in the user's session.
Sidecar: when /usr/bin/mycellium-bootstrap exists (production
install) we hand pkexec that path instead of the bare daemon.
\`pnpm tauri dev\` falls back to the unwrapped binary path.
Backend
- regenerate_identity command stops the daemon, deletes
priv_key.bin, leaves the user to restart for a fresh identity;
falls back to the canonical XDG path when sidecar.key_path()
isn't populated yet
- tauri.conf.json ships the polkit policy via deb.files mapping;
src-tauri/packaging/polkit/tech.threefold.mycellium-ui.policy
declares the spawn action with auth_admin_keep so the dialog
appears once per session
Frontend
- config store persists SidecarConfig (peers, tunName, noTun)
through tauri-plugin-store; App.vue reads it and forwards to
start_daemon, replacing the hard-coded defaults
- Settings view: daemon-config form, identity panel with the
destructive regenerate button, sidecar log viewer, About
- README rewritten end-to-end: HTTP-loopback architecture, polkit
install path, build commands, verification matrix, and a
honest "known limitations" section