mirror of
https://github.com/LnL7/nix-darwin.git
synced 2024-12-14 11:57:34 +00:00
users: move submodules to separate files
This commit is contained in:
parent
b8713d540c
commit
3db35e87f0
6 changed files with 225 additions and 234 deletions
|
@ -62,8 +62,7 @@ let
|
|||
./modules/programs/tmux.nix
|
||||
./modules/programs/vim.nix
|
||||
./modules/programs/zsh
|
||||
./modules/users/users.nix
|
||||
./modules/users/groups.nix
|
||||
./modules/users
|
||||
];
|
||||
};
|
||||
|
||||
|
|
116
modules/users/default.nix
Normal file
116
modules/users/default.nix
Normal file
|
@ -0,0 +1,116 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.users;
|
||||
|
||||
group = import ./group.nix;
|
||||
user = import ./user.nix;
|
||||
|
||||
isCreated = list: name: elem name list;
|
||||
isDeleted = attrs: name: ! elem name (mapAttrsToList (n: v: v.name) attrs);
|
||||
|
||||
createdGroups = mapAttrsToList (n: v: v) (filterAttrs (n: v: isCreated cfg.knownGroups v.name) cfg.groups);
|
||||
createdUsers = mapAttrsToList (n: v: v) (filterAttrs (n: v: isCreated cfg.knownUsers v.name) cfg.users);
|
||||
deletedGroups = filter (n: isDeleted cfg.groups n) cfg.knownGroups;
|
||||
deletedUsers = filter (n: isDeleted cfg.users n) cfg.knownUsers;
|
||||
in
|
||||
|
||||
{
|
||||
options = {
|
||||
users.knownGroups = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = "List of groups that should be created and configured.";
|
||||
};
|
||||
|
||||
users.knownUsers = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = "List of users that should be created and configured.";
|
||||
};
|
||||
|
||||
users.groups = mkOption {
|
||||
type = types.loaOf (types.submodule group);
|
||||
default = {};
|
||||
description = "Configuration for groups.";
|
||||
};
|
||||
|
||||
users.users = mkOption {
|
||||
type = types.loaOf (types.submodule user);
|
||||
default = {};
|
||||
description = "Configuration for users.";
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
|
||||
system.activationScripts.groups.text = mkIf (cfg.knownGroups != []) ''
|
||||
echo "setting up groups..." >&2
|
||||
|
||||
${concatMapStringsSep "\n" (v: ''
|
||||
g=$(dscl . -read '/Groups/${v.name}' PrimaryGroupID 2> /dev/null) || true
|
||||
g=''${g#PrimaryGroupID: }
|
||||
if [ -z "$g" ]; then
|
||||
echo "creating group ${v.name}..." >&2
|
||||
dscl . -create '/Groups/${v.name}' PrimaryGroupID ${toString v.gid}
|
||||
dscl . -create '/Groups/${v.name}' RealName '${v.description}'
|
||||
else
|
||||
if [ "$g" -ne ${toString v.gid} ]; then
|
||||
echo "[1;31mwarning: existing group '${v.name}' has unexpected gid $g, skipping...[0m" >&2
|
||||
fi
|
||||
fi
|
||||
'') createdGroups}
|
||||
|
||||
${concatMapStringsSep "\n" (name: ''
|
||||
g=$(dscl . -read '/Groups/${name}' PrimaryGroupID 2> /dev/null) || true
|
||||
g=''${g#PrimaryGroupID: }
|
||||
if [ -n "$g" ]; then
|
||||
if [ "$g" -gt 501 ]; then
|
||||
echo "deleting group ${name}..." >&2
|
||||
dscl . -delete '/Groups/${name}' 2> /dev/null
|
||||
else
|
||||
echo "[1;31mwarning: existing group '${name}' has unexpected gid $g, skipping...[0m" >&2
|
||||
fi
|
||||
fi
|
||||
'') deletedGroups}
|
||||
'';
|
||||
|
||||
system.activationScripts.users.text = mkIf (cfg.knownUsers != []) ''
|
||||
echo "setting up users..." >&2
|
||||
|
||||
${concatMapStringsSep "\n" (v: ''
|
||||
u=$(dscl . -read '/Users/${v.name}' UniqueID 2> /dev/null) || true
|
||||
u=''${u#UniqueID: }
|
||||
if [ -z "$u" ]; then
|
||||
echo "creating user ${v.name}..." >&2
|
||||
dscl . -create '/Users/${v.name}' UniqueID ${toString v.uid}
|
||||
dscl . -create '/Users/${v.name}' PrimaryGroupID ${toString v.gid}
|
||||
dscl . -create '/Users/${v.name}' IsHidden ${if v.isHidden then "1" else "0"}
|
||||
dscl . -create '/Users/${v.name}' RealName '${v.description}'
|
||||
dscl . -create '/Users/${v.name}' NFSHomeDirectory '${v.home}'
|
||||
dscl . -create '/Users/${v.name}' UserShell '${v.shell}'
|
||||
else
|
||||
if [ "$u" -ne ${toString v.uid} ]; then
|
||||
echo "[1;31mwarning: existing user '${v.name}' has unexpected uid $u, skipping...[0m" >&2
|
||||
fi
|
||||
fi
|
||||
'') createdUsers}
|
||||
|
||||
${concatMapStringsSep "\n" (name: ''
|
||||
u=$(dscl . -read '/Users/${name}' UniqueID 2> /dev/null) || true
|
||||
u=''${u#UniqueID: }
|
||||
if [ -n "$u" ]; then
|
||||
if [ "$u" -gt 501 ]; then
|
||||
echo "deleting user ${name}..." >&2
|
||||
dscl . -delete '/Users/${name}' 2> /dev/null
|
||||
else
|
||||
echo "[1;31mwarning: existing user '${name}' has unexpected uid $u, skipping...[0m" >&2
|
||||
fi
|
||||
fi
|
||||
'') deletedUsers}
|
||||
'';
|
||||
|
||||
};
|
||||
}
|
35
modules/users/group.nix
Normal file
35
modules/users/group.nix
Normal file
|
@ -0,0 +1,35 @@
|
|||
{ name, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
options = {
|
||||
gid = mkOption {
|
||||
type = mkOptionType {
|
||||
name = "gid";
|
||||
check = t: isInt t && t > 501;
|
||||
};
|
||||
description = "The group's GID.";
|
||||
};
|
||||
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
The group's name. If undefined, the name of the attribute set
|
||||
will be used.
|
||||
'';
|
||||
};
|
||||
|
||||
description = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
description = "The group's description.";
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
|
||||
name = mkDefault name;
|
||||
|
||||
};
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.users;
|
||||
|
||||
isCreatedGroup = name: elem name cfg.knownGroups;
|
||||
isDeletedGroup = name: ! elem name (mapAttrsToList (n: v: v.name) cfg.groups);
|
||||
|
||||
createdGroups = mapAttrsToList (n: v: v) (filterAttrs (n: v: isCreatedGroup v.name) cfg.groups);
|
||||
deletedGroups = filter (n: isDeletedGroup n) cfg.knownGroups;
|
||||
|
||||
group =
|
||||
{ name, ... }:
|
||||
{
|
||||
options = {
|
||||
gid = mkOption {
|
||||
type = mkOptionType {
|
||||
name = "gid";
|
||||
check = t: isInt t && t > 501;
|
||||
};
|
||||
description = "The group's GID.";
|
||||
};
|
||||
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
The group's name. If undefined, the name of the attribute set
|
||||
will be used.
|
||||
'';
|
||||
};
|
||||
|
||||
description = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
description = "The group's description.";
|
||||
};
|
||||
};
|
||||
config = {
|
||||
name = mkDefault name;
|
||||
};
|
||||
};
|
||||
in
|
||||
|
||||
{
|
||||
options = {
|
||||
users.knownGroups = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = "List of groups that should be created and configured.";
|
||||
};
|
||||
|
||||
users.groups = mkOption {
|
||||
type = types.loaOf (types.submodule group);
|
||||
default = {};
|
||||
description = "Configuration for groups.";
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
|
||||
system.activationScripts.groups.text = mkIf (cfg.knownGroups != []) ''
|
||||
echo "setting up groups..." >&2
|
||||
|
||||
${concatMapStringsSep "\n" (v: ''
|
||||
g=$(dscl . -read '/Groups/${v.name}' PrimaryGroupID 2> /dev/null) || true
|
||||
g=''${g#PrimaryGroupID: }
|
||||
if [ -z "$g" ]; then
|
||||
echo "creating group ${v.name}..." >&2
|
||||
dscl . -create '/Groups/${v.name}' PrimaryGroupID ${toString v.gid}
|
||||
dscl . -create '/Groups/${v.name}' RealName '${v.description}'
|
||||
else
|
||||
if [ "$g" -ne ${toString v.gid} ]; then
|
||||
echo "[1;31mwarning: existing group '${v.name}' has unexpected gid $g, skipping...[0m" >&2
|
||||
fi
|
||||
fi
|
||||
'') createdGroups}
|
||||
|
||||
${concatMapStringsSep "\n" (name: ''
|
||||
g=$(dscl . -read '/Groups/${name}' PrimaryGroupID 2> /dev/null) || true
|
||||
g=''${g#PrimaryGroupID: }
|
||||
if [ -n "$g" ]; then
|
||||
if [ "$g" -gt 501 ]; then
|
||||
echo "deleting group ${name}..." >&2
|
||||
dscl . -delete '/Groups/${name}' 2> /dev/null
|
||||
else
|
||||
echo "[1;31mwarning: existing group '${name}' has unexpected gid $g, skipping...[0m" >&2
|
||||
fi
|
||||
fi
|
||||
'') deletedGroups}
|
||||
'';
|
||||
|
||||
};
|
||||
}
|
73
modules/users/user.nix
Normal file
73
modules/users/user.nix
Normal file
|
@ -0,0 +1,73 @@
|
|||
{ name, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
options = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Whether this user should be created.";
|
||||
};
|
||||
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
The name of the user account. If undefined, the name of the
|
||||
attribute set will be used.
|
||||
'';
|
||||
};
|
||||
|
||||
description = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
example = "Alice Q. User";
|
||||
description = ''
|
||||
A short description of the user account, typically the
|
||||
user's full name.
|
||||
'';
|
||||
};
|
||||
|
||||
uid = mkOption {
|
||||
type = types.int;
|
||||
description = "The user's UID.";
|
||||
};
|
||||
|
||||
gid = mkOption {
|
||||
type = types.int;
|
||||
default = 20;
|
||||
description = "The user's primary group.";
|
||||
};
|
||||
|
||||
isHidden = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Whether to make the user account hidden.";
|
||||
};
|
||||
|
||||
# extraGroups = mkOption {
|
||||
# type = types.listOf types.str;
|
||||
# default = [];
|
||||
# description = "The user's auxiliary groups.";
|
||||
# };
|
||||
|
||||
home = mkOption {
|
||||
type = types.path;
|
||||
default = "/var/empty";
|
||||
description = "The user's home directory.";
|
||||
};
|
||||
|
||||
shell = mkOption {
|
||||
type = types.either types.shellPackage types.path;
|
||||
default = "/sbin/nologin";
|
||||
example = literalExample "pkgs.bashInteractive";
|
||||
description = "The user's shell.";
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
|
||||
name = mkDefault name;
|
||||
|
||||
};
|
||||
}
|
|
@ -1,137 +0,0 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.users;
|
||||
|
||||
isCreatedUser = name: elem name cfg.knownUsers;
|
||||
isDeletedUser = name: ! elem name (mapAttrsToList (n: v: v.name) cfg.users);
|
||||
|
||||
createdUsers = mapAttrsToList (n: v: v) (filterAttrs (n: v: isCreatedUser v.name) cfg.users);
|
||||
deletedUsers = filter (n: isDeletedUser n) cfg.knownUsers;
|
||||
|
||||
user =
|
||||
{ name, ... }:
|
||||
{
|
||||
options = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Whether this user should be created.";
|
||||
};
|
||||
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
The name of the user account. If undefined, the name of the
|
||||
attribute set will be used.
|
||||
'';
|
||||
};
|
||||
|
||||
description = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
example = "Alice Q. User";
|
||||
description = ''
|
||||
A short description of the user account, typically the
|
||||
user's full name.
|
||||
'';
|
||||
};
|
||||
|
||||
uid = mkOption {
|
||||
type = types.int;
|
||||
description = "The user's UID.";
|
||||
};
|
||||
|
||||
gid = mkOption {
|
||||
type = types.int;
|
||||
default = 20;
|
||||
description = "The user's primary group.";
|
||||
};
|
||||
|
||||
isHidden = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Whether to make the user account hidden.";
|
||||
};
|
||||
|
||||
# extraGroups = mkOption {
|
||||
# type = types.listOf types.str;
|
||||
# default = [];
|
||||
# description = "The user's auxiliary groups.";
|
||||
# };
|
||||
|
||||
home = mkOption {
|
||||
type = types.path;
|
||||
default = "/var/empty";
|
||||
description = "The user's home directory.";
|
||||
};
|
||||
|
||||
shell = mkOption {
|
||||
type = types.either types.shellPackage types.path;
|
||||
default = "/sbin/nologin";
|
||||
example = literalExample "pkgs.bashInteractive";
|
||||
description = "The user's shell.";
|
||||
};
|
||||
};
|
||||
config = {
|
||||
name = mkDefault name;
|
||||
};
|
||||
};
|
||||
in
|
||||
|
||||
{
|
||||
options = {
|
||||
users.knownUsers = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = "List of users that should be created and configured.";
|
||||
};
|
||||
|
||||
users.users = mkOption {
|
||||
type = types.loaOf (types.submodule user);
|
||||
default = {};
|
||||
description = "Configuration for users.";
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
|
||||
system.activationScripts.users.text = mkIf (cfg.knownUsers != []) ''
|
||||
echo "setting up users..." >&2
|
||||
|
||||
${concatMapStringsSep "\n" (v: ''
|
||||
u=$(dscl . -read '/Users/${v.name}' UniqueID 2> /dev/null) || true
|
||||
u=''${u#UniqueID: }
|
||||
if [ -z "$u" ]; then
|
||||
echo "creating user ${v.name}..." >&2
|
||||
dscl . -create '/Users/${v.name}' UniqueID ${toString v.uid}
|
||||
dscl . -create '/Users/${v.name}' PrimaryGroupID ${toString v.gid}
|
||||
dscl . -create '/Users/${v.name}' IsHidden ${if v.isHidden then "1" else "0"}
|
||||
dscl . -create '/Users/${v.name}' RealName '${v.description}'
|
||||
dscl . -create '/Users/${v.name}' NFSHomeDirectory '${v.home}'
|
||||
dscl . -create '/Users/${v.name}' UserShell '${v.shell}'
|
||||
else
|
||||
if [ "$u" -ne ${toString v.uid} ]; then
|
||||
echo "[1;31mwarning: existing user '${v.name}' has unexpected uid $u, skipping...[0m" >&2
|
||||
fi
|
||||
fi
|
||||
'') createdUsers}
|
||||
|
||||
${concatMapStringsSep "\n" (name: ''
|
||||
u=$(dscl . -read '/Users/${name}' UniqueID 2> /dev/null) || true
|
||||
u=''${u#UniqueID: }
|
||||
if [ -n "$u" ]; then
|
||||
if [ "$u" -gt 501 ]; then
|
||||
echo "deleting user ${name}..." >&2
|
||||
dscl . -delete '/Users/${name}' 2> /dev/null
|
||||
else
|
||||
echo "[1;31mwarning: existing user '${name}' has unexpected uid $u, skipping...[0m" >&2
|
||||
fi
|
||||
fi
|
||||
'') deletedUsers}
|
||||
'';
|
||||
|
||||
};
|
||||
}
|
Loading…
Reference in a new issue