diff --git a/modules/users/default.nix b/modules/users/default.nix index 2adf8132..ade4ffbc 100644 --- a/modules/users/default.nix +++ b/modules/users/default.nix @@ -2,8 +2,8 @@ let inherit (lib) concatStringsSep concatMapStringsSep elem escapeShellArg - escapeShellArgs filter filterAttrs mapAttrs' mapAttrsToList mkAfter - mkIf mkMerge mkOption mkOrder mkRemovedOptionModule optionals + escapeShellArgs filter filterAttrs flatten flip mapAttrs' mapAttrsToList + mkAfter mkIf mkMerge mkOption mkOrder mkRemovedOptionModule optionals optionalString types; cfg = config.users; @@ -105,7 +105,29 @@ in assertion = !builtins.elem "root" deletedUsers; message = "Remove `root` from `users.knownUsers` if you no longer want nix-darwin to manage it."; } - ]; + ] ++ flatten (flip mapAttrsToList cfg.users (name: user: + map (shell: { + assertion = let + s = user.shell.pname or null; + in + !user.ignoreShellProgramCheck -> (s == shell || (shell == "bash" && s == "bash-interactive")) -> (config.programs.${shell}.enable == true); + message = '' + users.users.${user.name}.shell is set to ${shell}, but + programs.${shell}.enable is not true. This will cause the ${shell} + shell to lack the basic Nix directories in its PATH and might make + logging in as that user impossible. You can fix it with: + programs.${shell}.enable = true; + + If you know what you're doing and you are fine with the behavior, + set users.users.${user.name}.ignoreShellProgramCheck = true; + instead. + ''; + }) [ + "bash" + "fish" + "zsh" + ] + )); users.gids = mkMerge gids; users.uids = mkMerge uids; diff --git a/modules/users/user.nix b/modules/users/user.nix index 9689e052..5256ac3b 100644 --- a/modules/users/user.nix +++ b/modules/users/user.nix @@ -84,6 +84,17 @@ ''; }; + ignoreShellProgramCheck = mkOption { + type = types.bool; + default = false; + description = '' + By default, nix-darwin will check that programs.SHELL.enable is set to + true if the user has a custom shell specified. If that behavior isn't + required and there are custom overrides in place to make sure that the + shell is functional, set this to true. + ''; + }; + packages = mkOption { type = types.listOf types.package; default = [];