diff options
| -rw-r--r-- | custom/uucp-mediaserver.nix | 2 | ||||
| -rw-r--r-- | custom/uucp.nix | 114 | ||||
| -rw-r--r-- | hel.nix | 29 | ||||
| -rw-r--r-- | odin.nix | 24 | ||||
| -rw-r--r-- | ymir.nix | 23 |
5 files changed, 119 insertions, 73 deletions
diff --git a/custom/uucp-mediaserver.nix b/custom/uucp-mediaserver.nix index 23b43118..5ed3b5ed 100644 --- a/custom/uucp-mediaserver.nix +++ b/custom/uucp-mediaserver.nix | |||
| @@ -61,6 +61,6 @@ in { | |||
| 61 | environment.systemPackages = [ scripts ]; | 61 | environment.systemPackages = [ scripts ]; |
| 62 | 62 | ||
| 63 | services.uucp.commandPath = [ "${scripts}/bin" ]; | 63 | services.uucp.commandPath = [ "${scripts}/bin" ]; |
| 64 | services.uucp.commands = genAttrs cfg.remoteNodes (name: ["mediaspace.${name}"] ); | 64 | services.uucp.remoteNodes = genAttrs cfg.remoteNodes (name: { commands = ["mediaspace.${name}"]; } ); |
| 65 | }; | 65 | }; |
| 66 | } | 66 | } |
diff --git a/custom/uucp.nix b/custom/uucp.nix index f5b89bfe..61e42119 100644 --- a/custom/uucp.nix +++ b/custom/uucp.nix | |||
| @@ -3,23 +3,72 @@ | |||
| 3 | with lib; | 3 | with lib; |
| 4 | 4 | ||
| 5 | let | 5 | let |
| 6 | portSpec = name: '' | 6 | portSpec = name: node: concatStringsSep "\n" (mapAttrsToList (portName: port: '' |
| 7 | port ${name} | 7 | port ${name}.${portName} |
| 8 | type pipe | 8 | type pipe |
| 9 | protocol ${if builtins.hasAttr name cfg.protocols then cfg.protocols."${name}" else cfg.defaultProtocol} | 9 | protocol ${node.protocols} |
| 10 | reliable true | 10 | reliable true |
| 11 | command ${pkgs.openssh}/bin/ssh -x -o batchmode=yes ${name} | 11 | command ${pkgs.openssh}/bin/ssh -x -o batchmode=yes ${name}.${portName} |
| 12 | ''; | 12 | '') node.hostnames); |
| 13 | sysSpec = name: '' | 13 | sysSpec = name: '' |
| 14 | system ${name} | 14 | system ${name} |
| 15 | time Any | 15 | time Any |
| 16 | port ${name} | ||
| 17 | chat "" | 16 | chat "" |
| 18 | protocol ${if builtins.hasAttr name cfg.protocols then cfg.protocols."${name}" else cfg.defaultProtocol} | ||
| 19 | command-path ${concatStringsSep " " cfg.commandPath} | 17 | command-path ${concatStringsSep " " cfg.commandPath} |
| 20 | commands ${concatStringsSep " " (if builtins.hasAttr name cfg.commands then unique (cfg.defaultCommands ++ cfg.commands."${name}") else cfg.defaultCommands)} | 18 | commands ${concatStringsSep " " node.commands} |
| 19 | ${concatStringsSep "\nalternate\n" (mapAttrsToList (portName: port: '' | ||
| 20 | port ${name}.${portName} | ||
| 21 | '') node.hostnames)} | ||
| 22 | ''; | ||
| 23 | sshConfig = name: node: concatStringsSep "\n" (mapAttrsToList (portName: port: '' | ||
| 24 | Host ${name}.${portName} | ||
| 25 | Hostname ${port} | ||
| 26 | IdentitiesOnly Yes | ||
| 27 | IdentityFile ${cfg.sshKeyDir}/${name}.pub | ||
| 28 | '') node.hostnames); | ||
| 29 | sshKeyGen = name: node: '' | ||
| 30 | if [[ ! -e ${cfg.sshKeyDir}/${name} ]]; then | ||
| 31 | ssh-keygen ${escapeShellArgs node.generateKey} -f ${cfg.sshKeyDir}/${name} | ||
| 32 | fi | ||
| 33 | ''; | ||
| 34 | restrictKey = key: '' | ||
| 35 | restrict,command="${config.security.wrapperDir}/uucico" ${key} | ||
| 21 | ''; | 36 | ''; |
| 22 | 37 | ||
| 38 | nodeCfg = { | ||
| 39 | options = { | ||
| 40 | commands = mkOption { | ||
| 41 | type = types.listOf types.string; | ||
| 42 | default = cfg.defaultCommands; | ||
| 43 | description = "Commands to allow for this remote"; | ||
| 44 | }; | ||
| 45 | |||
| 46 | protocols = mkOption { | ||
| 47 | type = types.string; | ||
| 48 | default = cfg.defaultProtocols; | ||
| 49 | description = "UUCP protocols to use for this remote"; | ||
| 50 | }; | ||
| 51 | |||
| 52 | publicKeys = mkOption { | ||
| 53 | type = types.listOf types.string; | ||
| 54 | default = []; | ||
| 55 | description = "SSH public keys for this node"; | ||
| 56 | }; | ||
| 57 | |||
| 58 | generateKey = mkOption { | ||
| 59 | type = types.listOf types.string; | ||
| 60 | default = [ "-t ed25519" ]; | ||
| 61 | description = "Arguments to pass to `ssh-keygen` to generate a keypair for communication with this host"; | ||
| 62 | }; | ||
| 63 | |||
| 64 | hostnames = mkOption { | ||
| 65 | type = types.attrsOf types.string; | ||
| 66 | default = {}; | ||
| 67 | description = ""; | ||
| 68 | }; | ||
| 69 | }; | ||
| 70 | }; | ||
| 71 | |||
| 23 | cfg = config.services.uucp; | 72 | cfg = config.services.uucp; |
| 24 | in { | 73 | in { |
| 25 | options = { | 74 | options = { |
| @@ -44,14 +93,14 @@ in { | |||
| 44 | description = "Overrides for the local uucp linux-user"; | 93 | description = "Overrides for the local uucp linux-user"; |
| 45 | }; | 94 | }; |
| 46 | 95 | ||
| 47 | sshConfig = mkOption { | 96 | extraSSHConfig = mkOption { |
| 48 | type = types.str; | 97 | type = types.str; |
| 49 | default = ""; | 98 | default = ""; |
| 50 | description = "~uucp/.ssh/config"; | 99 | description = "Extra SSH config"; |
| 51 | }; | 100 | }; |
| 52 | 101 | ||
| 53 | remoteNodes = mkOption { | 102 | remoteNodes = mkOption { |
| 54 | type = types.listOf types.str; | 103 | type = types.attrsOf (types.submodule nodeCfg); |
| 55 | default = {}; | 104 | default = {}; |
| 56 | description = '' | 105 | description = '' |
| 57 | Ports to set up | 106 | Ports to set up |
| @@ -73,22 +122,22 @@ in { | |||
| 73 | description = "Commands allowed for remotes without explicit override"; | 122 | description = "Commands allowed for remotes without explicit override"; |
| 74 | }; | 123 | }; |
| 75 | 124 | ||
| 76 | commands = mkOption { | 125 | defaultProtocols = mkOption { |
| 77 | type = types.attrsOf (types.listOf types.string); | ||
| 78 | default = {}; | ||
| 79 | description = "Override commands for specific remotes"; | ||
| 80 | }; | ||
| 81 | |||
| 82 | defaultProtocol = mkOption { | ||
| 83 | type = types.string; | 126 | type = types.string; |
| 84 | default = "e"; | 127 | default = "e"; |
| 85 | description = "UUCP protocol to use within ssh unless overriden"; | 128 | description = "UUCP protocol to use within ssh unless overriden"; |
| 86 | }; | 129 | }; |
| 87 | 130 | ||
| 88 | protocols = mkOption { | 131 | homeDir = mkOption { |
| 89 | type = types.attrsOf types.string; | 132 | type = types.path; |
| 90 | default = {}; | 133 | default = "/var/uucp"; |
| 91 | description = "UUCP protocols to use for specific remotes"; | 134 | description = "Home of the uucp user"; |
| 135 | }; | ||
| 136 | |||
| 137 | sshKeyDir = mkOption { | ||
| 138 | type = types.path; | ||
| 139 | default = "${cfg.homeDir}/.ssh/"; | ||
| 140 | description = "Directory to store ssh keypairs"; | ||
| 92 | }; | 141 | }; |
| 93 | 142 | ||
| 94 | spoolDir = mkOption { | 143 | spoolDir = mkOption { |
| @@ -184,16 +233,27 @@ in { | |||
| 184 | isSystemUser = true; | 233 | isSystemUser = true; |
| 185 | isNormalUser = false; | 234 | isNormalUser = false; |
| 186 | createHome = true; | 235 | createHome = true; |
| 187 | home = cfg.spoolDir; | 236 | home = cfg.homeDir; |
| 188 | description = "User for uucp over ssh"; | 237 | description = "User for uucp over ssh"; |
| 189 | useDefaultShell = true; | 238 | useDefaultShell = true; |
| 239 | openssh.authorizedKeys.keys = map restrictKey (concat (mapAttrsToList (name: node: node.publicKeys) cfg.remoteNodes)); | ||
| 190 | } // cfg.sshUser; | 240 | } // cfg.sshUser; |
| 191 | 241 | ||
| 192 | system.activationScripts."uucp-sshconfig" = '' | 242 | system.activationScripts."uucp-sshconfig" = '' |
| 193 | mkdir -p ${config.users.users."uucp".home}/.ssh | 243 | mkdir -p ${config.users.users."uucp".home}/.ssh |
| 194 | chown ${config.users.users."uucp".name}:${config.users.users."uucp".group} ${config.users.users."uucp".home}/.ssh | 244 | chown ${config.users.users."uucp".name}:${config.users.users."uucp".group} ${config.users.users."uucp".home}/.ssh |
| 195 | chmod 700 ${config.users.users."uucp".home}/.ssh | 245 | chmod 700 ${config.users.users."uucp".home}/.ssh |
| 196 | ln -fs ${builtins.toFile "ssh-config" cfg.sshConfig} ${config.users.users."uucp".home}/.ssh/config | 246 | ln -fs ${builtins.toFile "ssh-config" '' |
| 247 | ${concatStringsSpec "\n" (mapAttrsToList sshConfig cfg.remoteNodes)} | ||
| 248 | |||
| 249 | ${cfg.extraSSHConfig} | ||
| 250 | ''} ${config.users.users."uucp".home}/.ssh/config | ||
| 251 | |||
| 252 | mkdir -p ${cfg.sshKeyDir} | ||
| 253 | chown ${config.users.users."uucp".name}:${config.users.users."uucp".group} ${cfg.sshKeyDir} | ||
| 254 | chmod 700 ${config.sshKeyDir} | ||
| 255 | |||
| 256 | ${concatStringsSep "\n" (mapAttrsToList sshKeyGen cfg.remoteNodes)} | ||
| 197 | ''; | 257 | ''; |
| 198 | 258 | ||
| 199 | system.activationScripts."uucp-logs" = '' | 259 | system.activationScripts."uucp-logs" = '' |
| @@ -213,10 +273,10 @@ in { | |||
| 213 | port ssh | 273 | port ssh |
| 214 | type stdin | 274 | type stdin |
| 215 | protocol e | 275 | protocol e |
| 216 | '' + concatStringsSep "\n" (map portSpec cfg.remoteNodes); | 276 | '' + concatStringsSep "\n" (mapAttrsToList portSpec cfg.remoteNodes); |
| 217 | }; | 277 | }; |
| 218 | environment.etc."uucp/sys" = { | 278 | environment.etc."uucp/sys" = { |
| 219 | text = cfg.extraSys + "\n" + concatStringsSep "\n" (map sysSpec cfg.remoteNodes); | 279 | text = cfg.extraSys + "\n" + concatStringsSep "\n" (mapAttrsToList sysSpec cfg.remoteNodes); |
| 220 | }; | 280 | }; |
| 221 | 281 | ||
| 222 | security.wrappers = let | 282 | security.wrappers = let |
| @@ -301,7 +361,7 @@ in { | |||
| 301 | 361 | ||
| 302 | case "''${2}" in | 362 | case "''${2}" in |
| 303 | (?(vpn-)up) | 363 | (?(vpn-)up) |
| 304 | ${concatMapStringsSep "\n " (name: "${pkgs.systemd}/bin/systemctl start uucico@${name}.service") cfg.remoteNodes} | 364 | ${concatStringsSep "\n " (mapAttrsToList (name: node: "${pkgs.systemd}/bin/systemctl start uucico@${name}.service") cfg.remoteNodes)} |
| 305 | ;; | 365 | ;; |
| 306 | esac | 366 | esac |
| 307 | ''; | 367 | ''; |
| @@ -202,25 +202,20 @@ | |||
| 202 | uucp = { | 202 | uucp = { |
| 203 | enable = true; | 203 | enable = true; |
| 204 | nodeName = "hel"; | 204 | nodeName = "hel"; |
| 205 | remoteNodes = ["odin" "ymir"]; | 205 | remoteNodes = { |
| 206 | sshUser = { | 206 | "odin" = { |
| 207 | openssh.authorizedKeys.keys = [ ''restrict,command="${config.security.wrapperDir}/uucico" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFH1QWdgoC03nzW5GBuCl2pqASHeIXIYtE9IInHdaKcO uucp@ymir'' | 207 | publicKeys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKcDj49TqmflGTmtGBqDawxmCBWW1txj61CZ7KT0hTHK uucp@odin"]; |
| 208 | ''restrict,command="${config.security.wrapperDir}/uucico" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKcDj49TqmflGTmtGBqDawxmCBWW1txj61CZ7KT0hTHK uucp@odin'' | 208 | hostnames = ["odin.asgard.yggdrasil"]; |
| 209 | ]; | 209 | commands = lib.mkForce ["recv-media" "notify-gkleen"]; |
| 210 | }; | ||
| 211 | "ymir" = { | ||
| 212 | publicKeys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFH1QWdgoC03nzW5GBuCl2pqASHeIXIYtE9IInHdaKcO uucp@ymir"]; | ||
| 213 | hostnames = ["ymir.yggdrasil.li" "ymir.niflheim.yggdrasil"]; | ||
| 214 | }; | ||
| 210 | }; | 215 | }; |
| 211 | sshConfig = '' | 216 | |
| 212 | Host odin | ||
| 213 | Hostname odin.asgard.yggdrasil | ||
| 214 | IdentityFile ~/.ssh/odin | ||
| 215 | Host ymir | ||
| 216 | Hostname ymir.niflheim.yggdrasil | ||
| 217 | IdentityFile ~/.ssh/ymir | ||
| 218 | ''; | ||
| 219 | commandPath = [ "${pkgs.callPackage ./hel/recv-media.nix {}}/bin" config.security.wrapperDir ]; | 217 | commandPath = [ "${pkgs.callPackage ./hel/recv-media.nix {}}/bin" config.security.wrapperDir ]; |
| 220 | defaultCommands = []; | 218 | defaultCommands = lib.mkForce []; |
| 221 | commands = { | ||
| 222 | "odin" = ["recv-media" "notify-gkleen"]; | ||
| 223 | }; | ||
| 224 | }; | 219 | }; |
| 225 | 220 | ||
| 226 | postfix = { | 221 | postfix = { |
| @@ -78,22 +78,16 @@ | |||
| 78 | services.uucp = { | 78 | services.uucp = { |
| 79 | enable = true; | 79 | enable = true; |
| 80 | nodeName = "odin"; | 80 | nodeName = "odin"; |
| 81 | remoteNodes = [ "ymir" "hel" ]; | 81 | remoteNodes = { |
| 82 | sshUser = { | 82 | "ymir" = { |
| 83 | openssh.authorizedKeys.keys = [ ''restrict,command="${config.security.wrapperDir}/uucico" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKD8ycFGfVkBL9wjA5Kc33cl6Qt5K2505G/38oH8Cy/e uucp@hel'' | 83 | publicKeys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGANj+LJ4CI6VrAgBRocKCGq74kZnwD1PdKr/gdlfVr1 uucp@ymir"]; |
| 84 | ''restrict,command="${config.security.wrapperDir}/uucico" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGANj+LJ4CI6VrAgBRocKCGq74kZnwD1PdKr/gdlfVr1 uucp@ymir'' | 84 | hostnames = ["ymir.yggdrasil.li" "ymir.niflheim.yggdrasil"]; |
| 85 | ]; | 85 | }; |
| 86 | "hel" = { | ||
| 87 | publicKeys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKD8ycFGfVkBL9wjA5Kc33cl6Qt5K2505G/38oH8Cy/e uucp@hel"]; | ||
| 88 | hostnames = ["hel.asgard.yggdrasil" "hel.midgard.yggdrasil"]; | ||
| 89 | }; | ||
| 86 | }; | 90 | }; |
| 87 | sshConfig = '' | ||
| 88 | Host ymir | ||
| 89 | Hostname ymir.niflheim.yggdrasil | ||
| 90 | IdentityFile ~/.ssh/ymir | ||
| 91 | Host hel | ||
| 92 | Hostname hel.midgard.yggdrasil | ||
| 93 | IdentityFile ~/.ssh/hel | ||
| 94 | ''; | ||
| 95 | commandPath = ["${pkgs.rmail}/bin"]; | ||
| 96 | defaultCommands = ["rmail"]; | ||
| 97 | 91 | ||
| 98 | media-server = { | 92 | media-server = { |
| 99 | enable = true; | 93 | enable = true; |
| @@ -852,20 +852,17 @@ in rec { | |||
| 852 | services.uucp = { | 852 | services.uucp = { |
| 853 | enable = true; | 853 | enable = true; |
| 854 | nodeName = "ymir"; | 854 | nodeName = "ymir"; |
| 855 | remoteNodes = [ "odin" "hel" ]; | 855 | remoteNodes = { |
| 856 | sshUser = { | 856 | "odin" = { |
| 857 | openssh.authorizedKeys.keys = [ ''restrict,command="${config.security.wrapperDir}/uucico" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKT/BsAMLJs9NYhKIso4J3EF+VzRBm3c+qCQ5ONKc/1s uucp@odin'' | 857 | publicKeys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKT/BsAMLJs9NYhKIso4J3EF+VzRBm3c+qCQ5ONKc/1s uucp@odin"]; |
| 858 | ''restrict,command="${config.security.wrapperDir}/uucico" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOWBybBQKbPucqBgULQ1phv7IKFWl1Xc4drkCx3D5mIz uucp@hel'' | 858 | hostnames = ["odin.asgard.yggdrasil"]; |
| 859 | ]; | 859 | }; |
| 860 | "hel" = { | ||
| 861 | publicKeys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOWBybBQKbPucqBgULQ1phv7IKFWl1Xc4drkCx3D5mIz uucp@hel"]; | ||
| 862 | hostnames = ["hel.midgard.yggdrasil"]; | ||
| 863 | }; | ||
| 860 | }; | 864 | }; |
| 861 | sshConfig = '' | 865 | |
| 862 | Host odin | ||
| 863 | Hostname odin.asgard.yggdrasil | ||
| 864 | IdentityFile ~/.ssh/odin | ||
| 865 | Host hel | ||
| 866 | Hostname hel.midgard.yggdrasil | ||
| 867 | IdentityFile ~/.ssh/hel | ||
| 868 | ''; | ||
| 869 | commandPath = ["${pkgs.rmail}/bin" "${pkgs.push2bin}/bin"]; | 866 | commandPath = ["${pkgs.rmail}/bin" "${pkgs.push2bin}/bin"]; |
| 870 | defaultCommands = ["rmail" "push2bin"]; | 867 | defaultCommands = ["rmail" "push2bin"]; |
| 871 | }; | 868 | }; |
