{
  liminix
, dropbear
, lib
, watch-ssh-keys
}:
{
  address,
  allowLocalPortForward,
  allowPasswordLogin,
  allowPasswordLoginForRoot,
  allowRemoteConnectionToForwardedPorts,
  allowRemotePortForward,
  allowRoot,
  authorizedKeys,
  port,
  extraConfig
}:
let
  name = "sshd";
  inherit (builtins) toString typeOf;
  inherit (liminix.services) longrun;
  inherit (lib) concatStringsSep mapAttrs mapAttrsToList;
  keydir = "/run/${name}/authorized_keys";
  options =
    [
      "-e" #  pass environment to child
      "-E" #  log to stderr
      "-R" #  create hostkeys if needed
      "-P /run/dropbear.pid"
      "-F" #  don't fork into background
    ] ++
    (lib.optional (! allowRoot) "-w") ++
    (lib.optional (! allowPasswordLogin) "-s") ++
    (lib.optional (! allowPasswordLoginForRoot) "-g") ++
    (lib.optional (! allowLocalPortForward) "-j") ++
    (lib.optional (! allowRemotePortForward) "-k") ++
    (lib.optional (! allowRemoteConnectionToForwardedPorts) "-a") ++
    (lib.optionals (authorizedKeys != null) ["-U" "${keydir}/%n"]) ++
    [(if address != null
      then "-p ${address}:${toString port}"
      else "-p ${toString port}")] ++
    [extraConfig];
  isKeyservice = typeOf authorizedKeys == "lambda";
  authKeysConcat =
    if authorizedKeys != null && !isKeyservice
    then mapAttrs
      (n : v : concatStringsSep "\\n" v)
      authorizedKeys
    else {};
  keyservice = longrun {
    name = "${name}-watch-keys";
    run = ''
      mkdir -p ${keydir}
      exec ${watch-ssh-keys}/bin/watch-ssh-keys -d ${keydir} ${authorizedKeys "service"} ${authorizedKeys "path"}
    '';
    dependencies = [ (authorizedKeys "service") ] ;
  };
in
longrun {
  inherit name;
  # we need /run/dropbear to point to hostkey storage, as that
  # pathname is hardcoded into the binary.
  # env -i clears the environment so we don't pass anything weird to
  # ssh sessions
  run = ''
    ln -s $(mkstate dropbear) /run
    mkdir -p /run/${name}/authorized_keys
    ${concatStringsSep "\n"
      (mapAttrsToList
        (n : v : "echo -e '${v}' > /run/${name}/authorized_keys/${n} ")
        authKeysConcat
      )
     }
    . /etc/profile # sets PATH but do we need this?  it's the same file as ashrc
    exec env -i ENV=/etc/ashrc PATH=$PATH ${dropbear}/bin/dropbear ${concatStringsSep " " options}
  '';
  dependencies = lib.optional isKeyservice keyservice;
}