adapt generator modules from clan-core modules
see https://git.clan.lol/clan/clan-core/src/branch/main/clanServices
This commit is contained in:
		
							parent
							
								
									39f4680381
								
							
						
					
					
						commit
						0da36a23e0
					
				
					 15 changed files with 511 additions and 0 deletions
				
			
		|  | @ -16,6 +16,7 @@ | |||
|     in { | ||||
|       nixosModules.default = { imports = [ ./options.nix ]; }; | ||||
|       nixosModules.backend-on-machine = { imports = [ ./backends/on-machine.nix ]; }; | ||||
|       nixosModules.generators = { imports = [ ./generators ]; }; | ||||
|       # TODO fix tests | ||||
|       checks = forAllSystems (system: let | ||||
|         tests = { | ||||
|  |  | |||
							
								
								
									
										11
									
								
								generators/default.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								generators/default.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | |||
| { | ||||
|   imports = [ | ||||
|     ./disk-id | ||||
|     ./garage | ||||
|     ./machine-id | ||||
|     ./root-password | ||||
|     ./sshd | ||||
|     ./state-version | ||||
|     ./user-password | ||||
|   ]; | ||||
| } | ||||
							
								
								
									
										30
									
								
								generators/disk-id/default.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								generators/disk-id/default.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | |||
| { | ||||
|   config, | ||||
|   lib, | ||||
|   pkgs, | ||||
|   ... | ||||
| }: | ||||
| let | ||||
|   cfg = config.vars.disk-id; | ||||
| in | ||||
| { | ||||
|   options.vars.disk-id.enable = lib.mkEnableOption "Generates a uuid for use in disk device naming"; | ||||
|   config = lib.mkIf cfg.enable { | ||||
|     vars.generators.disk-id = { | ||||
|       files.diskId.secret = false; | ||||
|       runtimeInputs = [ | ||||
|         pkgs.coreutils | ||||
|         pkgs.bash | ||||
|       ]; | ||||
|       script = '' | ||||
|         uuid=$(bash ${./uuid4.sh}) | ||||
| 
 | ||||
|         # Remove the hyphens from the UUID | ||||
|         uuid_no_hyphens=$(echo -n "$uuid" | tr -d '-') | ||||
| 
 | ||||
|         echo -n "$uuid_no_hyphens" > "$out/diskId" | ||||
|       ''; | ||||
|     }; | ||||
|     disko.devices.disk."main".name = "main-" + config.vars.generators.disk-id.files.diskId.value; | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										20
									
								
								generators/disk-id/uuid4.sh
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								generators/disk-id/uuid4.sh
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,20 @@ | |||
| #!/usr/bin/env bash | ||||
| 
 | ||||
| # Read 16 bytes from /dev/urandom | ||||
| uuid=$(dd if=/dev/urandom bs=1 count=16 2>/dev/null | od -An -tx1 | tr -d ' \n') | ||||
| 
 | ||||
| # Break the UUID into pieces and apply the required modifications | ||||
| byte6=${uuid:12:2} | ||||
| byte8=${uuid:16:2} | ||||
| 
 | ||||
| # Construct the correct version and variant | ||||
| hex_byte6=$(printf "%x" $((0x$byte6 & 0x0F | 0x40))) | ||||
| hex_byte8=$(printf "%x" $((0x$byte8 & 0x3F | 0x80))) | ||||
| 
 | ||||
| # Rebuild the UUID with the correct fields | ||||
| uuid_v4="${uuid:0:12}${hex_byte6}${uuid:14:2}${hex_byte8}${uuid:18:14}" | ||||
| 
 | ||||
| # Format the UUID correctly 8-4-4-4-12 | ||||
| uuid_formatted="${uuid_v4:0:8}-${uuid_v4:8:4}-${uuid_v4:12:4}-${uuid_v4:16:4}-${uuid_v4:20:12}" | ||||
| 
 | ||||
| echo -n "$uuid_formatted" | ||||
							
								
								
									
										59
									
								
								generators/garage/default.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								generators/garage/default.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,59 @@ | |||
| { | ||||
|   config, | ||||
|   lib, | ||||
|   pkgs, | ||||
|   ... | ||||
| }: | ||||
| let | ||||
|   cfg = config.vars.garage; | ||||
| in | ||||
| { | ||||
|   options.vars.garage.enable = lib.mkEnableOption '' | ||||
|     S3-compatible object store for small self-hosted geo-distributed deployments. | ||||
| 
 | ||||
|     This module generates garage-specific keys automatically. | ||||
| 
 | ||||
|     Options: [NixosModuleOptions](https://search.nixos.org/options?channel=unstable&size=50&sort=relevance&type=packages&query=garage) | ||||
|     Documentation: https://garagehq.deuxfleurs.fr/ | ||||
|   ''; | ||||
|   config = lib.mkIf cfg.enable { | ||||
|     systemd.services.garage.serviceConfig = { | ||||
|       LoadCredential = [ | ||||
|         "rpc_secret_path:${config.vars.generators.garage-shared.files.rpc_secret.path}" | ||||
|         "admin_token_path:${config.vars.generators.garage.files.admin_token.path}" | ||||
|         "metrics_token_path:${config.vars.generators.garage.files.metrics_token.path}" | ||||
|       ]; | ||||
|       Environment = [ | ||||
|         "GARAGE_ALLOW_WORLD_READABLE_SECRETS=true" | ||||
|         "GARAGE_RPC_SECRET_FILE=%d/rpc_secret_path" | ||||
|         "GARAGE_ADMIN_TOKEN_FILE=%d/admin_token_path" | ||||
|         "GARAGE_METRICS_TOKEN_FILE=%d/metrics_token_path" | ||||
|       ]; | ||||
|     }; | ||||
| 
 | ||||
|     vars.generators.garage = { | ||||
|       files.admin_token = { }; | ||||
|       files.metrics_token = { }; | ||||
|       runtimeInputs = [ | ||||
|         pkgs.coreutils | ||||
|         pkgs.openssl | ||||
|       ]; | ||||
|       script = '' | ||||
|         openssl rand -base64 -out "$out"/admin_token 32 | ||||
|         openssl rand -base64 -out "$out"/metrics_token 32 | ||||
|       ''; | ||||
|     }; | ||||
| 
 | ||||
|     vars.generators.garage-shared = { | ||||
|       share = true; | ||||
|       files.rpc_secret = { }; | ||||
|       runtimeInputs = [ | ||||
|         pkgs.coreutils | ||||
|         pkgs.openssl | ||||
|       ]; | ||||
|       script = '' | ||||
|         openssl rand -hex -out "$out"/rpc_secret 32 | ||||
|       ''; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										46
									
								
								generators/machine-id/default.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								generators/machine-id/default.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,46 @@ | |||
| { | ||||
|   config, | ||||
|   lib, | ||||
|   pkgs, | ||||
|   ... | ||||
| }: | ||||
| let | ||||
|   var = config.vars.generators.machine-id.files.machineId or { }; | ||||
|   cfg = config.vars.machine-id; | ||||
| in | ||||
| { | ||||
|   options.vars.machine-id.enable = lib.mkEnableOption "Sets the /etc/machine-id and exposes it as a nix option"; | ||||
|   config = lib.mkIf cfg.enable (lib.mkMerge [ | ||||
|     (lib.mkIf ((var.value or null) != null) { | ||||
|       assertions = [ | ||||
|         { | ||||
|           assertion = lib.stringLength var.value == 32; | ||||
|           message = "machineId must be exactly 32 characters long."; | ||||
|         } | ||||
|       ]; | ||||
|       boot.kernelParams = [ | ||||
|         ''systemd.machine_id=${var.value}'' | ||||
|       ]; | ||||
|       environment.etc."machine-id" = { | ||||
|         text = var.value; | ||||
|       }; | ||||
|     }) | ||||
|     { | ||||
|       vars.generators.machine-id = { | ||||
|         files.machineId.secret = false; | ||||
|         runtimeInputs = [ | ||||
|           pkgs.coreutils | ||||
|           pkgs.bash | ||||
|         ]; | ||||
|         script = '' | ||||
|           uuid=$(bash ${./uuid4.sh}) | ||||
| 
 | ||||
|           # Remove the hyphens from the UUID | ||||
|           uuid_no_hyphens=$(echo -n "$uuid" | tr -d '-') | ||||
| 
 | ||||
|           echo -n "$uuid_no_hyphens" > "$out/machineId" | ||||
|         ''; | ||||
|       }; | ||||
|     } | ||||
|   ]); | ||||
| } | ||||
							
								
								
									
										20
									
								
								generators/machine-id/uuid4.sh
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								generators/machine-id/uuid4.sh
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,20 @@ | |||
| #!/usr/bin/env bash | ||||
| 
 | ||||
| # Read 16 bytes from /dev/urandom | ||||
| uuid=$(dd if=/dev/urandom bs=1 count=16 2>/dev/null | od -An -tx1 | tr -d ' \n') | ||||
| 
 | ||||
| # Break the UUID into pieces and apply the required modifications | ||||
| byte6=${uuid:12:2} | ||||
| byte8=${uuid:16:2} | ||||
| 
 | ||||
| # Construct the correct version and variant | ||||
| hex_byte6=$(printf "%x" $((0x$byte6 & 0x0F | 0x40))) | ||||
| hex_byte8=$(printf "%x" $((0x$byte8 & 0x3F | 0x80))) | ||||
| 
 | ||||
| # Rebuild the UUID with the correct fields | ||||
| uuid_v4="${uuid:0:12}${hex_byte6}${uuid:14:2}${hex_byte8}${uuid:18:14}" | ||||
| 
 | ||||
| # Format the UUID correctly 8-4-4-4-12 | ||||
| uuid_formatted="${uuid_v4:0:8}-${uuid_v4:8:4}-${uuid_v4:12:4}-${uuid_v4:16:4}-${uuid_v4:20:12}" | ||||
| 
 | ||||
| echo -n "$uuid_formatted" | ||||
							
								
								
									
										9
									
								
								generators/options.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								generators/options.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | |||
| { | ||||
|   lib, | ||||
|   ... | ||||
| }: | ||||
| { | ||||
|   options.vars = { | ||||
|     unattended = lib.mkEnableOption "Whether to default to generating values unattended, rather than prompting for desired values."; | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										60
									
								
								generators/root-password/default.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								generators/root-password/default.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,60 @@ | |||
| { | ||||
|   config, | ||||
|   lib, | ||||
|   pkgs, | ||||
|   ... | ||||
| }: | ||||
| let | ||||
|   cfg = config.vars.root-password; | ||||
| in | ||||
| { | ||||
|   imports = [ | ||||
|     ../options.nix | ||||
|   ]; | ||||
|   options.vars.root-password = { | ||||
|     enable = lib.mkEnableOption "Automatically generates and configures a password for the root user."; | ||||
|     prompt = lib.mkOption { | ||||
|       type = lib.types.bool; | ||||
|       default = !config.vars.unattended; | ||||
|       example = true; | ||||
|       description = "Whether the user should be prompted."; | ||||
|     }; | ||||
|   }; | ||||
|   config = lib.mkIf cfg.enable { | ||||
|     users.mutableUsers = false; | ||||
|     users.users.root.hashedPasswordFile = | ||||
|       config.vars.generators.root-password.files.password-hash.path; | ||||
| 
 | ||||
|     vars.generators.root-password = { | ||||
|       files.password-hash = { | ||||
|         neededFor = "users"; | ||||
|       }; | ||||
|       files.password-hash.restartUnits = lib.optional (config.services.userborn.enable) "userborn.service"; | ||||
|       files.password = { | ||||
|         deploy = false; | ||||
|       }; | ||||
|       runtimeInputs = [ | ||||
|         pkgs.coreutils | ||||
|         pkgs.mkpasswd | ||||
|         pkgs.xkcdpass | ||||
|       ]; | ||||
|       prompts = lib.mkIf cfg.prompt { | ||||
|         password = { | ||||
|           type = "hidden"; | ||||
|           persist = true; | ||||
|           description = "You can autogenerate a password, if you leave this prompt blank."; | ||||
|         }; | ||||
|       }; | ||||
| 
 | ||||
|       script = '' | ||||
|         prompt_value=${if cfg.prompt then ''$(cat "$prompts"/password)'' else ""} | ||||
|         if [[ -n "''${prompt_value-}" ]]; then | ||||
|           echo "$prompt_value" | tr -d "\n" > "$out"/password | ||||
|         else | ||||
|           xkcdpass --numwords 3 --delimiter - --count 1 | tr -d "\n" > "$out"/password | ||||
|         fi | ||||
|         mkpasswd -s -m sha-512 < "$out"/password | tr -d "\n" > "$out"/password-hash | ||||
|       ''; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										6
									
								
								generators/sshd/client.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								generators/sshd/client.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,6 @@ | |||
| { ... }: | ||||
| { | ||||
|   imports = [ | ||||
|     ./shared.nix | ||||
|   ]; | ||||
| } | ||||
							
								
								
									
										6
									
								
								generators/sshd/default.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								generators/sshd/default.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,6 @@ | |||
| { | ||||
|   imports = [ | ||||
|     ./client.nix | ||||
|     ./server.nix | ||||
|   ]; | ||||
| } | ||||
							
								
								
									
										103
									
								
								generators/sshd/server.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								generators/sshd/server.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,103 @@ | |||
| { | ||||
|   config, | ||||
|   pkgs, | ||||
|   lib, | ||||
|   ... | ||||
| }: | ||||
| let | ||||
|   stringSet = list: builtins.attrNames (builtins.groupBy lib.id list); | ||||
| 
 | ||||
|   domains = stringSet config.vars.sshd.certificate.searchDomains; | ||||
| 
 | ||||
|   cfg = config.vars.sshd; | ||||
| 
 | ||||
|   name = config.networking.hostName; | ||||
| in | ||||
| { | ||||
|   imports = [ ../shared.nix ]; | ||||
|   options = { | ||||
|     vars.sshd = { | ||||
|       enable = lib.mkEnableOption "Set up the opensshd service, generating a host key for the machine."; | ||||
|       hostKeys.rsa.enable = lib.mkEnableOption "Generate RSA host key"; | ||||
|     }; | ||||
|   }; | ||||
|   config = lib.mkIf cfg.enable { | ||||
|     services.openssh = { | ||||
|       enable = true; | ||||
|       settings.PasswordAuthentication = false; | ||||
| 
 | ||||
|       settings.HostCertificate = lib.mkIf ( | ||||
|         cfg.certificate.searchDomains != [ ] | ||||
|       ) config.vars.generators.openssh-cert.files."ssh.id_ed25519-cert.pub".path; | ||||
| 
 | ||||
|       hostKeys = | ||||
|         [ | ||||
|           { | ||||
|             path = config.vars.generators.openssh.files."ssh.id_ed25519".path; | ||||
|             type = "ed25519"; | ||||
|           } | ||||
|         ] | ||||
|         ++ lib.optional cfg.hostKeys.rsa.enable { | ||||
|           path = config.vars.generators.openssh-rsa.files."ssh.id_rsa".path; | ||||
|           type = "rsa"; | ||||
|         }; | ||||
|     }; | ||||
| 
 | ||||
|     vars.generators.openssh = { | ||||
|       files."ssh.id_ed25519" = { }; | ||||
|       files."ssh.id_ed25519.pub".secret = false; | ||||
|       runtimeInputs = [ | ||||
|         pkgs.coreutils | ||||
|         pkgs.openssh | ||||
|       ]; | ||||
|       script = '' | ||||
|         ssh-keygen -t ed25519 -N "" -f "$out"/ssh.id_ed25519 | ||||
|       ''; | ||||
|     }; | ||||
| 
 | ||||
|     programs.ssh.knownHosts.sshd-self-ed25519 = { | ||||
|       hostNames = [ | ||||
|         "localhost" | ||||
|         config.networking.hostName | ||||
|       ] ++ (lib.optional (config.networking.domain != null) config.networking.fqdn); | ||||
|       publicKey = config.vars.generators.openssh.files."ssh.id_ed25519.pub".value; | ||||
|     }; | ||||
| 
 | ||||
|     vars.generators.openssh-rsa = lib.mkIf config.vars.sshd.hostKeys.rsa.enable { | ||||
|       files."ssh.id_rsa" = { }; | ||||
|       files."ssh.id_rsa.pub".secret = false; | ||||
|       runtimeInputs = [ | ||||
|         pkgs.coreutils | ||||
|         pkgs.openssh | ||||
|       ]; | ||||
|       script = '' | ||||
|         ssh-keygen -t rsa -b 4096 -N "" -f "$out"/ssh.id_rsa | ||||
|       ''; | ||||
|     }; | ||||
| 
 | ||||
|     vars.generators.openssh-cert = lib.mkIf (cfg.certificate.searchDomains != [ ]) { | ||||
|       files."ssh.id_ed25519-cert.pub".secret = false; | ||||
|       dependencies = [ | ||||
|         "openssh" | ||||
|         "openssh-ca" | ||||
|       ]; | ||||
|       validation = { | ||||
|         inherit name; | ||||
|         domains = lib.genAttrs config.vars.sshd.certificate.searchDomains lib.id; | ||||
|       }; | ||||
|       runtimeInputs = [ | ||||
|         pkgs.openssh | ||||
|         pkgs.jq | ||||
|       ]; | ||||
|       script = '' | ||||
|         ssh-keygen \ | ||||
|           -s $in/openssh-ca/id_ed25519 \ | ||||
|           -I ${name} \ | ||||
|           -h \ | ||||
|           -n ${lib.concatMapStringsSep "," (d: "${name}.${d}") domains} \ | ||||
|           $in/openssh/ssh.id_ed25519.pub | ||||
|         mv $in/openssh/ssh.id_ed25519-cert.pub "$out"/ssh.id_ed25519-cert.pub | ||||
|       ''; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										44
									
								
								generators/sshd/shared.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								generators/sshd/shared.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,44 @@ | |||
| { | ||||
|   config, | ||||
|   lib, | ||||
|   pkgs, | ||||
|   ... | ||||
| }: | ||||
| let | ||||
|   cfg = config.vars.sshd.certificate; | ||||
| in | ||||
| { | ||||
|   options.vars.sshd.certificate = { | ||||
|     enable = lib.mkEnableOption "Add machines to the known hosts, enabling secure remote access to them over ssh."; | ||||
|     searchDomains = lib.mkOption { | ||||
|       type = lib.types.listOf lib.types.str; | ||||
|       default = [ ]; | ||||
|       example = [ "mydomain.com" ]; | ||||
|       description = "List of domains to include in the certificate. This option will prepend the machine name in front of each domain before adding it to the certificate."; | ||||
|     }; | ||||
|   }; | ||||
|   config = lib.mkIf cfg.enable { | ||||
|     vars.generators.openssh-ca = | ||||
|       lib.mkIf (config.vars.sshd.certificate.searchDomains != [ ]) | ||||
|         { | ||||
|           share = true; | ||||
|           files.id_ed25519.deploy = false; | ||||
|           files."id_ed25519.pub" = { | ||||
|             deploy = false; | ||||
|             secret = false; | ||||
|           }; | ||||
|           runtimeInputs = [ | ||||
|             pkgs.openssh | ||||
|           ]; | ||||
|           script = '' | ||||
|             ssh-keygen -t ed25519 -N "" -f "$out"/id_ed25519 | ||||
|           ''; | ||||
|         }; | ||||
| 
 | ||||
|     programs.ssh.knownHosts.ssh-ca = lib.mkIf (config.vars.sshd.certificate.searchDomains != [ ]) { | ||||
|       certAuthority = true; | ||||
|       extraHostNames = builtins.map (domain: "*.${domain}") config.vars.sshd.certificate.searchDomains; | ||||
|       publicKey = config.vars.generators.openssh-ca.files."id_ed25519.pub".value; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										22
									
								
								generators/state-version/default.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								generators/state-version/default.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | |||
| { config, lib, ... }: | ||||
| let | ||||
|   var = config.vars.generators.state-version.files.version or { }; | ||||
|   cfg = config.vars.state-version; | ||||
| in | ||||
| { | ||||
|   options.vars.state-version.enable = lib.mkEnableOption "Automatically generate the state version of the nixos installation."; | ||||
|   config = lib.mkIf cfg.enable { | ||||
|     system.stateVersion = lib.mkDefault (lib.removeSuffix "\n" var.value); | ||||
| 
 | ||||
|     vars.generators.state-version = { | ||||
|       files.version = { | ||||
|         secret = false; | ||||
|         value = lib.mkDefault config.system.nixos.release; | ||||
|       }; | ||||
|       runtimeInputs = [ ]; | ||||
|       script = '' | ||||
|         echo -n ${config.system.stateVersion} > "$out"/version | ||||
|       ''; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										74
									
								
								generators/user-password/default.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								generators/user-password/default.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,74 @@ | |||
| { | ||||
|   pkgs, | ||||
|   config, | ||||
|   lib, | ||||
|   ... | ||||
| }: | ||||
| let | ||||
|   cfg = config.vars.user-password; | ||||
| in | ||||
| { | ||||
|   imports = [ | ||||
|     ../options.nix | ||||
|   ]; | ||||
|   options.vars.user-password = { | ||||
|     enable = lib.mkEnableOption '' | ||||
|       Automatically generates and configures a password for a user. | ||||
| 
 | ||||
|       This will set `mutableUsers` to `false`, meaning you can not manage user passwords through `passwd` anymore. | ||||
|     ''; | ||||
|     users = lib.mkOption { | ||||
|       type = lib.types.attrsOf (lib.submodule { | ||||
|         options = { | ||||
|           prompt = lib.mkOption { | ||||
|             type = lib.types.bool; | ||||
|             default = !config.vars.unattended; | ||||
|             example = true; | ||||
|             description = "Whether the user should be prompted."; | ||||
|           }; | ||||
|         }; | ||||
|       }); | ||||
|       description = "The users for which to generate passwords."; | ||||
|       example = "{ alice = { }; }"; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   config = lib.mkIf cfg.enable { | ||||
|     users.mutableUsers = false; | ||||
|     users.users = lib.mapAttrs (userName: _: { | ||||
|       hashedPasswordFile = config.vars.generators."user-password-${userName}".files.user-password-hash.path; | ||||
|       isNormalUser = lib.mkDefault true; | ||||
|     }) cfg.users; | ||||
| 
 | ||||
|     vars.generators = lib.mapAttrs (userName: user: { | ||||
|       "user-password-${userName}" = { | ||||
|         files.user-password-hash.neededFor = "users"; | ||||
|         files.user-password-hash.restartUnits = lib.optional (config.services.userborn.enable) "userborn.service"; | ||||
| 
 | ||||
|         prompts = lib.mkIf user.prompt { | ||||
|           "user-password-${userName}" = { | ||||
|             type = "hidden"; | ||||
|             persist = true; | ||||
|             description = "You can autogenerate a password, if you leave this prompt blank."; | ||||
|             files.user-password.deploy = false; | ||||
|           }; | ||||
|         }; | ||||
| 
 | ||||
|         runtimeInputs = [ | ||||
|           pkgs.coreutils | ||||
|           pkgs.xkcdpass | ||||
|           pkgs.mkpasswd | ||||
|         ]; | ||||
|         script = '' | ||||
|           prompt_value=${if user.prompt then ''$(cat "$prompts"/user-password)'' else ""} | ||||
|           if [[ -n "''${prompt_value-}" ]]; then | ||||
|             echo "$prompt_value" | tr -d "\n" > "$out"/user-password | ||||
|           else | ||||
|             xkcdpass --numwords 3 --delimiter - --count 1 | tr -d "\n" > "$out"/user-password | ||||
|           fi | ||||
|           mkpasswd -s -m sha-512 < "$out"/user-password | tr -d "\n" > "$out"/user-password-hash | ||||
|         ''; | ||||
|       }; | ||||
|     }) cfg.users; | ||||
|   }; | ||||
| } | ||||
		Loading…
	
	Add table
		
		Reference in a new issue