ALPHA: wire is a tool to deploy nixos systems wire.althaea.zone/
at trunk 6.8 kB view raw
1# SPDX-License-Identifier: AGPL-3.0-or-later 2# Copyright 2024-2025 wire Contributors 3 4{ 5 lib, 6 name, 7 ... 8}: 9let 10 inherit (lib) types; 11in 12{ 13 imports = 14 let 15 inherit (lib) mkAliasOptionModule; 16 in 17 [ 18 (mkAliasOptionModule [ "deployment" "targetHost" ] [ "deployment" "target" "hosts" ]) 19 (mkAliasOptionModule [ "deployment" "targetUser" ] [ "deployment" "target" "user" ]) 20 (mkAliasOptionModule [ "deployment" "targetPort" ] [ "deployment" "target" "port" ]) 21 ]; 22 23 options.deployment = { 24 target = lib.mkOption { 25 type = types.submodule { 26 imports = [ 27 (lib.mkAliasOptionModule [ "host" ] [ "hosts" ]) 28 ]; 29 options = { 30 hosts = lib.mkOption { 31 type = types.coercedTo types.str lib.singleton (types.listOf types.str); 32 description = "IPs or hostnames to attempt to connect to. They are tried in order."; 33 default = lib.singleton name; 34 apply = lib.unique; 35 }; 36 user = lib.mkOption { 37 type = types.str; 38 description = "User to use for SSH. The user must be atleast `wheel` and must use an SSH key or similar 39 non-interactive login method. More information can be found at https://wire.althaea.zone/guides/non-root-user"; 40 default = "root"; 41 }; 42 port = lib.mkOption { 43 type = types.int; 44 default = 22; 45 description = "SSH port to use."; 46 }; 47 }; 48 }; 49 description = "Describes the target for this node"; 50 default = { }; 51 }; 52 53 buildOnTarget = lib.mkOption { 54 type = types.bool; 55 default = false; 56 description = "Whether to build the system on the target host or not."; 57 }; 58 59 allowLocalDeployment = lib.mkOption { 60 type = types.bool; 61 default = true; 62 description = "Whether to allow or deny this node being applied to localhost when the host's hostname matches the 63 node's name."; 64 }; 65 66 tags = lib.mkOption { 67 type = types.listOf types.str; 68 default = [ ]; 69 description = "Tags for node."; 70 example = [ 71 "arm" 72 "cloud" 73 ]; 74 }; 75 76 privilegeEscalationCommand = lib.mkOption { 77 type = types.listOf types.str; 78 description = "Command to elevate."; 79 default = [ 80 "sudo" 81 "--" 82 ]; 83 }; 84 85 replaceUnknownProfiles = lib.mkOption { 86 type = types.bool; 87 description = "No-op, colmena compatibility"; 88 default = true; 89 }; 90 91 sshOptions = lib.mkOption { 92 type = types.listOf types.str; 93 description = "No-op, colmena compatibility"; 94 default = [ ]; 95 }; 96 97 _keys = lib.mkOption { 98 internal = true; 99 readOnly = true; 100 }; 101 102 _hostPlatform = lib.mkOption { 103 internal = true; 104 readOnly = true; 105 }; 106 107 keys = lib.mkOption { 108 type = types.attrsOf ( 109 types.submodule ( 110 { 111 name, 112 config, 113 ... 114 }: 115 { 116 imports = 117 let 118 inherit (lib) mkAliasOptionModule; 119 in 120 [ 121 (mkAliasOptionModule [ "keyFile" ] [ "source" ]) 122 (mkAliasOptionModule [ "keyCommand" ] [ "source" ]) 123 (mkAliasOptionModule [ "text" ] [ "source" ]) 124 ]; 125 options = { 126 name = lib.mkOption { 127 type = types.str; 128 default = name; 129 description = "Filename of the secret."; 130 }; 131 destDir = lib.mkOption { 132 type = types.path; 133 default = "/run/keys/"; 134 description = "Destination directory for the secret. Change this to something other than `/run/keys/` for keys to persist past reboots."; 135 }; 136 path = lib.mkOption { 137 internal = true; 138 type = types.path; 139 default = 140 if lib.hasSuffix "/" config.destDir then 141 "${config.destDir}${config.name}" 142 else 143 "${config.destDir}/${config.name}"; 144 description = "Path that the key is deployed to."; 145 }; 146 service = lib.mkOption { 147 internal = true; 148 type = types.str; 149 default = "${config.name}-key.service"; 150 description = "Name of the systemd service that represents this key."; 151 }; 152 group = lib.mkOption { 153 type = types.str; 154 default = "root"; 155 description = "Group to own the key. If this group does not exist this will silently fail and the key will be owned by gid 0."; 156 }; 157 user = lib.mkOption { 158 type = types.str; 159 default = "root"; 160 description = "User to own the key. If this user does not exist this will silently fail and the key will be owned by uid 0."; 161 }; 162 permissions = lib.mkOption { 163 type = types.str; 164 default = "0600"; 165 description = "Unix Octal permissions, in string format, for the key."; 166 }; 167 source = lib.mkOption { 168 type = types.oneOf [ 169 types.str 170 types.path 171 (types.listOf types.str) 172 ]; 173 description = "Source of the key. Either a path to a file, a literal string, or a command to generate the key."; 174 }; 175 uploadAt = lib.mkOption { 176 type = types.enum [ 177 "pre-activation" 178 "post-activation" 179 ]; 180 default = "pre-activation"; 181 description = "When to upload the key. Either `pre-activation` or `post-activation`."; 182 }; 183 environment = lib.mkOption { 184 type = types.attrsOf types.str; 185 default = { }; 186 description = "Key-Value environment variables to use when creating the key if the key source is a command."; 187 }; 188 }; 189 } 190 ) 191 ); 192 description = "Secrets to be deployed to the node."; 193 default = { }; 194 example = { 195 "wireless.env" = { 196 source = [ 197 "gpg" 198 "--decrypt" 199 "secrets/wireless.env.gpg" 200 ]; 201 destDir = "/etc/keys/"; 202 }; 203 204 "arbfile.txt" = { 205 source = ./arbfile.txt; 206 destDir = "/etc/arbs/"; 207 }; 208 209 "arberfile.txt" = { 210 source = '' 211 Hello World 212 ''; 213 destDir = "/etc/arbs/"; 214 }; 215 }; 216 }; 217 }; 218}