diff --git a/release/SHA256SUMS b/release/SHA256SUMS
index 3f5a623..d1400f6 100644
--- a/release/SHA256SUMS
+++ b/release/SHA256SUMS
@@ -1 +1 @@
-acab8758c4ba7f3894e5e9bce28cbd759b8ec7e08a1ee00f54f6fdcac75a4221 release/mycellium-ui_0.1.0_amd64.deb
+38e0a3d03797490e1d6caa2681f9d5580493908834736b0db6a7d99558bb8823 release/mycellium-ui_0.1.0_amd64.deb
diff --git a/release/mycellium-ui_0.1.0_amd64.deb b/release/mycellium-ui_0.1.0_amd64.deb
index 3750483..2506c93 100644
Binary files a/release/mycellium-ui_0.1.0_amd64.deb and b/release/mycellium-ui_0.1.0_amd64.deb differ
diff --git a/src-tauri/packaging/mycellium-bootstrap b/src-tauri/packaging/mycellium-bootstrap
new file mode 100755
index 0000000..2618eaf
--- /dev/null
+++ b/src-tauri/packaging/mycellium-bootstrap
@@ -0,0 +1,27 @@
+#!/bin/sh
+# /usr/bin/mycellium-bootstrap — installed by mycellium-ui.deb
+#
+# Wrapper around the mycelium daemon that guarantees a clean start
+# every time. Without this, an orphan mycelium left over from a
+# previous run (which the user-space launcher cannot SIGKILL because
+# the daemon runs as root via pkexec) would block the next start
+# with one of:
+#
+# * EBUSY on TUN device "mycelium" creation
+# * "Address in use" on the JSON-RPC port (hardcoded 8990 in 0.6.1)
+# * "Failed to bind multicast discovery socket" on UDP 9650
+#
+# This script runs under the same elevated context as the mycelium
+# daemon itself (single pkexec call), so polkit's auth_admin_keep
+# caching only fires one prompt per session.
+
+set -e
+
+# Best-effort cleanup. Errors ignored so the exec at the end always
+# runs even on a clean machine.
+pkill -9 -x mycelium 2>/dev/null || true
+sleep 0.3
+ip link del mycelium 2>/dev/null || true
+ip link del mycel0 2>/dev/null || true
+
+exec /usr/bin/mycelium "$@"
diff --git a/src-tauri/packaging/polkit/tech.threefold.mycellium-ui.policy b/src-tauri/packaging/polkit/tech.threefold.mycellium-ui.policy
index 944ad64..28c84a0 100644
--- a/src-tauri/packaging/polkit/tech.threefold.mycellium-ui.policy
+++ b/src-tauri/packaging/polkit/tech.threefold.mycellium-ui.policy
@@ -6,7 +6,14 @@
Threefold
https://threefold.io
-
+
+
Run the Mycelium overlay daemon
Lancer le démon de l'overlay Mycelium
Authentication is required to start the Mycelium overlay daemon.
@@ -14,11 +21,8 @@
auth_admin
auth_admin
-
auth_admin_keep
+ /usr/bin/mycellium-bootstrap
diff --git a/src-tauri/src/sidecar.rs b/src-tauri/src/sidecar.rs
index a1d0258..f54aee8 100644
--- a/src-tauri/src/sidecar.rs
+++ b/src-tauri/src/sidecar.rs
@@ -121,6 +121,17 @@ impl SidecarHandle {
}
let bin = locate_sidecar(app)?;
+ // In a `.deb` install, our pre-install script ships
+ // /usr/bin/mycellium-bootstrap that pkill+ip-link-del cleans
+ // any orphan state before exec-ing the real binary. Polkit
+ // is configured to auth_admin_keep that exact path, so
+ // subsequent starts are silent.
+ // Falls back to the bare binary in `tauri dev` where the
+ // bootstrap script isn't installed system-wide.
+ let elevation_target = match bootstrap_path() {
+ Some(p) => p,
+ None => bin.clone(),
+ };
// Three ports: HTTP API (loopback), TCP listen, QUIC (UDP) listen.
// mycelium defaults to 9651 for both peer-listen ports, which
// collides if another instance (or a leftover from a previous test)
@@ -176,11 +187,12 @@ impl SidecarHandle {
info!(
?bin,
+ elevation_target = %elevation_target.display(),
api_port, tcp_port, quic_port, metrics_port,
"spawning mycelium sidecar via pkexec"
);
- let mut cmd = elevation::elevated(&bin, &args);
+ let mut cmd = elevation::elevated(&elevation_target, &args);
cmd.stdout(Stdio::piped())
.stderr(Stdio::piped())
.kill_on_drop(true);
@@ -299,6 +311,15 @@ impl SidecarHandle {
}
}
+/// Path of the privileged wrapper script shipped in our `.deb`. When
+/// present, we invoke it instead of the mycelium binary directly so
+/// the elevated context can clean up any orphan TUN / processes from
+/// a previous crash before `exec /usr/bin/mycelium`.
+fn bootstrap_path() -> Option {
+ let p = PathBuf::from("/usr/bin/mycellium-bootstrap");
+ p.exists().then_some(p)
+}
+
/// Mycelium logs the assigned overlay IPv6 once at startup like:
/// `INFO mycelium: Node overlay IP: 43d:956e:7877:d933:eecc:b305:21ff:77f9`
/// We don't pull a regex crate just for this — a hand-rolled parser is
diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json
index f19ab50..40f7819 100644
--- a/src-tauri/tauri.conf.json
+++ b/src-tauri/tauri.conf.json
@@ -42,7 +42,8 @@
"deb": {
"depends": ["pkexec | policykit-1"],
"files": {
- "/usr/share/polkit-1/actions/tech.threefold.mycellium-ui.policy": "packaging/polkit/tech.threefold.mycellium-ui.policy"
+ "/usr/share/polkit-1/actions/tech.threefold.mycellium-ui.policy": "packaging/polkit/tech.threefold.mycellium-ui.policy",
+ "/usr/bin/mycellium-bootstrap": "packaging/mycellium-bootstrap"
}
}
}