368 lines
		
	
	
	
		
			9.4 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			368 lines
		
	
	
	
		
			9.4 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;
 | 
						|
    hass = 2004;
 | 
						|
    syncthing = 2007;
 | 
						|
    ollama = 2008;
 | 
						|
    git = 2009;
 | 
						|
    immich = 2010;
 | 
						|
    qbittorrent = 2011;
 | 
						|
    paperless = 2012;
 | 
						|
    actual = 2013;
 | 
						|
  };
 | 
						|
 | 
						|
  gids = {
 | 
						|
    leyla = 1000;
 | 
						|
    eve = 1002;
 | 
						|
    users = 100;
 | 
						|
    jellyfin_media = 2001;
 | 
						|
    jellyfin = 2000;
 | 
						|
    forgejo = 2002;
 | 
						|
    hass = 2004;
 | 
						|
    syncthing = 2007;
 | 
						|
    ollama = 2008;
 | 
						|
    git = 2009;
 | 
						|
    immich = 2010;
 | 
						|
    qbittorrent = 2011;
 | 
						|
    paperless = 2012;
 | 
						|
    actual = 2013;
 | 
						|
  };
 | 
						|
 | 
						|
  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"]
 | 
						|
              ++ (lib.lists.optionals host.users.eve.isPrincipleUser ["wheel"]);
 | 
						|
            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;
 | 
						|
          };
 | 
						|
 | 
						|
          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;
 | 
						|
            isSystemUser = true;
 | 
						|
            group = config.users.users.qbittorrent.name;
 | 
						|
          };
 | 
						|
 | 
						|
          paperless = {
 | 
						|
            uid = lib.mkForce uids.paperless;
 | 
						|
            isSystemUser = true;
 | 
						|
            group = config.users.users.paperless.name;
 | 
						|
          };
 | 
						|
 | 
						|
          actual = {
 | 
						|
            uid = lib.mkForce uids.actual;
 | 
						|
            isSystemUser = true;
 | 
						|
            group = config.users.users.actual.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
 | 
						|
            ];
 | 
						|
          };
 | 
						|
 | 
						|
          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
 | 
						|
            ];
 | 
						|
          };
 | 
						|
 | 
						|
          paperless = {
 | 
						|
            gid = lib.mkForce gids.paperless;
 | 
						|
            members = [
 | 
						|
              users.paperless.name
 | 
						|
            ];
 | 
						|
          };
 | 
						|
 | 
						|
          actual = {
 | 
						|
            gid = lib.mkForce gids.actual;
 | 
						|
            members = [
 | 
						|
              users.actual.name
 | 
						|
            ];
 | 
						|
          };
 | 
						|
        };
 | 
						|
      };
 | 
						|
    }
 | 
						|
    (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
 | 
						|
        )
 | 
						|
      );
 | 
						|
    })
 | 
						|
  ];
 | 
						|
}
 |