From 3c4f4860f47eff6cedeea095cf89236e14b8a7be Mon Sep 17 00:00:00 2001 From: Miroslav Vadkerti Date: Thu, 2 Apr 2026 10:25:27 +0200 Subject: [PATCH] Add `dnf` Home Manager module for toolbox package management MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a reusable Home Manager module that declaratively manages DNF packages inside Fedora toolbox containers. The module provides: - `dnf.install` — items to install via `dnf install` (packages, groups, paths, URLs, provides) - `dnf.releaseInstall` — per-Fedora-release items keyed by `VERSION_ID` - `dnf.upgradeAll` — optional full `dnf -y upgrade` on every activation The activation script uses `gum spin` for spinner output when available, falling back to plain echo. DNF's built-in idempotency handles already-installed items gracefully. Assisted-by: Claude Code Signed-off-by: Miroslav Vadkerti --- flake.nix | 3 ++ home.nix | 10 ++++++ modules/dnf.nix | 84 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 modules/dnf.nix diff --git a/flake.nix b/flake.nix index 20470ca..7347e1f 100644 --- a/flake.nix +++ b/flake.nix @@ -42,6 +42,7 @@ formatter.x86_64-linux = nixpkgs.legacyPackages.x86_64-linux.alejandra; homeManagerModules = { + dnf = import ./modules/dnf.nix; hostConfig = import ./modules/host-config.nix; }; @@ -50,6 +51,7 @@ modules = [ nixvim.homeModules.nixvim + ./modules/dnf.nix ./modules/host-config.nix ./home.nix ]; @@ -65,6 +67,7 @@ modules = [ nixvim.homeModules.nixvim + ./modules/dnf.nix ./modules/host-config.nix ./home.nix ]; diff --git a/home.nix b/home.nix index e6cbe94..a6bbab6 100644 --- a/home.nix +++ b/home.nix @@ -112,6 +112,16 @@ in { TESTING_FARM_PUBLIC_IP_RESOLVE_TRIES = 10; }; + dnf = { + enable = true; + install = [ + ]; + # releaseInstall = { + # "41" = ["some-f41-item"]; + # }; + # upgradeAll = false; + }; + hostConfig = { enable = true; xdgDesktopEntries = true; diff --git a/modules/dnf.nix b/modules/dnf.nix new file mode 100644 index 0000000..ef4ad6e --- /dev/null +++ b/modules/dnf.nix @@ -0,0 +1,84 @@ +{ + config, + lib, + ... +}: let + cfg = config.dnf; + + installScript = '' + test -f /run/.toolboxenv || exit + + FEDORA_RELEASE=$(. /etc/os-release && echo "$VERSION_ID") + + INSTALL="${lib.concatStringsSep " " cfg.install}" + + ${lib.concatStrings (lib.mapAttrsToList (release: items: '' + if [ "$FEDORA_RELEASE" = "${release}" ]; then + INSTALL="$INSTALL ${lib.concatStringsSep " " items}" + fi + '') + cfg.releaseInstall)} + + # Helper: run command with gum spinner if available, fallback to echo + _dnf_run() { + local title="$1"; shift + if command -v gum &>/dev/null; then + gum spin --spinner dot --title "$title" -- "$@" + else + echo -e "\e[32m$title\e[0m" + "$@" + fi + } + + # Install items (dnf handles already-installed items gracefully) + if [ -n "$INSTALL" ]; then + _dnf_run "DNF: installing $INSTALL" /usr/bin/sudo dnf -y install $INSTALL + fi + + # Upgrade all packages + ${lib.optionalString cfg.upgradeAll '' + _dnf_run "DNF: upgrading all packages" /usr/bin/sudo dnf -y upgrade + ''} + ''; +in { + options.dnf = { + enable = lib.mkEnableOption "DNF package management in toolbox containers"; + + install = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = []; + example = ["krb5-workstation" "@development-tools" "/path/to/local.rpm"]; + description = '' + Items to install via `dnf install`. Accepts anything dnf supports: + package names, group names (@group), paths, URLs, provides, etc. + Installed regardless of Fedora release version. + ''; + }; + + releaseInstall = lib.mkOption { + type = lib.types.attrsOf (lib.types.listOf lib.types.str); + default = {}; + example = { + "41" = ["some-f41-pkg"]; + "42" = ["some-f42-pkg"]; + }; + description = '' + Per-Fedora-release items to install. Keys are VERSION_ID strings + (e.g. "41", "42"). Items are only installed when that release is + detected via /etc/os-release. + ''; + }; + + upgradeAll = lib.mkOption { + type = lib.types.bool; + default = false; + description = "When true, run `dnf -y upgrade` (all packages) on every activation."; + }; + }; + + config = lib.mkIf cfg.enable { + home.activation = { + dnfInstall = lib.hm.dag.entryAfter ["reloadSystemd"] installScript; + }; + }; +}