nixos/ttyd: add writable option

Co-authored-by: Carsten Rodin <19612711+carstoid@users.noreply.github.com>

Changed files
+26 -5
nixos
modules
services
web-servers
tests
web-servers
+10
nixos/modules/services/web-servers/ttyd.nix
···
++ (concatLists (mapAttrsToList (_k: _v: [ "--client-option" "${_k}=${_v}" ]) cfg.clientOptions))
++ [ "--terminal-type" cfg.terminalType ]
++ optionals cfg.checkOrigin [ "--check-origin" ]
+
++ optionals cfg.writeable [ "--writable" ] # the typo is correct
++ [ "--max-clients" (toString cfg.maxClients) ]
++ optionals (cfg.indexFile != null) [ "--index" cfg.indexFile ]
++ optionals cfg.enableIPv6 [ "--ipv6" ]
···
type = types.ints.u8;
default = 1;
description = lib.mdDoc "Signal to send to the command on session close.";
+
};
+
+
writeable = mkOption {
+
type = types.nullOr types.bool;
+
default = null; # null causes an eval error, forcing the user to consider attack surface
+
example = true;
+
description = lib.mdDoc "Allow clients to write to the TTY.";
};
clientOptions = mkOption {
···
[ { assertion = cfg.enableSSL
-> cfg.certFile != null && cfg.keyFile != null && cfg.caFile != null;
message = "SSL is enabled for ttyd, but no certFile, keyFile or caFile has been specified."; }
+
{ assertion = cfg.writeable != null;
+
message = "services.ttyd.writeable must be set"; }
{ assertion = ! (cfg.interface != null && cfg.socket != null);
message = "Cannot set both interface and socket for ttyd."; }
{ assertion = (cfg.username != null) == (cfg.passwordFile != null);
+16 -5
nixos/tests/web-servers/ttyd.nix
···
name = "ttyd";
meta.maintainers = with lib.maintainers; [ stunkymonkey ];
-
nodes.machine = { pkgs, ... }: {
+
nodes.readonly = { pkgs, ... }: {
services.ttyd = {
enable = true;
username = "foo";
passwordFile = pkgs.writeText "password" "bar";
+
writeable = false;
+
};
+
};
+
+
nodes.writeable = { pkgs, ... }: {
+
services.ttyd = {
+
enable = true;
+
username = "foo";
+
passwordFile = pkgs.writeText "password" "bar";
+
writeable = true;
};
};
testScript = ''
-
machine.wait_for_unit("ttyd.service")
-
machine.wait_for_open_port(7681)
-
response = machine.succeed("curl -vvv -u foo:bar -s -H 'Host: ttyd' http://127.0.0.1:7681/")
-
assert '<title>ttyd - Terminal</title>' in response, "Page didn't load successfully"
+
for machine in [readonly, writeable]:
+
machine.wait_for_unit("ttyd.service")
+
machine.wait_for_open_port(7681)
+
response = machine.succeed("curl -vvv -u foo:bar -s -H 'Host: ttyd' http://127.0.0.1:7681/")
+
assert '<title>ttyd - Terminal</title>' in response, "Page didn't load successfully"
'';
})