-
-
Notifications
You must be signed in to change notification settings - Fork 13.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
nixos/tmate-ssh-server: init module (#192270)
* nixos/tmate-ssh-server: init module Co-authored-by: Aaron Andersen <aaron@fosslib.net>
- Loading branch information
1 parent
6c31662
commit 396f4f0
Showing
7 changed files
with
232 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 ]; | ||
}; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import ./make-test-python.nix ({ pkgs, lib, ... }: | ||
let | ||
inherit (import ./ssh-keys.nix pkgs) | ||
snakeOilPrivateKey snakeOilPublicKey; | ||
|
||
setUpPrivateKey = name: '' | ||
${name}.succeed( | ||
"mkdir -p /root/.ssh", | ||
"chown 700 /root/.ssh", | ||
"cat '${snakeOilPrivateKey}' > /root/.ssh/id_snakeoil", | ||
"chown 600 /root/.ssh/id_snakeoil", | ||
) | ||
${name}.wait_for_file("/root/.ssh/id_snakeoil") | ||
''; | ||
|
||
sshOpts = "-oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -oIdentityFile=/root/.ssh/id_snakeoil"; | ||
|
||
in | ||
{ | ||
name = "tmate-ssh-server"; | ||
nodes = | ||
{ | ||
server = { ... }: { | ||
services.tmate-ssh-server = { | ||
enable = true; | ||
port = 2223; | ||
}; | ||
}; | ||
client = { ... }: { | ||
environment.systemPackages = [ pkgs.tmate ]; | ||
services.openssh.enable = true; | ||
users.users.root.openssh.authorizedKeys.keys = [ snakeOilPublicKey ]; | ||
}; | ||
client2 = { ... }: { | ||
environment.systemPackages = [ pkgs.openssh ]; | ||
}; | ||
}; | ||
testScript = '' | ||
start_all() | ||
server.wait_for_unit("tmate-ssh-server.service") | ||
server.wait_for_open_port(2223) | ||
server.wait_for_file("/etc/tmate-ssh-server-keys/ssh_host_ed25519_key.pub") | ||
server.wait_for_file("/etc/tmate-ssh-server-keys/ssh_host_rsa_key.pub") | ||
server.succeed("tmate-client-config > /tmp/tmate.conf") | ||
server.wait_for_file("/tmp/tmate.conf") | ||
${setUpPrivateKey "server"} | ||
client.wait_for_unit("sshd.service") | ||
client.wait_for_open_port(22) | ||
server.succeed("scp ${sshOpts} /tmp/tmate.conf client:/tmp/tmate.conf") | ||
client.wait_for_file("/tmp/tmate.conf") | ||
client.send_chars("root\n") | ||
client.sleep(2) | ||
client.send_chars("tmate -f /tmp/tmate.conf\n") | ||
client.sleep(2) | ||
client.send_chars("q") | ||
client.sleep(2) | ||
client.send_chars("tmate display -p '#{tmate_ssh}' > /tmp/ssh_command\n") | ||
client.wait_for_file("/tmp/ssh_command") | ||
ssh_cmd = client.succeed("cat /tmp/ssh_command") | ||
client2.succeed("mkdir -p ~/.ssh; ssh-keyscan -p 2223 server > ~/.ssh/known_hosts") | ||
client2.send_chars("root\n") | ||
client2.sleep(2) | ||
client2.send_chars(ssh_cmd.strip() + "\n") | ||
client2.sleep(2) | ||
client2.send_chars("touch /tmp/client_2\n") | ||
client.wait_for_file("/tmp/client_2") | ||
''; | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters