From abb1476fc84d956747bcfa90e5aa38def51ccf23 Mon Sep 17 00:00:00 2001 From: dtoro Date: Wed, 1 Jul 2026 14:02:07 +0200 Subject: [PATCH] fix(homelab): cmd_sync missing the geteuid guard every other command has MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every other mutating subcommand (secret, refresh-creds, client add/remove) already re-execs via sudo only when os.geteuid() != 0. cmd_sync was the one exception, calling sudo unconditionally — fails with "No such file or directory: 'sudo'" on minimal root-only images (no sudo binary at all), hit live running `homelab sync` on strong over root SSH. Co-Authored-By: Claude Sonnet 5 --- bin/homelab | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/bin/homelab b/bin/homelab index d1c3a94..e2a05bc 100755 --- a/bin/homelab +++ b/bin/homelab @@ -1031,14 +1031,19 @@ def cmd_refresh_creds(args: argparse.Namespace) -> int: def cmd_sync(args: argparse.Namespace) -> int: + # Unlike every other mutating command here, this one had no os.geteuid() + # guard — always shelled out to sudo. Fails outright with "No such file + # or directory: 'sudo'" on minimal root-only Linux images (no sudo + # binary installed at all) reached via `ssh root@host`, e.g. strong. + needs_sudo = os.geteuid() != 0 if sys.platform == "darwin": - return subprocess.call( - ["sudo", "launchctl", "kickstart", "-k", - "system/network.hubris.homelab-context-sync"] - ) - return subprocess.call( - ["sudo", "systemctl", "start", "homelab-context-sync.service"] - ) + cmd = ["launchctl", "kickstart", "-k", + "system/network.hubris.homelab-context-sync"] + else: + cmd = ["systemctl", "start", "homelab-context-sync.service"] + if needs_sudo: + cmd = ["sudo"] + cmd + return subprocess.call(cmd) def cmd_mcp(args: argparse.Namespace) -> int: