ssh.nix (2366B)
1 { 2 liminix, 3 dropbear, 4 lib, 5 watch-ssh-keys, 6 }: 7 { 8 address, 9 allowLocalPortForward, 10 allowPasswordLogin, 11 allowPasswordLoginForRoot, 12 allowRemoteConnectionToForwardedPorts, 13 allowRemotePortForward, 14 allowRoot, 15 authorizedKeys, 16 port, 17 extraConfig, 18 }: 19 let 20 name = "sshd"; 21 inherit (builtins) toString typeOf; 22 inherit (liminix.services) longrun; 23 inherit (lib) concatStringsSep mapAttrs mapAttrsToList; 24 keydir = "/run/${name}/authorized_keys"; 25 options = 26 [ 27 "-e" # pass environment to child 28 "-E" # log to stderr 29 "-R" # create hostkeys if needed 30 "-P /run/dropbear.pid" 31 "-F" # don't fork into background 32 ] 33 ++ (lib.optional (!allowRoot) "-w") 34 ++ (lib.optional (!allowPasswordLogin) "-s") 35 ++ (lib.optional (!allowPasswordLoginForRoot) "-g") 36 ++ (lib.optional (!allowLocalPortForward) "-j") 37 ++ (lib.optional (!allowRemotePortForward) "-k") 38 ++ (lib.optional (!allowRemoteConnectionToForwardedPorts) "-a") 39 ++ (lib.optionals (authorizedKeys != null) [ 40 "-U" 41 "${keydir}/%n" 42 ]) 43 ++ [ 44 (if address != null then "-p ${address}:${toString port}" else "-p ${toString port}") 45 ] 46 ++ [ extraConfig ]; 47 isKeyservice = typeOf authorizedKeys == "lambda"; 48 authKeysConcat = 49 if authorizedKeys != null && !isKeyservice then 50 mapAttrs (n: v: concatStringsSep "\\n" v) authorizedKeys 51 else 52 { }; 53 keyservice = longrun { 54 name = "${name}-watch-keys"; 55 run = '' 56 mkdir -p ${keydir} 57 exec ${watch-ssh-keys}/bin/watch-ssh-keys -d ${keydir} ${authorizedKeys "service"} ${authorizedKeys "path"} 58 ''; 59 dependencies = [ (authorizedKeys "service") ]; 60 }; 61 in 62 longrun { 63 inherit name; 64 # we need /run/dropbear to point to hostkey storage, as that 65 # pathname is hardcoded into the binary. 66 # env -i clears the environment so we don't pass anything weird to 67 # ssh sessions 68 run = '' 69 ln -s $(mkstate dropbear) /run 70 mkdir -p /run/${name}/authorized_keys 71 ${concatStringsSep "\n" ( 72 mapAttrsToList (n: v: "echo -e '${v}' > /run/${name}/authorized_keys/${n} ") authKeysConcat 73 )} 74 . /etc/profile # sets PATH but do we need this? it's the same file as ashrc 75 exec env -i ENV=/etc/ashrc PATH=$PATH ${dropbear}/bin/dropbear ${concatStringsSep " " options} 76 ''; 77 dependencies = lib.optional isKeyservice keyservice; 78 }