summary refs log tree commit diff
path: root/nixos/modules/services/networking/tmate-ssh-server.nix
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules/services/networking/tmate-ssh-server.nix')
-rw-r--r--nixos/modules/services/networking/tmate-ssh-server.nix122
1 files changed, 122 insertions, 0 deletions
diff --git a/nixos/modules/services/networking/tmate-ssh-server.nix b/nixos/modules/services/networking/tmate-ssh-server.nix
new file mode 100644
index 00000000000..1b8f6662ef4
--- /dev/null
+++ b/nixos/modules/services/networking/tmate-ssh-server.nix
@@ -0,0 +1,122 @@
+{ config, lib, pkgs, ... }:
+with lib;
+let
+  cfg = config.services.tmate-ssh-server;
+
+  defaultKeysDir = "/etc/tmate-ssh-server-keys";
+  edKey = "${defaultKeysDir}/ssh_host_ed25519_key";
+  rsaKey = "${defaultKeysDir}/ssh_host_rsa_key";
+
+  keysDir =
+    if cfg.keysDir == null
+    then defaultKeysDir
+    else cfg.keysDir;
+
+  domain = config.networking.domain;
+in
+{
+  options.services.tmate-ssh-server = {
+    enable = mkEnableOption (mdDoc "tmate ssh server");
+
+    package = mkOption {
+      type = types.package;
+      description = mdDoc "The package containing tmate-ssh-server";
+      defaultText = literalExpression "pkgs.tmate-ssh-server";
+      default = pkgs.tmate-ssh-server;
+    };
+
+    host = mkOption {
+      type = types.str;
+      description = mdDoc "External host name";
+      defaultText = lib.literalExpression "config.networking.domain or config.networking.hostName ";
+      default =
+        if domain == null then
+          config.networking.hostName
+        else
+          domain;
+    };
+
+    port = mkOption {
+      type = types.port;
+      description = mdDoc "Listen port for the ssh server";
+      default = 2222;
+    };
+
+    openFirewall = mkOption {
+      type = types.bool;
+      default = true;
+      description = mdDoc "Whether to automatically open the specified ports in the firewall.";
+    };
+
+    advertisedPort = mkOption {
+      type = types.port;
+      description = mdDoc "External port advertised to clients";
+    };
+
+    keysDir = mkOption {
+      type = with types; nullOr str;
+      description = mdDoc "Directory containing ssh keys, defaulting to auto-generation";
+      default = null;
+    };
+  };
+
+  config = mkIf cfg.enable {
+
+    networking.firewall.allowedTCPPorts = optionals cfg.openFirewall [ cfg.port ];
+
+    services.tmate-ssh-server = {
+      advertisedPort = mkDefault cfg.port;
+    };
+
+    environment.systemPackages =
+      let
+        tmate-config = pkgs.writeText "tmate.conf"
+          ''
+            set -g tmate-server-host "${cfg.host}"
+            set -g tmate-server-port ${toString cfg.port}
+            set -g tmate-server-ed25519-fingerprint "@ed25519_fingerprint@"
+            set -g tmate-server-rsa-fingerprint "@rsa_fingerprint@"
+          '';
+      in
+      [
+        (pkgs.writeShellApplication {
+          name = "tmate-client-config";
+          runtimeInputs = with pkgs;[ openssh coreutils sd ];
+          text = ''
+            RSA_SIG="$(ssh-keygen -l -E SHA256 -f "${keysDir}/ssh_host_rsa_key.pub" | cut -d ' ' -f 2)"
+            ED25519_SIG="$(ssh-keygen -l -E SHA256 -f "${keysDir}/ssh_host_ed25519_key.pub" | cut -d ' ' -f 2)"
+            sd -sp '@ed25519_fingerprint@' "$ED25519_SIG" ${tmate-config} | \
+              sd -sp '@rsa_fingerprint@' "$RSA_SIG"
+          '';
+        })
+      ];
+
+    systemd.services.tmate-ssh-server = {
+      description = "tmate SSH Server";
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig = {
+        ExecStart = "${cfg.package}/bin/tmate-ssh-server -h ${cfg.host} -p ${toString cfg.port} -q ${toString cfg.advertisedPort} -k ${keysDir}";
+      };
+      preStart = mkIf (cfg.keysDir == null) ''
+        if [[ ! -d ${defaultKeysDir} ]]
+        then
+          mkdir -p ${defaultKeysDir}
+        fi
+        if [[ ! -f ${edKey} ]]
+        then
+          ${pkgs.openssh}/bin/ssh-keygen -t ed25519 -f ${edKey} -N ""
+        fi
+        if [[ ! -f ${rsaKey} ]]
+        then
+          ${pkgs.openssh}/bin/ssh-keygen -t rsa -f ${rsaKey} -N ""
+        fi
+      '';
+    };
+  };
+
+  meta = {
+    maintainers = with maintainers; [ jlesquembre ];
+  };
+
+}