at 23.11-pre 3.2 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.uptermd; 7in 8{ 9 options = { 10 services.uptermd = { 11 enable = mkEnableOption (lib.mdDoc "uptermd"); 12 13 openFirewall = mkOption { 14 type = types.bool; 15 default = false; 16 description = lib.mdDoc '' 17 Whether to open the firewall for the port in {option}`services.uptermd.port`. 18 ''; 19 }; 20 21 port = mkOption { 22 type = types.port; 23 default = 2222; 24 description = lib.mdDoc '' 25 Port the server will listen on. 26 ''; 27 }; 28 29 listenAddress = mkOption { 30 type = types.str; 31 default = "[::]"; 32 example = "127.0.0.1"; 33 description = lib.mdDoc '' 34 Address the server will listen on. 35 ''; 36 }; 37 38 hostKey = mkOption { 39 type = types.nullOr types.path; 40 default = null; 41 example = "/run/keys/upterm_host_ed25519_key"; 42 description = lib.mdDoc '' 43 Path to SSH host key. If not defined, an ed25519 keypair is generated automatically. 44 ''; 45 }; 46 47 extraFlags = mkOption { 48 type = types.listOf types.str; 49 default = []; 50 example = [ "--debug" ]; 51 description = lib.mdDoc '' 52 Extra flags passed to the uptermd command. 53 ''; 54 }; 55 }; 56 }; 57 58 config = mkIf cfg.enable { 59 networking.firewall = mkIf cfg.openFirewall { 60 allowedTCPPorts = [ cfg.port ]; 61 }; 62 63 systemd.services.uptermd = { 64 description = "Upterm Daemon"; 65 wantedBy = [ "multi-user.target" ]; 66 after = [ "network.target" ]; 67 68 path = [ pkgs.openssh ]; 69 70 preStart = mkIf (cfg.hostKey == null) '' 71 if ! [ -f ssh_host_ed25519_key ]; then 72 ssh-keygen \ 73 -t ed25519 \ 74 -f ssh_host_ed25519_key \ 75 -N "" 76 fi 77 ''; 78 79 serviceConfig = { 80 StateDirectory = "uptermd"; 81 WorkingDirectory = "/var/lib/uptermd"; 82 ExecStart = "${pkgs.upterm}/bin/uptermd --ssh-addr ${cfg.listenAddress}:${toString cfg.port} --private-key ${if cfg.hostKey == null then "ssh_host_ed25519_key" else cfg.hostKey} ${concatStringsSep " " cfg.extraFlags}"; 83 84 # Hardening 85 AmbientCapabilities = mkIf (cfg.port < 1024) [ "CAP_NET_BIND_SERVICE" ]; 86 CapabilityBoundingSet = mkIf (cfg.port < 1024) [ "CAP_NET_BIND_SERVICE" ]; 87 PrivateUsers = cfg.port >= 1024; 88 DynamicUser = true; 89 LockPersonality = true; 90 MemoryDenyWriteExecute = true; 91 PrivateDevices = true; 92 ProtectClock = true; 93 ProtectControlGroups = true; 94 ProtectHome = true; 95 ProtectHostname = true; 96 ProtectKernelLogs = true; 97 ProtectKernelModules = true; 98 ProtectKernelTunables = true; 99 ProtectProc = "invisible"; 100 # AF_UNIX is for ssh-keygen, which relies on nscd to resolve the uid to a user 101 RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ]; 102 RestrictNamespaces = true; 103 RestrictRealtime = true; 104 SystemCallArchitectures = "native"; 105 SystemCallFilter = "@system-service"; 106 }; 107 }; 108 }; 109}