Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

Expand All @@ -50,6 +51,7 @@

modules = [
nixvim.homeModules.nixvim
./modules/dnf.nix
./modules/host-config.nix
./home.nix
];
Expand All @@ -65,6 +67,7 @@

modules = [
nixvim.homeModules.nixvim
./modules/dnf.nix
./modules/host-config.nix
./home.nix
];
Expand Down
10 changes: 10 additions & 0 deletions home.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
84 changes: 84 additions & 0 deletions modules/dnf.nix
Original file line number Diff line number Diff line change
@@ -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
''}
Comment on lines +33 to +41
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Hardcoding /usr/bin/sudo may break on images without sudo or with it in a different path.

In minimal or toolbox containers sudo may be missing or not at /usr/bin/sudo, causing _dnf_run to fail even though dnf is present. Consider either detecting sudo and falling back to direct dnf when absent, or just calling sudo dnf ... and relying on $PATH instead of a hardcoded path.

Suggested change
# 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
''}
# Install items (dnf handles already-installed items gracefully)
if [ -n "$INSTALL" ]; then
if command -v sudo &>/dev/null; then
_dnf_run "DNF: installing $INSTALL" sudo dnf -y install $INSTALL
else
_dnf_run "DNF: installing $INSTALL" dnf -y install $INSTALL
fi
fi
# Upgrade all packages
${lib.optionalString cfg.upgradeAll ''
if command -v sudo &>/dev/null; then
_dnf_run "DNF: upgrading all packages" sudo dnf -y upgrade
else
_dnf_run "DNF: upgrading all packages" dnf -y upgrade
fi
''}

Copy link
Copy Markdown
Owner

@thrix thrix Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sourcery-ai well, tbh if we want to make it right, we should rather check fi the user is not root, and if not require sudo ...

'';
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;
};
};
}
Loading