nix-config/modules/nixos-modules/users.nix

353 lines
9.1 KiB
Nix

{
lib,
config,
inputs,
...
}: let
SOPS_AGE_KEY_DIRECTORY = import ../../const/sops_age_key_directory.nix;
host = config.host;
principleUsers = host.principleUsers;
terminalUsers = host.terminalUsers;
normalUsers = host.normalUsers;
uids = {
leyla = 1000;
eve = 1002;
jellyfin = 2000;
forgejo = 2002;
adguardhome = 2003;
hass = 2004;
syncthing = 2007;
ollama = 2008;
git = 2009;
immich = 2010;
qbittorrent = 2011;
};
gids = {
leyla = 1000;
eve = 1002;
users = 100;
jellyfin_media = 2001;
jellyfin = 2000;
forgejo = 2002;
adguardhome = 2003;
hass = 2004;
syncthing = 2007;
ollama = 2008;
git = 2009;
immich = 2010;
qbittorrent = 2011;
};
users = config.users.users;
leyla = users.leyla.name;
eve = users.eve.name;
in {
config = lib.mkMerge [
{
# principle users are by definition trusted
nix.settings.trusted-users = builtins.map (user: user.name) principleUsers;
# we should only be able to ssh into principle users of a computer who are also set up for terminal access
services.openssh.settings.AllowUsers = builtins.map (user: user.name) (lib.lists.intersectLists terminalUsers principleUsers);
# we need to set up env variables to nix can find keys to decrypt passwords on rebuild
environment = {
sessionVariables = {
SOPS_AGE_KEY_DIRECTORY = SOPS_AGE_KEY_DIRECTORY;
SOPS_AGE_KEY_FILE = "${SOPS_AGE_KEY_DIRECTORY}/key.txt";
};
};
# set up user passwords
sops = {
defaultSopsFormat = "yaml";
gnupg.sshKeyPaths = [];
age = {
keyFile = "/var/lib/sops-nix/key.txt";
sshKeyPaths = [];
# generateKey = true;
};
secrets = {
"passwords/leyla" = {
neededForUsers = true;
sopsFile = "${inputs.secrets}/user-passwords.yaml";
};
"passwords/eve" = {
neededForUsers = true;
sopsFile = "${inputs.secrets}/user-passwords.yaml";
};
};
};
users = {
mutableUsers = false;
users = {
leyla = {
uid = lib.mkForce uids.leyla;
name = lib.mkForce host.users.leyla.name;
description = "Leyla";
extraGroups =
(lib.lists.optionals host.users.leyla.isNormalUser ["networkmanager"])
++ (lib.lists.optionals host.users.leyla.isPrincipleUser ["wheel" "dialout"])
++ (lib.lists.optionals host.users.leyla.isDesktopUser ["adbusers"]);
hashedPasswordFile = config.sops.secrets."passwords/leyla".path;
isNormalUser = host.users.leyla.isNormalUser;
isSystemUser = !host.users.leyla.isNormalUser;
group = config.users.users.leyla.name;
};
eve = {
uid = lib.mkForce uids.eve;
name = lib.mkForce host.users.eve.name;
description = "Eve";
extraGroups = lib.optionals host.users.eve.isNormalUser ["networkmanager"];
hashedPasswordFile = config.sops.secrets."passwords/eve".path;
isNormalUser = host.users.eve.isNormalUser;
isSystemUser = !host.users.eve.isNormalUser;
group = config.users.users.eve.name;
};
jellyfin = {
uid = lib.mkForce uids.jellyfin;
isSystemUser = true;
group = config.users.users.jellyfin.name;
};
forgejo = {
uid = lib.mkForce uids.forgejo;
isSystemUser = true;
group = config.users.users.forgejo.name;
};
adguardhome = {
uid = lib.mkForce uids.adguardhome;
isSystemUser = true;
group = config.users.users.adguardhome.name;
};
hass = {
uid = lib.mkForce uids.hass;
isSystemUser = true;
group = config.users.users.hass.name;
};
syncthing = {
uid = lib.mkForce uids.syncthing;
isSystemUser = true;
group = config.users.users.syncthing.name;
};
ollama = {
uid = lib.mkForce uids.ollama;
isSystemUser = true;
group = config.users.users.ollama.name;
};
git = {
uid = lib.mkForce uids.git;
isSystemUser = !config.services.forgejo.enable;
isNormalUser = config.services.forgejo.enable;
group = config.users.users.git.name;
};
immich = {
uid = lib.mkForce uids.immich;
isSystemUser = true;
group = config.users.users.immich.name;
};
qbittorrent = {
uid = lib.mkForce uids.qbittorrent;
isNormalUser = true;
group = config.users.users.qbittorrent.name;
};
};
groups = {
leyla = {
gid = lib.mkForce gids.leyla;
members = [
leyla
];
};
eve = {
gid = lib.mkForce gids.eve;
members = [
eve
];
};
users = {
gid = lib.mkForce gids.users;
members = [
leyla
eve
];
};
jellyfin_media = {
gid = lib.mkForce gids.jellyfin_media;
members = [
users.jellyfin.name
leyla
eve
];
};
jellyfin = {
gid = lib.mkForce gids.jellyfin;
members = [
users.jellyfin.name
# leyla
];
};
forgejo = {
gid = lib.mkForce gids.forgejo;
members = [
users.forgejo.name
# leyla
];
};
adguardhome = {
gid = lib.mkForce gids.adguardhome;
members = [
users.adguardhome.name
# leyla
];
};
hass = {
gid = lib.mkForce gids.hass;
members = [
users.hass.name
# leyla
];
};
syncthing = {
gid = lib.mkForce gids.syncthing;
members = [
users.syncthing.name
leyla
eve
];
};
ollama = {
gid = lib.mkForce gids.ollama;
members = [
users.ollama.name
];
};
git = {
gid = lib.mkForce gids.git;
members = [
users.git.name
];
};
immich = {
gid = lib.mkForce gids.immich;
members = [
users.immich.name
# leyla
];
};
qbittorrent = {
gid = lib.mkForce gids.qbittorrent;
members = [
users.qbittorrent.name
leyla
];
};
};
};
}
(lib.mkIf config.host.impermanence.enable {
boot.initrd.postResumeCommands = lib.mkAfter (
lib.strings.concatLines (builtins.map (user: "zfs rollback -r rpool/local/home/${user.name}@blank")
normalUsers)
);
systemd = {
tmpfiles.rules =
builtins.map (
user: "d /persist/home/${user.name} 700 ${user.name} ${user.name} -"
)
normalUsers;
};
fileSystems = lib.mkMerge [
{
${SOPS_AGE_KEY_DIRECTORY}.neededForBoot = true;
}
(
builtins.listToAttrs (
builtins.map (user:
lib.attrsets.nameValuePair "/persist/home/${user.name}" {
neededForBoot = true;
})
normalUsers
)
)
(
builtins.listToAttrs (
builtins.map (user:
lib.attrsets.nameValuePair "/home/${user.name}" {
neededForBoot = true;
})
normalUsers
)
)
];
host.storage.pool.extraDatasets = lib.mkMerge (
[
{
# sops age key needs to be available to pre persist for user generation
"local/system/sops" = {
type = "zfs_fs";
mountpoint = SOPS_AGE_KEY_DIRECTORY;
options = {
atime = "off";
relatime = "off";
canmount = "on";
};
};
}
]
++ (
builtins.map (user: {
"local/home/${user.name}" = {
type = "zfs_fs";
mountpoint = "/home/${user.name}";
options = {
canmount = "on";
};
postCreateHook = ''
zfs snapshot rpool/local/home/${user.name}@blank
'';
};
"persist/home/${user.name}" = {
type = "zfs_fs";
mountpoint = "/persist/home/${user.name}";
};
})
normalUsers
)
);
})
];
}