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" } } }