mirror of
https://github.com/LnL7/nix-darwin.git
synced 2025-03-06 00:37:00 +00:00
This process was automated by [my fork of `nix-doc-munge`]; thanks to @pennae for writing this tool! It automatically checks that the resulting documentation doesn't change, although my fork loosens this a little to ignore some irrelevant whitespace and typographical differences. As of this commit there is no DocBook remaining in the options documentation. You can play along at home if you want to reproduce this commit: $ NIX_PATH=nixpkgs=flake:nixpkgs/c1bca7fe84c646cfd4ebf3482c0e6317a0b13f22 \ nix shell nixpkgs#coreutils \ -c find . -name '*.nix' \ -exec nix run github:emilazy/nix-doc-munge/0a7190f600027bf7baf6cb7139e4d69ac2f51062 \ {} + [my fork of `nix-doc-munge`]: https://github.com/emilazy/nix-doc-munge
196 lines
6.8 KiB
Nix
196 lines
6.8 KiB
Nix
{ config, lib, pkgs, ... }:
|
||
|
||
with lib;
|
||
|
||
let
|
||
cfg = config.users;
|
||
|
||
group = import ./group.nix;
|
||
user = import ./user.nix;
|
||
|
||
toArguments = concatMapStringsSep " " (v: "'${v}'");
|
||
toGID = v: { "${toString v.gid}" = v.name; };
|
||
toUID = v: { "${toString v.uid}" = v.name; };
|
||
|
||
isCreated = list: name: elem name list;
|
||
isDeleted = attrs: name: ! elem name (mapAttrsToList (n: v: v.name) attrs);
|
||
|
||
gids = mapAttrsToList (n: toGID) (filterAttrs (n: v: isCreated cfg.knownGroups v.name) cfg.groups);
|
||
uids = mapAttrsToList (n: toUID) (filterAttrs (n: v: isCreated cfg.knownUsers v.name) cfg.users);
|
||
|
||
createdGroups = mapAttrsToList (n: v: cfg.groups."${v}") cfg.gids;
|
||
createdUsers = mapAttrsToList (n: v: cfg.users."${v}") cfg.uids;
|
||
deletedGroups = filter (n: isDeleted cfg.groups n) cfg.knownGroups;
|
||
deletedUsers = filter (n: isDeleted cfg.users n) cfg.knownUsers;
|
||
|
||
packageUsers = filterAttrs (_: u: u.packages != []) cfg.users;
|
||
in
|
||
|
||
{
|
||
options = {
|
||
users.knownGroups = mkOption {
|
||
type = types.listOf types.str;
|
||
default = [];
|
||
description = lib.mdDoc ''
|
||
List of groups owned and managed by nix-darwin. Used to indicate
|
||
what users are safe to create/delete based on the configuration.
|
||
Don't add system groups to this.
|
||
'';
|
||
};
|
||
|
||
users.knownUsers = mkOption {
|
||
type = types.listOf types.str;
|
||
default = [];
|
||
description = lib.mdDoc ''
|
||
List of users owned and managed by nix-darwin. Used to indicate
|
||
what users are safe to create/delete based on the configuration.
|
||
Don't add the admin user or other system users to this.
|
||
'';
|
||
};
|
||
|
||
users.groups = mkOption {
|
||
type = types.attrsOf (types.submodule group);
|
||
default = {};
|
||
description = lib.mdDoc "Configuration for groups.";
|
||
};
|
||
|
||
users.users = mkOption {
|
||
type = types.attrsOf (types.submodule user);
|
||
default = {};
|
||
description = lib.mdDoc "Configuration for users.";
|
||
};
|
||
|
||
users.gids = mkOption {
|
||
internal = true;
|
||
type = types.attrsOf types.str;
|
||
default = {};
|
||
};
|
||
|
||
users.uids = mkOption {
|
||
internal = true;
|
||
type = types.attrsOf types.str;
|
||
default = {};
|
||
};
|
||
|
||
users.forceRecreate = mkOption {
|
||
internal = true;
|
||
type = types.bool;
|
||
default = false;
|
||
description = lib.mdDoc "Remove and recreate existing groups/users.";
|
||
};
|
||
};
|
||
|
||
config = {
|
||
|
||
users.gids = mkMerge gids;
|
||
users.uids = mkMerge uids;
|
||
|
||
system.activationScripts.groups.text = mkIf (cfg.knownGroups != []) ''
|
||
echo "setting up groups..." >&2
|
||
|
||
${concatMapStringsSep "\n" (v: ''
|
||
${optionalString cfg.forceRecreate ''
|
||
g=$(dscl . -read '/Groups/${v.name}' PrimaryGroupID 2> /dev/null) || true
|
||
g=''${g#PrimaryGroupID: }
|
||
if [ "$g" -eq ${toString v.gid} ]; then
|
||
echo "deleting group ${v.name}..." >&2
|
||
dscl . -delete '/Groups/${v.name}' 2> /dev/null
|
||
else
|
||
echo "[1;31mwarning: existing group '${v.name}' has unexpected gid $g, skipping...[0m" >&2
|
||
fi
|
||
''}
|
||
|
||
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}'
|
||
g=${toString v.gid}
|
||
fi
|
||
|
||
if [ "$g" -eq ${toString v.gid} ]; then
|
||
g=$(dscl . -read '/Groups/${v.name}' GroupMembership 2> /dev/null) || true
|
||
if [ "$g" != 'GroupMembership: ${concatStringsSep " " v.members}' ]; then
|
||
echo "updating group members ${v.name}..." >&2
|
||
dscl . -create '/Groups/${v.name}' GroupMembership ${toArguments v.members}
|
||
fi
|
||
else
|
||
echo "[1;31mwarning: existing group '${v.name}' has unexpected gid $g, skipping...[0m" >&2
|
||
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: ''
|
||
${optionalString cfg.forceRecreate ''
|
||
u=$(dscl . -read '/Users/${v.name}' UniqueID 2> /dev/null) || true
|
||
u=''${u#UniqueID: }
|
||
if [ "$u" -eq ${toString v.uid} ]; then
|
||
echo "deleting user ${v.name}..." >&2
|
||
dscl . -delete '/Users/${v.name}' 2> /dev/null
|
||
else
|
||
echo "[1;31mwarning: existing user '${v.name}' has unexpected uid $u, skipping...[0m" >&2
|
||
fi
|
||
''}
|
||
|
||
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}'
|
||
${optionalString v.createHome "createhomedir -cu '${v.name}'"}
|
||
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}
|
||
'';
|
||
|
||
environment.etc = mapAttrs' (name: { packages, ... }: {
|
||
name = "profiles/per-user/${name}";
|
||
value.source = pkgs.buildEnv {
|
||
name = "user-environment";
|
||
paths = packages;
|
||
inherit (config.environment) pathsToLink extraOutputsToInstall;
|
||
inherit (config.system.path) postBuild;
|
||
};
|
||
}) packageUsers;
|
||
|
||
environment.profiles = mkIf (packageUsers != {}) (mkOrder 900 [ "/etc/profiles/per-user/$USER" ]);
|
||
};
|
||
}
|