diff --git a/nixos/modules/services/web-servers/ttyd.nix b/nixos/modules/services/web-servers/ttyd.nix
index e545869ca432..14361df2bb66 100644
--- a/nixos/modules/services/web-servers/ttyd.nix
+++ b/nixos/modules/services/web-servers/ttyd.nix
@@ -1,11 +1,17 @@
{ config, lib, pkgs, ... }:
-with lib;
-
let
cfg = config.services.ttyd;
+ inherit (lib)
+ optionals
+ types
+ concatLists
+ mapAttrsToList
+ mkOption
+ ;
+
# Command line arguments for the ttyd daemon
args = [ "--port" (toString cfg.port) ]
++ optionals (cfg.socket != null) [ "--interface" cfg.socket ]
@@ -14,6 +20,7 @@ let
++ (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" ]
@@ -30,40 +37,40 @@ in
options = {
services.ttyd = {
- enable = mkEnableOption (lib.mdDoc "ttyd daemon");
+ enable = lib.mkEnableOption ("ttyd daemon");
port = mkOption {
type = types.port;
default = 7681;
- description = lib.mdDoc "Port to listen on (use 0 for random port)";
+ description = "Port to listen on (use 0 for random port)";
};
socket = mkOption {
type = types.nullOr types.path;
default = null;
example = "/var/run/ttyd.sock";
- description = lib.mdDoc "UNIX domain socket path to bind.";
+ description = "UNIX domain socket path to bind.";
};
interface = mkOption {
type = types.nullOr types.str;
default = null;
example = "eth0";
- description = lib.mdDoc "Network interface to bind.";
+ description = "Network interface to bind.";
};
username = mkOption {
type = types.nullOr types.str;
default = null;
- description = lib.mdDoc "Username for basic authentication.";
+ description = "Username for basic http authentication.";
};
passwordFile = mkOption {
type = types.nullOr types.path;
default = null;
apply = value: if value == null then null else toString value;
- description = lib.mdDoc ''
- File containing the password to use for basic authentication.
+ description = ''
+ File containing the password to use for basic http authentication.
For insecurely putting the password in the globally readable store use
`pkgs.writeText "ttydpw" "MyPassword"`.
'';
@@ -72,19 +79,46 @@ in
signal = mkOption {
type = types.ints.u8;
default = 1;
- description = lib.mdDoc "Signal to send to the command on session close.";
+ description = "Signal to send to the command on session close.";
+ };
+
+ entrypoint = mkOption {
+ type = types.listOf types.str;
+ default = [ "${pkgs.shadow}/bin/login" ];
+ defaultText = lib.literalExpression ''
+ [ "''${pkgs.shadow}/bin/login" ]
+ '';
+ example = lib.literalExpression ''
+ [ (lib.getExe pkgs.htop) ]
+ '';
+ description = "Which command ttyd runs.";
+ apply = lib.escapeShellArgs;
+ };
+
+ user = mkOption {
+ type = types.str;
+ # `login` needs to be run as root
+ default = "root";
+ description = "Which unix user ttyd should run as.";
+ };
+
+ writeable = mkOption {
+ type = types.nullOr types.bool;
+ default = null; # null causes an eval error, forcing the user to consider attack surface
+ example = true;
+ description = "Allow clients to write to the TTY.";
};
clientOptions = mkOption {
type = types.attrsOf types.str;
default = {};
- example = literalExpression ''
+ example = lib.literalExpression ''
{
fontSize = "16";
fontFamily = "Fira Code";
}
'';
- description = lib.mdDoc ''
+ description = ''
Attribute set of client options for xtermjs.