1
0
Fork 0
mirror of https://github.com/nix-community/home-manager.git synced 2025-12-08 10:01:05 +01:00
home-manager/nixos/common.nix
David 1a99a515a1 nixos/common: guard nix.package access when nix.enable is false
When nix-darwin has `nix.enable = false` (e.g., for Determinate Nix
users), accessing `config.nix.package` throws an error:

    error: nix.package: accessed when `nix.enable` is off

This regression was introduced in commit a521eab when adding the
`home.uid` option. The code restructuring changed `inherit (config.nix)
package` to be evaluated unconditionally, whereas PR #6383 had
previously ensured this worked correctly.

The fix wraps the package assignment in `mkIf config.nix.enable` to
only access `config.nix.package` when nix management is enabled in the
host OS configuration.

Fixes: #8303
2025-12-05 10:37:47 -06:00

195 lines
5.9 KiB
Nix

# This module is the common base for the NixOS and nix-darwin modules.
# For OS-specific configuration, please edit nixos/default.nix or nix-darwin/default.nix instead.
{
config,
lib,
pkgs,
_class,
...
}:
let
inherit (lib)
flip
mkOption
mkEnableOption
mkIf
types
;
cfg = config.home-manager;
extendedLib = import ../modules/lib/stdlib-extended.nix lib;
hmModule = types.submoduleWith {
description = "Home Manager module";
class = "homeManager";
specialArgs = {
lib = extendedLib;
osConfig = config;
osClass = _class;
modulesPath = builtins.toString ../modules;
}
// cfg.extraSpecialArgs;
modules = [
(
{ name, options, ... }:
{
imports =
import ../modules/modules.nix {
inherit pkgs;
lib = extendedLib;
inherit (cfg) minimal;
useNixpkgsModule = !cfg.useGlobalPkgs;
}
++ cfg.sharedModules;
config = {
submoduleSupport = {
enable = true;
externalPackageInstall = cfg.useUserPackages;
};
home = {
username = config.users.users.${name}.name;
homeDirectory = config.users.users.${name}.home;
uid = mkIf (options.users.users.${name}.uid.isDefined or false) config.users.users.${name}.uid;
};
nix = {
# Forward `nix.enable` from the OS configuration. The
# conditional is to check whether nix-darwin is new enough
# to have the `nix.enable` option; it was previously a
# `mkRemovedOptionModule` error, which we can crudely detect
# by `visible` being set to `false`.
enable = mkIf (options.nix.enable.visible or true) config.nix.enable;
# Make activation script use same version of Nix as system as a whole.
# This avoids problems with Nix not being in PATH.
# Only set package when nix is enabled to avoid errors when
# nix-darwin has nix.enable = false (e.g., Determinate Nix users).
package = mkIf config.nix.enable config.nix.package;
};
};
}
)
];
};
in
{
options.home-manager = {
useUserPackages = mkEnableOption ''
installation of user packages through the
{option}`users.users.<name>.packages` option'';
useGlobalPkgs = mkEnableOption ''
using the system configuration's `pkgs`
argument in Home Manager. This disables the Home Manager
options {option}`nixpkgs.*`'';
backupCommand = mkOption {
type = types.nullOr (types.either types.str types.path);
default = null;
example = lib.literalExpression "\${pkgs.trash-cli}/bin/trash";
description = ''
On activation run this command on each existing file
rather than exiting with an error.
'';
};
backupFileExtension = mkOption {
type = types.nullOr types.str;
default = null;
example = "backup";
description = ''
On activation move existing files by appending the given
file extension rather than exiting with an error.
'';
};
overwriteBackup = mkEnableOption ''
forced overwriting of existing backup files when using `backupFileExtension`
'';
extraSpecialArgs = mkOption {
type = types.attrs;
default = { };
example = lib.literalExpression "{ inherit emacs-overlay; }";
description = ''
Extra `specialArgs` passed to Home Manager. This
option can be used to pass additional arguments to all modules.
'';
};
minimal = mkEnableOption ''
only the necessary modules that allow home-manager to function.
This can be used to allow vendoring a minimal list of modules yourself, rather than
importing every single module.
THIS IS FOR ADVANCED USERS, AND WILL DISABLE ALMOST EVERY MODULE.
THIS SHOULD NOT BE ENABLED UNLESS YOU KNOW THE IMPLICATIONS.
'';
sharedModules = mkOption {
type = with types; listOf raw;
default = [ ];
example = lib.literalExpression "[ { home.packages = [ nixpkgs-fmt ]; } ]";
description = ''
Extra modules added to all users.
'';
};
verbose = mkEnableOption "verbose output on activation";
enableLegacyProfileManagement = mkOption {
type = types.bool;
default = false;
description = ''
Whether to enable legacy profile management during activation. When
enabled, the Home Manager activation will produce a per-user
`home-manager` Nix profile, just like in the standalone installation of
Home Manager. Typically, this is not desired when Home Manager is
embedded in the system configuration.
'';
};
users = mkOption {
type = types.attrsOf hmModule;
default = { };
# Prevent the entire submodule being included in the documentation.
visible = "shallow";
description = ''
Per-user Home Manager configuration.
'';
};
};
config = lib.mkMerge [
# Fix potential recursion when configuring home-manager users based on values in users.users #594
(mkIf (cfg.useUserPackages && cfg.users != { }) {
users.users = lib.mapAttrs (_username: usercfg: { packages = [ usercfg.home.path ]; }) cfg.users;
environment.pathsToLink = [ "/etc/profile.d" ];
})
(mkIf (cfg.users != { }) {
warnings = lib.flatten (
flip lib.mapAttrsToList cfg.users (
user: config: flip map config.warnings (warning: "${user} profile: ${warning}")
)
);
assertions = lib.flatten (
flip lib.mapAttrsToList cfg.users (
user: config:
flip map config.assertions (assertion: {
inherit (assertion) assertion;
message = "${user} profile: ${assertion.message}";
})
)
);
})
];
}