at 23.11-pre 5.8 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.xrdp; 7 confDir = pkgs.runCommand "xrdp.conf" { preferLocalBuild = true; } '' 8 mkdir $out 9 10 cp ${cfg.package}/etc/xrdp/{km-*,xrdp,sesman,xrdp_keyboard}.ini $out 11 12 cat > $out/startwm.sh <<EOF 13 #!/bin/sh 14 . /etc/profile 15 ${cfg.defaultWindowManager} 16 EOF 17 chmod +x $out/startwm.sh 18 19 substituteInPlace $out/xrdp.ini \ 20 --replace "#rsakeys_ini=" "rsakeys_ini=/run/xrdp/rsakeys.ini" \ 21 --replace "certificate=" "certificate=${cfg.sslCert}" \ 22 --replace "key_file=" "key_file=${cfg.sslKey}" \ 23 --replace LogFile=xrdp.log LogFile=/dev/null \ 24 --replace EnableSyslog=true EnableSyslog=false 25 26 substituteInPlace $out/sesman.ini \ 27 --replace LogFile=xrdp-sesman.log LogFile=/dev/null \ 28 --replace EnableSyslog=1 EnableSyslog=0 29 30 # Ensure that clipboard works for non-ASCII characters 31 sed -i -e '/.*SessionVariables.*/ a\ 32 LANG=${config.i18n.defaultLocale}\ 33 LOCALE_ARCHIVE=${config.i18n.glibcLocales}/lib/locale/locale-archive 34 ' $out/sesman.ini 35 ''; 36in 37{ 38 39 ###### interface 40 41 options = { 42 43 services.xrdp = { 44 45 enable = mkEnableOption (lib.mdDoc "xrdp, the Remote Desktop Protocol server"); 46 47 package = mkOption { 48 type = types.package; 49 default = pkgs.xrdp; 50 defaultText = literalExpression "pkgs.xrdp"; 51 description = lib.mdDoc '' 52 The package to use for the xrdp daemon's binary. 53 ''; 54 }; 55 56 port = mkOption { 57 type = types.port; 58 default = 3389; 59 description = lib.mdDoc '' 60 Specifies on which port the xrdp daemon listens. 61 ''; 62 }; 63 64 openFirewall = mkOption { 65 default = false; 66 type = types.bool; 67 description = lib.mdDoc "Whether to open the firewall for the specified RDP port."; 68 }; 69 70 sslKey = mkOption { 71 type = types.str; 72 default = "/etc/xrdp/key.pem"; 73 example = "/path/to/your/key.pem"; 74 description = lib.mdDoc '' 75 ssl private key path 76 A self-signed certificate will be generated if file not exists. 77 ''; 78 }; 79 80 sslCert = mkOption { 81 type = types.str; 82 default = "/etc/xrdp/cert.pem"; 83 example = "/path/to/your/cert.pem"; 84 description = lib.mdDoc '' 85 ssl certificate path 86 A self-signed certificate will be generated if file not exists. 87 ''; 88 }; 89 90 defaultWindowManager = mkOption { 91 type = types.str; 92 default = "xterm"; 93 example = "xfce4-session"; 94 description = lib.mdDoc '' 95 The script to run when user log in, usually a window manager, e.g. "icewm", "xfce4-session" 96 This is per-user overridable, if file ~/startwm.sh exists it will be used instead. 97 ''; 98 }; 99 100 confDir = mkOption { 101 type = types.path; 102 default = confDir; 103 defaultText = literalMD "generated from configuration"; 104 description = lib.mdDoc "The location of the config files for xrdp."; 105 }; 106 }; 107 }; 108 109 110 ###### implementation 111 112 config = mkIf cfg.enable { 113 114 networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.port ]; 115 116 # xrdp can run X11 program even if "services.xserver.enable = false" 117 xdg = { 118 autostart.enable = true; 119 menus.enable = true; 120 mime.enable = true; 121 icons.enable = true; 122 }; 123 124 fonts.enableDefaultFonts = mkDefault true; 125 126 systemd = { 127 services.xrdp = { 128 wantedBy = [ "multi-user.target" ]; 129 after = [ "network.target" ]; 130 description = "xrdp daemon"; 131 requires = [ "xrdp-sesman.service" ]; 132 preStart = '' 133 # prepare directory for unix sockets (the sockets will be owned by loggedinuser:xrdp) 134 mkdir -p /tmp/.xrdp || true 135 chown xrdp:xrdp /tmp/.xrdp 136 chmod 3777 /tmp/.xrdp 137 138 # generate a self-signed certificate 139 if [ ! -s ${cfg.sslCert} -o ! -s ${cfg.sslKey} ]; then 140 mkdir -p $(dirname ${cfg.sslCert}) || true 141 mkdir -p $(dirname ${cfg.sslKey}) || true 142 ${pkgs.openssl.bin}/bin/openssl req -x509 -newkey rsa:2048 -sha256 -nodes -days 365 \ 143 -subj /C=US/ST=CA/L=Sunnyvale/O=xrdp/CN=www.xrdp.org \ 144 -config ${cfg.package}/share/xrdp/openssl.conf \ 145 -keyout ${cfg.sslKey} -out ${cfg.sslCert} 146 chown root:xrdp ${cfg.sslKey} ${cfg.sslCert} 147 chmod 440 ${cfg.sslKey} ${cfg.sslCert} 148 fi 149 if [ ! -s /run/xrdp/rsakeys.ini ]; then 150 mkdir -p /run/xrdp 151 ${cfg.package}/bin/xrdp-keygen xrdp /run/xrdp/rsakeys.ini 152 fi 153 ''; 154 serviceConfig = { 155 User = "xrdp"; 156 Group = "xrdp"; 157 PermissionsStartOnly = true; 158 ExecStart = "${cfg.package}/bin/xrdp --nodaemon --port ${toString cfg.port} --config ${cfg.confDir}/xrdp.ini"; 159 }; 160 }; 161 162 services.xrdp-sesman = { 163 wantedBy = [ "multi-user.target" ]; 164 after = [ "network.target" ]; 165 description = "xrdp session manager"; 166 restartIfChanged = false; # do not restart on "nixos-rebuild switch". like "display-manager", it can have many interactive programs as children 167 serviceConfig = { 168 ExecStart = "${cfg.package}/bin/xrdp-sesman --nodaemon --config ${cfg.confDir}/sesman.ini"; 169 ExecStop = "${pkgs.coreutils}/bin/kill -INT $MAINPID"; 170 }; 171 }; 172 173 }; 174 175 users.users.xrdp = { 176 description = "xrdp daemon user"; 177 isSystemUser = true; 178 group = "xrdp"; 179 }; 180 users.groups.xrdp = {}; 181 182 security.pam.services.xrdp-sesman = { allowNullPassword = true; startSession = true; }; 183 }; 184 185}