diff --git a/sw/default.nix b/sw/default.nix index 6826768..caf5bb2 100644 --- a/sw/default.nix +++ b/sw/default.nix @@ -22,6 +22,7 @@ in imports = [ ./python.nix ./ghostty.nix + ./shared-services.nix ]; options.modules.sw = { @@ -74,22 +75,6 @@ in oh-my-posh inputs.lazyvim-nixvim.packages.${stdenv.hostPlatform.system}.nvim inputs.agenix.packages.${stdenv.hostPlatform.system}.default - # Custom update script - (writeShellScriptBin "update-system" '' - HOSTNAME=$(hostname) - FLAKE_URI="github:UGA-Innovation-Factory/nixos-systems" - - # Pass arguments like --impure to nixos-rebuild - EXTRA_ARGS="$@" - - if [[ "$HOSTNAME" == nix-surface* ]]; then - echo "Detected Surface tablet. Using remote build host." - sudo nixos-rebuild switch --flake "$FLAKE_URI" --build-host engr-ugaif@192.168.11.133 --refresh $EXTRA_ARGS - else - echo "Updating local system..." - sudo nixos-rebuild switch --flake "$FLAKE_URI" --refresh $EXTRA_ARGS - fi - '') ]; } # Import Desktop or Kiosk modules based on type diff --git a/sw/shared-services.nix b/sw/shared-services.nix new file mode 100644 index 0000000..46616c2 --- /dev/null +++ b/sw/shared-services.nix @@ -0,0 +1,98 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +{ + options.modules.sw.remoteBuild = lib.mkOption { + type = types.submodule { + options = { + hosts = mkOption { + type = types.listOf types.str; + default = [ "engr-ugaif@192.168.11.133 x86_64-linux" ]; + description = "List of remote build hosts for system rebuilding."; + }; + + enable = mkOption { + type = types.bool; + default = false; + description = "Whether to enable remote build for 'update-system' command."; + }; + }; + }; + default = { }; + description = "Remote build configuration"; + }; + + config = { + modules.sw.remoteBuild.enable = lib.mkDefault (config.modules.sw.type == "tablet-kiosk"); + + environment.systemPackages = [ + (pkgs.writeShellScriptBin "update-system" '' + set -euo pipefail + + UNIT="update-system.service" + + # Start following logs in the background + journalctl -fu "$UNIT" -n 0 --output=cat & + JPID=$! + + # Start the service and wait for it to finish + if systemctl start --wait --no-ask-password "$UNIT"; then + STATUS=$? + else + STATUS=$? + fi + + sleep 2 + + # Kill the log follower + kill "$JPID" 2>/dev/null || true + + exit "$STATUS" + '') + ]; + + systemd.services.update-system = { + enable = true; + description = "System daemon to one-shot run the Nix updater from fleet flake as root"; + serviceConfig = { + Type = "oneshot"; + ExecStart = + let + hosts = config.modules.sw.remoteBuild.hosts; + builders = lib.strings.concatMapStringsSep ";" (x: x) hosts; + rebuildCmd = "${pkgs.nixos-rebuild}/bin/nixos-rebuild switch --refresh"; + source = "--flake github:UGA-Innovation-Factory/nixos-systems"; + remoteBuildFlags = if config.modules.sw.remoteBuild.enable + then + ''--builders "${builders}"'' + else ""; + in + "${rebuildCmd} ${remoteBuildFlags} --print-build-logs ${source}#${config.networking.hostName}"; + User = "root"; + Group = "root"; + TimeoutStartSec = "0"; + }; + }; + + security.polkit = { + debug = true; + enable = true; + extraConfig = '' + polkit.addRule(function(action, subject) { + if (action.id == "org.freedesktop.systemd1.manage-units" && + action.lookup("unit") == "update-system.service" && + action.lookup("verb") == "start" && + subject.isInGroup("users")) { + return polkit.Result.YES; + } + }); + ''; + }; + }; +}