Use shell packages to select the user's shell

The string type is still available for backward-compatiblity.
This commit is contained in:
zimbatm 2016-06-12 20:03:14 +01:00
parent e2413ad5a8
commit 2974b6f4c8
6 changed files with 43 additions and 20 deletions

View file

@ -100,6 +100,10 @@ rec {
in if isDerivation res then res else toDerivation res; in if isDerivation res then res else toDerivation res;
}; };
shellPackage = package // {
check = x: (package.check x) && (hasAttr "shellPath" x);
};
path = mkOptionType { path = mkOptionType {
name = "path"; name = "path";
# Hacky: there is no isPath primop. # Hacky: there is no isPath primop.

View file

@ -8,4 +8,10 @@ rec {
replaceChars ["/" "-" " "] ["-" "\\x2d" "\\x20"] replaceChars ["/" "-" " "] ["-" "\\x2d" "\\x20"]
(if hasPrefix "/" s then substring 1 (stringLength s) s else s); (if hasPrefix "/" s then substring 1 (stringLength s) s else s);
# Returns a system path for a given shell package
toShellPath = shell:
if types.shellPackage.check shell then
"/run/current-system/sw${shell.shellPath}"
else
shell;
} }

View file

@ -1,7 +1,7 @@
# This module defines a global environment configuration and # This module defines a global environment configuration and
# a common configuration for all shells. # a common configuration for all shells.
{ config, lib, pkgs, ... }: { config, lib, utils, pkgs, ... }:
with lib; with lib;
@ -135,13 +135,13 @@ in
environment.shells = mkOption { environment.shells = mkOption {
default = []; default = [];
example = [ "/run/current-system/sw/bin/zsh" ]; example = literalExample "[ pkgs.bashInteractive pkgs.zsh ]";
description = '' description = ''
A list of permissible login shells for user accounts. A list of permissible login shells for user accounts.
No need to mention <literal>/bin/sh</literal> No need to mention <literal>/bin/sh</literal>
here, it is placed into this list implicitly. here, it is placed into this list implicitly.
''; '';
type = types.listOf types.path; type = types.listOf (types.either types.shellPackage types.path);
}; };
}; };
@ -158,7 +158,7 @@ in
environment.etc."shells".text = environment.etc."shells".text =
'' ''
${concatStringsSep "\n" cfg.shells} ${concatStringsSep "\n" (map utils.toShellPath cfg.shells)}
/bin/sh /bin/sh
''; '';

View file

@ -1,9 +1,8 @@
{ config, lib, pkgs, ... }: { config, lib, utils, pkgs, ... }:
with lib; with lib;
let let
ids = config.ids; ids = config.ids;
cfg = config.users; cfg = config.users;
@ -103,7 +102,7 @@ let
}; };
home = mkOption { home = mkOption {
type = types.str; type = types.path;
default = "/var/empty"; default = "/var/empty";
description = "The user's home directory."; description = "The user's home directory.";
}; };
@ -118,8 +117,10 @@ let
}; };
shell = mkOption { shell = mkOption {
type = types.str; type = types.either types.shellPackage types.path;
default = "/run/current-system/sw/bin/nologin"; default = pkgs.nologin;
defaultText = "pkgs.nologin";
example = literalExample "pkgs.bashInteractive";
description = "The path to the user's shell."; description = "The path to the user's shell.";
}; };
@ -359,11 +360,12 @@ let
spec = pkgs.writeText "users-groups.json" (builtins.toJSON { spec = pkgs.writeText "users-groups.json" (builtins.toJSON {
inherit (cfg) mutableUsers; inherit (cfg) mutableUsers;
users = mapAttrsToList (n: u: users = mapAttrsToList (_: u:
{ inherit (u) { inherit (u)
name uid group description home shell createHome isSystemUser name uid group description home createHome isSystemUser
password passwordFile hashedPassword password passwordFile hashedPassword
initialPassword initialHashedPassword; initialPassword initialHashedPassword;
shell = utils.toShellPath u.shell;
}) cfg.users; }) cfg.users;
groups = mapAttrsToList (n: g: groups = mapAttrsToList (n: g:
{ inherit (g) name gid; { inherit (g) name gid;
@ -373,6 +375,12 @@ let
}) cfg.groups; }) cfg.groups;
}); });
systemShells =
let
shells = mapAttrsToList (_: u: u.shell) cfg.users;
in
filter types.shellPackage.check shells;
in { in {
###### interface ###### interface
@ -478,6 +486,9 @@ in {
}; };
}; };
# Install all the user shells
environment.systemPackages = systemShells;
users.groups = { users.groups = {
root.gid = ids.gids.root; root.gid = ids.gids.root;
wheel.gid = ids.gids.wheel; wheel.gid = ids.gids.wheel;

View file

@ -200,7 +200,7 @@ in
# Configuration for readline in bash. # Configuration for readline in bash.
environment.etc."inputrc".source = ./inputrc; environment.etc."inputrc".source = ./inputrc;
users.defaultUserShell = mkDefault "/run/current-system/sw/bin/bash"; users.defaultUserShell = mkDefault pkgs.bashInteractive;
environment.pathsToLink = optionals cfg.enableCompletion [ environment.pathsToLink = optionals cfg.enableCompletion [
"/etc/bash_completion.d" "/etc/bash_completion.d"

View file

@ -1,6 +1,6 @@
# Configuration for the pwdutils suite of tools: passwd, useradd, etc. # Configuration for the pwdutils suite of tools: passwd, useradd, etc.
{ config, lib, pkgs, ... }: { config, lib, utils, pkgs, ... }:
with lib; with lib;
@ -43,13 +43,13 @@ in
users.defaultUserShell = lib.mkOption { users.defaultUserShell = lib.mkOption {
description = '' description = ''
This option defines the default shell assigned to user This option defines the default shell assigned to user
accounts. This must not be a store path, since the path is accounts. This can be either a full system path or a shell package.
This must not be a store path, since the path is
used outside the store (in particular in /etc/passwd). used outside the store (in particular in /etc/passwd).
Rather, it should be the path of a symlink that points to the
actual shell in the Nix store.
''; '';
example = "/run/current-system/sw/bin/zsh"; example = literalExample "pkgs.zsh";
type = types.path; type = types.either types.path types.shellPackage;
}; };
}; };
@ -60,7 +60,9 @@ in
config = { config = {
environment.systemPackages = environment.systemPackages =
lib.optional config.users.mutableUsers pkgs.shadow; lib.optional config.users.mutableUsers pkgs.shadow ++
lib.optional (types.shellPackage.check config.users.defaultUserShell)
config.users.defaultUserShell;
environment.etc = environment.etc =
[ { # /etc/login.defs: global configuration for pwdutils. You [ { # /etc/login.defs: global configuration for pwdutils. You
@ -74,7 +76,7 @@ in
'' ''
GROUP=100 GROUP=100
HOME=/home HOME=/home
SHELL=${config.users.defaultUserShell} SHELL=${utils.toShellPath config.users.defaultUserShell}
''; '';
target = "default/useradd"; target = "default/useradd";
} }