From 5eae0c65d8384f4b5ecdf213c1cc526bf554fe1e Mon Sep 17 00:00:00 2001 From: Michael Hoang Date: Sat, 12 Apr 2025 20:19:59 +0200 Subject: [PATCH] cli: support updating `nix-darwin` machines --- pkgs/clan-cli/clan_cli/machines/machines.py | 24 +++++++++++++- pkgs/clan-cli/clan_cli/machines/update.py | 35 ++++++++++++--------- 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/pkgs/clan-cli/clan_cli/machines/machines.py b/pkgs/clan-cli/clan_cli/machines/machines.py index d8bb280f3..5a6e31d67 100644 --- a/pkgs/clan-cli/clan_cli/machines/machines.py +++ b/pkgs/clan-cli/clan_cli/machines/machines.py @@ -7,11 +7,12 @@ from functools import cached_property from pathlib import Path from typing import TYPE_CHECKING, Any, Literal +from clan_cli.cmd import Log, RunOpts, run_no_stdout from clan_cli.errors import ClanCmdError, ClanError from clan_cli.facts import public_modules as facts_public_modules from clan_cli.facts import secret_modules as facts_secret_modules from clan_cli.flake import Flake -from clan_cli.nix import nix_config, nix_test_store +from clan_cli.nix import nix_config, nix_eval, nix_test_store from clan_cli.ssh.host import Host from clan_cli.ssh.host_key import HostKeyCheck from clan_cli.ssh.parse import parse_deployment_address @@ -196,6 +197,27 @@ class Machine: meta={"machine": self, "target_host": self.target_host}, ) + @cached_property + def deploy_as_root(self) -> bool: + if self._class_ == "nixos": + return True + + # Currently nix-darwin HEAD requires you to deploy as a non-root user + # however there is a soon to be merged PR that requires deployment + # as root to match NixOS: https://github.com/nix-darwin/nix-darwin/pull/1341 + return json.loads( + run_no_stdout( + nix_eval( + [ + f"{self.flake}#darwinConfigurations.{self.name}.options.system", + "--apply", + "system: system ? primaryUser", + ] + ), + RunOpts(log=Log.NONE), + ).stdout.strip() + ) + def nix( self, attr: str, diff --git a/pkgs/clan-cli/clan_cli/machines/update.py b/pkgs/clan-cli/clan_cli/machines/update.py index 910f83c24..c8d7a763c 100644 --- a/pkgs/clan-cli/clan_cli/machines/update.py +++ b/pkgs/clan-cli/clan_cli/machines/update.py @@ -138,7 +138,6 @@ def deploy_machines(machines: list[Machine]) -> None: nix_options = [ "--show-trace", - "--fast", "--option", "keep-going", "true", @@ -146,27 +145,30 @@ def deploy_machines(machines: list[Machine]) -> None: "accept-flake-config", "true", "-L", - "--build-host", - "", *machine.nix_options, "--flake", f"{path}#{machine.name}", ] - switch_cmd = ["nixos-rebuild", "switch", *nix_options] - test_cmd = ["nixos-rebuild", "test", *nix_options] + become_root = machine.deploy_as_root - become_root = True + if machine._class_ == "nixos": + nix_options += [ + "--fast", + "--build-host", + "", + ] - target_host: Host | None = host.meta.get("target_host") - if target_host: - become_root = False - switch_cmd.extend(["--target-host", target_host.target]) - test_cmd.extend(["--target-host", target_host.target]) + target_host: Host | None = host.meta.get("target_host") + if target_host: + become_root = False + nix_options += ["--target-host", target_host.target] - if target_host.user != "root": - switch_cmd.extend(["--use-remote-sudo"]) - test_cmd.extend(["--use-remote-sudo"]) + if target_host.user != "root": + nix_options += ["--use-remote-sudo"] + + switch_cmd = [f"{machine._class_}-rebuild", "switch", *nix_options] + test_cmd = [f"{machine._class_}-rebuild", "test", *nix_options] env = host.nix_ssh_env(None) ret = host.run( @@ -201,6 +203,11 @@ def deploy_machines(machines: list[Machine]) -> None: with AsyncRuntime() as runtime: for machine in machines: + if machine._class_ == "darwin": + if not machine.deploy_as_root and machine.target_host.user == "root": + msg = f"'TargetHost' should be set to a non-root user for deploying to nix-darwin on machine '{machine.name}'" + raise ClanError(msg) + machine.info(f"Updating {machine.name}") runtime.async_run( AsyncOpts(