diff --git a/nix/modules/hive-c0re.nix b/nix/modules/hive-c0re.nix index 25c0a7d7..5d8fe6bc 100644 --- a/nix/modules/hive-c0re.nix +++ b/nix/modules/hive-c0re.nix @@ -425,10 +425,13 @@ in ExecStart = "${cfg.package}/bin/hive-c0re --socket /run/hyperhive/host.sock serve --hyperhive-flake ${cfg.hyperhiveFlake} --nixpkgs-flake ${cfg.nixpkgsFlake} --nixpkgs-unstable-flake ${cfg.nixpkgsUnstableFlake} --dashboard-port ${toString cfg.dashboardPort} --operator-pronouns ${lib.escapeShellArg cfg.operatorPronouns} --context-window-tokens ${lib.escapeShellArg (builtins.toJSON cfg.contextWindowTokens)}"; # One-time migration: chown existing state tree to the service # user after upgrading from a root-run install. The `+` prefix - # runs this step as root even though User = hive-core. systemd's - # StateDirectory chowns the top-level dir at every start, but - # pre-existing files inside may still be root-owned. - ExecStartPre = "+${pkgs.coreutils}/bin/sh -c 'chown -R hive-core:hive-core /var/lib/hyperhive || true'"; + # runs this step as root even though User = hive-core; the `-` + # prefix tolerates failure (e.g. an empty tree) without blocking + # startup. coreutils ships `chown` but no `sh`, so invoke chown + # directly rather than through a shell. systemd's StateDirectory + # chowns the top-level dir at every start, but pre-existing files + # inside may still be root-owned. + ExecStartPre = "+-${pkgs.coreutils}/bin/chown -R hive-core:hive-core /var/lib/hyperhive"; Restart = "on-failure"; RestartSec = 2; User = "hive-core";