Commit 7fc5c1624dec

Vincent Demeester <vincent@sbr.pm>
2026-01-08 11:49:14
feat(nixpkgs): Add NixOS module and package for consolidation tool
- Package script as Nix derivation for easy installation - Provide systemd service/timer for automated consolidation - Integrate with job-notify for failure alerts - Include security hardening in systemd service Signed-off-by: Vincent Demeester <vincent@sbr.pm>
1 parent baf0194
Changed files (4)
modules
nixpkgs-consolidate
pkgs
tools
nixpkgs-consolidate
modules/nixpkgs-consolidate/default.nix
@@ -0,0 +1,131 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+
+with lib;
+
+let
+  cfg = config.services.nixpkgs-consolidate;
+
+  consolidateScript = pkgs.writeShellScript "nixpkgs-consolidate-wrapper" ''
+    set -euo pipefail
+
+    export NIXPKGS_REPO_PATH="${cfg.repoPath}"
+    export NIXPKGS_WORKTREE_PATH="${cfg.worktreePath}"
+    export NIXPKGS_CONFIG_FILE="${cfg.configFile}"
+    export NTFY_TOKEN_FILE="${cfg.ntfyTokenFile}"
+    export LOG_DIR="${cfg.logDir}"
+
+    exec ${pkgs.nixpkgs-consolidate}/bin/nixpkgs-consolidate
+  '';
+in
+{
+  options.services.nixpkgs-consolidate = {
+    enable = mkEnableOption "automated nixpkgs branch consolidation";
+
+    repoPath = mkOption {
+      type = types.str;
+      default = "/home/vincent/src/nixpkgs";
+      description = "Path to nixpkgs repository";
+    };
+
+    worktreePath = mkOption {
+      type = types.str;
+      default = "/home/vincent/src/nixpkgs-consolidate-work";
+      description = "Path to worktree for consolidation work";
+    };
+
+    configFile = mkOption {
+      type = types.str;
+      default = "/home/vincent/.config/nixpkgs-automation/branches.conf";
+      description = "Path to branches configuration file";
+    };
+
+    schedule = mkOption {
+      type = types.str;
+      default = "daily";
+      example = "Mon,Thu *-*-* 02:00:00";
+      description = ''
+        Systemd timer schedule (OnCalendar format).
+        Use "daily", "weekly", or systemd calendar syntax.
+      '';
+    };
+
+    user = mkOption {
+      type = types.str;
+      default = "vincent";
+      description = "User to run consolidation as (needs git access)";
+    };
+
+    ntfyTokenFile = mkOption {
+      type = types.str;
+      default = "/run/agenix/ntfy-token";
+      description = "Path to ntfy authentication token";
+    };
+
+    logDir = mkOption {
+      type = types.str;
+      default = "/var/log/nixpkgs-consolidate";
+      description = "Directory for log files";
+    };
+
+    randomizedDelaySec = mkOption {
+      type = types.int;
+      default = 1800; # 30 minutes
+      description = "Random delay in seconds before starting";
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.services.nixpkgs-consolidate = {
+      description = "Nixpkgs branch consolidation automation";
+
+      serviceConfig = {
+        Type = "oneshot";
+        User = cfg.user;
+        ExecStart = "${consolidateScript}";
+
+        # Security hardening
+        PrivateTmp = true;
+        ProtectSystem = "strict";
+        ProtectHome = "read-only";
+        ReadWritePaths = [
+          cfg.repoPath
+          cfg.worktreePath
+          cfg.logDir
+          "%h/.config/nixpkgs-automation"
+        ];
+        NoNewPrivileges = true;
+
+        # Logging
+        StandardOutput = "journal";
+        StandardError = "journal";
+        SyslogIdentifier = "nixpkgs-consolidate";
+      };
+
+      # Trigger notification on failure
+      unitConfig.OnFailure = [ "job-notify@%n.service" ];
+    };
+
+    systemd.timers.nixpkgs-consolidate = {
+      description = "Timer for nixpkgs branch consolidation";
+      wantedBy = [ "timers.target" ];
+
+      timerConfig = {
+        OnCalendar = cfg.schedule;
+        RandomizedDelaySec = cfg.randomizedDelaySec;
+        Persistent = true;
+      };
+    };
+
+    # Ensure directories exist
+    systemd.tmpfiles.rules = [
+      "d ${cfg.logDir} 0750 ${cfg.user} users -"
+      "d ${cfg.repoPath} 0750 ${cfg.user} users -"
+      "d ${cfg.worktreePath} 0750 ${cfg.user} users -"
+    ];
+  };
+}
pkgs/default.nix
@@ -33,6 +33,7 @@ in
   jellyfin-manage-playlist = pkgs.callPackage ../tools/jellyfin-manage-playlist { };
   music-playlist-dl = pkgs.callPackage ../tools/music-playlist-dl { };
   nix-flake-update = pkgs.callPackage ../tools/nix-flake-update { };
+  nixpkgs-consolidate = pkgs.callPackage ../tools/nixpkgs-consolidate { };
   beets-lidarr-fields = pkgs.python3Packages.callPackage ./beets-lidarr-fields { };
   beets-filetote = pkgs.python3Packages.callPackage ./beets-filetote { };
 
tools/nixpkgs-consolidate/default.nix
@@ -0,0 +1,39 @@
+{
+  lib,
+  stdenv,
+  bash,
+  git,
+  curl,
+  coreutils,
+}:
+
+stdenv.mkDerivation {
+  pname = "nixpkgs-consolidate";
+  version = "1.0.0";
+
+  src = ./.;
+
+  dontUnpack = true;
+  dontBuild = true;
+
+  installPhase = ''
+    runHook preInstall
+
+    mkdir -p $out/bin
+    cp ${./nixpkgs-consolidate.sh} $out/bin/nixpkgs-consolidate
+    chmod +x $out/bin/nixpkgs-consolidate
+
+    # Patch shebang
+    patchShebangs $out/bin/nixpkgs-consolidate
+
+    runHook postInstall
+  '';
+
+  meta = with lib; {
+    description = "Consolidate multiple nixpkgs WIP branches into a single branch";
+    homepage = "https://github.com/vdemeester/home";
+    license = licenses.mit;
+    platforms = platforms.unix;
+    mainProgram = "nixpkgs-consolidate";
+  };
+}
flake.nix
@@ -139,6 +139,7 @@
         govanityurl = ./modules/govanityurl;
         gosmee = ./modules/gosmee;
         rsync-replica = ./modules/rsync-replica;
+        nixpkgs-consolidate = ./modules/nixpkgs-consolidate;
       };
 
       # system-manager configurations