diff --git a/hosts/patricknix/fs.nix b/hosts/patricknix/fs.nix index 4eaf880..ca3b62c 100644 --- a/hosts/patricknix/fs.nix +++ b/hosts/patricknix/fs.nix @@ -24,5 +24,6 @@ }; }; fileSystems."/state".neededForBoot = true; + fileSystems."/persist".neededForBoot = true; boot.initrd.luks.devices.enc-rpool.allowDiscards = true; } diff --git a/hosts/testienix/default.nix b/hosts/testienix/default.nix index 760b8cd..264a7ee 100644 --- a/hosts/testienix/default.nix +++ b/hosts/testienix/default.nix @@ -10,6 +10,8 @@ ../../modules/hardware/physical.nix ../../modules/hardware/zfs.nix + ../../modules/services/samba.nix + ./net.nix ./fs.nix ]; diff --git a/hosts/testienix/fs.nix b/hosts/testienix/fs.nix index 81faed8..810d8ea 100644 --- a/hosts/testienix/fs.nix +++ b/hosts/testienix/fs.nix @@ -59,6 +59,7 @@ fileSystems."/state".neededForBoot = true; fileSystems."/panzer/state".neededForBoot = true; + fileSystems."/panzer/persist".neededForBoot = true; boot.initrd.luks.devices.enc-rpool.allowDiscards = true; boot.initrd.luks.devices.enc-panzer-1.allowDiscards = true; boot.initrd.luks.devices.enc-panzer-2.allowDiscards = true; diff --git a/modules/config/default.nix b/modules/config/default.nix index 8be3253..1124ed8 100644 --- a/modules/config/default.nix +++ b/modules/config/default.nix @@ -9,6 +9,7 @@ ./nix.nix ./ssh.nix ./system.nix + ./users.nix ./xdg.nix ./usbguard.nix @@ -17,6 +18,7 @@ ../secrets.nix ../meta.nix ../smb-mounts.nix + ../deterministic-ids.nix ./impermanence inputs.home-manager.nixosModules.default diff --git a/modules/config/system.nix b/modules/config/system.nix index 02dd798..10c7402 100644 --- a/modules/config/system.nix +++ b/modules/config/system.nix @@ -47,7 +47,6 @@ keyMap = lib.mkDefault "de-latin1-nodeadkeys"; }; - users.mutableUsers = false; environment.systemPackages = with pkgs; [ wget gcc diff --git a/modules/config/users.nix b/modules/config/users.nix new file mode 100644 index 0000000..d715291 --- /dev/null +++ b/modules/config/users.nix @@ -0,0 +1,17 @@ +{ + users.mutableUsers = false; + users.deterministicIds = let + uidGid = id: { + uid = id; + gid = id; + }; + in { + smb = uidGid 200; + nscd = uidGid 201; + sshd = uidGid 202; + tss = uidGid 203; + polkituser = uidGid 204; + systemd-oom = uidGid 300; + systemd-coredump = uidGid 301; + }; +} diff --git a/modules/deterministic-ids.nix b/modules/deterministic-ids.nix new file mode 100644 index 0000000..65d931c --- /dev/null +++ b/modules/deterministic-ids.nix @@ -0,0 +1,80 @@ +{ + lib, + config, + ... +}: let + inherit + (lib) + concatLists + flip + mapAttrsToList + mkDefault + mdDoc + mkIf + mkOption + types + ; + + cfg = config.users.deterministicIds; +in { + options = { + users.deterministicIds = mkOption { + default = {}; + description = mdDoc '' + Maps a user or group name to its expected uid/gid values. If a user/group is + used on the system without specifying a uid/gid, this module will assign the + corresponding ids defined here, or show an error if the definition is missing. + ''; + type = types.attrsOf (types.submodule { + options = { + uid = mkOption { + type = types.nullOr types.int; + default = null; + description = mdDoc "The uid to assign if it is missing in `users.users.`."; + }; + gid = mkOption { + type = types.nullOr types.int; + default = null; + description = mdDoc "The gid to assign if it is missing in `users.groups.`."; + }; + }; + }); + }; + + users.users = mkOption { + type = types.attrsOf (types.submodule ({name, ...}: { + config.uid = let + deterministicUid = cfg.${name}.uid or null; + in + mkIf (deterministicUid != null) (mkDefault deterministicUid); + })); + }; + + users.groups = mkOption { + type = types.attrsOf (types.submodule ({name, ...}: { + config.gid = let + deterministicGid = cfg.${name}.gid or null; + in + mkIf (deterministicGid != null) (mkDefault deterministicGid); + })); + }; + }; + + config = { + assertions = + concatLists (flip mapAttrsToList config.users.users (name: user: [ + { + assertion = user.uid != null; + message = "non-deterministic uid detected for '${name}', please assign one via `users.deterministicIds`"; + } + { + assertion = !user.autoSubUidGidRange; + message = "non-deterministic subUids/subGids detected for: ${name}"; + } + ])) + ++ flip mapAttrsToList config.users.groups (name: group: { + assertion = group.gid != null; + message = "non-deterministic gid detected for '${name}', please assign one via `users.deterministicIds`"; + }); + }; +} diff --git a/modules/services/samba.nix b/modules/services/samba.nix new file mode 100644 index 0000000..72ff605 --- /dev/null +++ b/modules/services/samba.nix @@ -0,0 +1,87 @@ +{config, ...}: { + services.samba-wsdd.enable = true; # make shares visible for windows 10 clients + networking.firewall.allowedTCPPorts = [ + 5357 # wsdd + ]; + networking.firewall.allowedUDPPorts = [ + 3702 # wsdd + ]; + services.samba = { + enable = true; + securityType = "user"; + openFirewall = true; + extraConfig = '' + logging = systemd + log level = 1 + hosts allow = 192.168.178. 127.0.0.1 10.0.0. localhost + hosts deny = 0.0.0.0/0 + guest account = nobody + map to guest = bad user + passdb backend = tdbsam:/tmp/smbpasswd.tdb + ''; + shares = { + ggr-data = { + path = /media/smb/ggr-data; + "read only" = "no"; + "guest ok" = "no"; + "create mask" = "0640"; + "directory mask" = "0750"; + "force user" = "smb"; + "force group" = "smb"; + "valid users" = "smb"; + }; + patri-data = { + path = /media/smb/patri-data; + "read only" = "no"; + "guest ok" = "no"; + "create mask" = "0640"; + "directory mask" = "0755"; + "force user" = "smb"; + "force group" = "smb"; + "valid users" = "smb"; + }; + media = { + path = /media/smb/media; + "read only" = "yes"; + "guest ok" = "yes"; + "create mask" = "0640"; + "directory mask" = "0750"; + "force user" = "smb"; + "force group" = "smb"; + "write list" = "smb"; + }; + }; + }; + age.secrets.smbpasswd.rekeyFile = ../../secrets/smbpasswd.age; + system.activationScripts.importSMBPasswd = { + text = '' + ${config.services.samba.package}/bin/pdbedit -i smbpasswd:${config.age.secrets.smbpasswd.path} -e tdbsam:/tmp/smbpasswd.tdb + ''; + }; + users.users.smb = { + isSystemUser = true; + group = "smb"; + hashedPassword = config.secrets.secrets.global.users.smb.passwordHash; + }; + users.groups.smb = {}; + environment.persistence."/panzer/persist".directories = [ + { + directory = "/media/smb/ggr-data"; + user = "smb"; + group = "smb"; + mode = "0750"; + } + { + directory = "/media/smb/patri-data"; + user = "smb"; + group = "smb"; + mode = "0750"; + } + { + directory = "/media/smb/media"; + user = "smb"; + group = "smb"; + mode = "0750"; + } + ]; +} diff --git a/secrets/secrets.nix.age b/secrets/secrets.nix.age index 732f732..b7d4eb4 100644 Binary files a/secrets/secrets.nix.age and b/secrets/secrets.nix.age differ diff --git a/secrets/smbpasswd.age b/secrets/smbpasswd.age new file mode 100644 index 0000000..3072419 --- /dev/null +++ b/secrets/smbpasswd.age @@ -0,0 +1,12 @@ +age-encryption.org/v1 +-> X25519 +UZl4Y69NOKiZi0MJJv2/3mGCgjZRXZdrEVfBRY2NF4 +CthaYoLtCoMLHiyS8L19HC77uuCj6aS/98qEdscRJMI +-> piv-p256 XTQkUA A3Tarwc4HTchv1AfPFSA9b+k3ZsTG92/MHZfQ9SdMZ1G +U8fOA4rkZjBKDEvsrM+B4WuUMvglyL424kmOYsnKYDA +-> piv-p256 ZFgiIw Al8+gVzwlrMIreKKwaUN/nefUxXnBTwFbWK7bofuXeTN +dkQzqvyI6UgyQFCkEuNjaN/fNDt+h9WVhlZCfmZ9hgg +-> :>hC-grease +lzYcEp/H6m//Nh4i7BHCaIrledYuikG5NzA1VinqtyIgXFSVMNQzERL9cPz/XJu5 +il4xJbAR01BSJIRvX//JMNJEC7U+hEAP +--- XU8Jypn1JQeq8Y8YpFAtQWhJQR8bhvUndsReymbdqSY +ÃDV!8:2?b