{
  liminix
, dropbear
, lib
}:
{
  address,
  allowLocalPortForward,
  allowPasswordLogin,
  allowPasswordLoginForRoot,
  allowRemoteConnectionToForwardedPorts,
  allowRemotePortForward,
  allowRoot,
  authorizedKeys,
  port,
  extraConfig
}:
let
  name = "sshd";
  inherit (builtins) toString;
  inherit (liminix.services) longrun;
  inherit (lib) concatStringsSep mapAttrs mapAttrsToList;
  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" "/run/${name}/authorized_keys/%n"]) ++
    [(if address != null
      then "-p ${address}:${toString port}"
      else "-p ${toString port}")] ++
    [extraConfig];
  authKeysConcat =
    if authorizedKeys != null
    then mapAttrs
      (n : v : concatStringsSep "\\n" v)
      authorizedKeys
    else {};
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}
  '';
}