turnon: 1.6.1 -> 1.6.2 (#364647)
[NixPkgs.git] / nixos / modules / services / networking / xrdp.nix
blobd571c6e4d88d79460368dea2560109f7464742c6
1 { config, lib, pkgs, ... }:
3 with lib;
5 let
6   cfg = config.services.xrdp;
8   confDir = pkgs.runCommand "xrdp.conf" { preferLocalBuild = true; } ''
9     mkdir -p $out
11     cp -r ${cfg.package}/etc/xrdp/* $out
12     chmod -R +w $out
14     cat > $out/startwm.sh <<EOF
15     #!/bin/sh
16     . /etc/profile
17     ${lib.optionalString cfg.audio.enable "${cfg.audio.package}/libexec/pulsaudio-xrdp-module/pulseaudio_xrdp_init"}
18     ${cfg.defaultWindowManager}
19     EOF
20     chmod +x $out/startwm.sh
22     substituteInPlace $out/xrdp.ini \
23       --replace "#rsakeys_ini=" "rsakeys_ini=/run/xrdp/rsakeys.ini" \
24       --replace "certificate=" "certificate=${cfg.sslCert}" \
25       --replace "key_file=" "key_file=${cfg.sslKey}" \
26       --replace LogFile=xrdp.log LogFile=/dev/null \
27       --replace EnableSyslog=true EnableSyslog=false
29     substituteInPlace $out/sesman.ini \
30       --replace LogFile=xrdp-sesman.log LogFile=/dev/null \
31       --replace EnableSyslog=1 EnableSyslog=0 \
32       --replace startwm.sh $out/startwm.sh \
33       --replace reconnectwm.sh $out/reconnectwm.sh \
35     # Ensure that clipboard works for non-ASCII characters
36     sed -i -e '/.*SessionVariables.*/ a\
37     LANG=${config.i18n.defaultLocale}\
38     LOCALE_ARCHIVE=${config.i18n.glibcLocales}/lib/locale/locale-archive
39     ' $out/sesman.ini
41     ${cfg.extraConfDirCommands}
42   '';
46   ###### interface
48   options = {
50     services.xrdp = {
52       enable = mkEnableOption "xrdp, the Remote Desktop Protocol server";
54       package = mkPackageOption pkgs "xrdp" { };
56       audio = {
57         enable = mkEnableOption "audio support for xrdp sessions. So far it only works with PulseAudio sessions on the server side. No PipeWire support yet";
58         package = mkPackageOption pkgs "pulseaudio-module-xrdp" {};
59       };
61       port = mkOption {
62         type = types.port;
63         default = 3389;
64         description = ''
65           Specifies on which port the xrdp daemon listens.
66         '';
67       };
69       openFirewall = mkOption {
70         default = false;
71         type = types.bool;
72         description = "Whether to open the firewall for the specified RDP port.";
73       };
75       sslKey = mkOption {
76         type = types.str;
77         default = "/etc/xrdp/key.pem";
78         example = "/path/to/your/key.pem";
79         description = ''
80           ssl private key path
81           A self-signed certificate will be generated if file not exists.
82         '';
83       };
85       sslCert = mkOption {
86         type = types.str;
87         default = "/etc/xrdp/cert.pem";
88         example = "/path/to/your/cert.pem";
89         description = ''
90           ssl certificate path
91           A self-signed certificate will be generated if file not exists.
92         '';
93       };
95       defaultWindowManager = mkOption {
96         type = types.str;
97         default = "xterm";
98         example = "xfce4-session";
99         description = ''
100           The script to run when user log in, usually a window manager, e.g. "icewm", "xfce4-session"
101           This is per-user overridable, if file ~/startwm.sh exists it will be used instead.
102         '';
103       };
105       confDir = mkOption {
106         type = types.path;
107         default = confDir;
108         internal = true;
109         description = ''
110           Configuration directory of xrdp and sesman.
112           Changes to this must be made through extraConfDirCommands.
113         '';
114         readOnly = true;
115       };
117       extraConfDirCommands = mkOption {
118         type = types.str;
119         default = "";
120         description = ''
121           Extra commands to run on the default confDir derivation.
122         '';
123         example = ''
124           substituteInPlace $out/sesman.ini \
125             --replace LogLevel=INFO LogLevel=DEBUG \
126             --replace LogFile=/dev/null LogFile=/var/log/xrdp.log
127         '';
128       };
129     };
130   };
132   ###### implementation
134   config = lib.mkMerge [
135     (mkIf cfg.audio.enable {
136       environment.systemPackages = [ cfg.audio.package ];  # needed for autostart
138       hardware.pulseaudio.extraModules = [ cfg.audio.package ];
139     })
141     (mkIf cfg.enable {
143       networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.port ];
145       # xrdp can run X11 program even if "services.xserver.enable = false"
146       xdg = {
147         autostart.enable = true;
148         menus.enable = true;
149         mime.enable = true;
150         icons.enable = true;
151       };
153       fonts.enableDefaultPackages = mkDefault true;
155       environment.etc."xrdp".source = "${confDir}/*";
157       systemd = {
158         services.xrdp = {
159           wantedBy = [ "multi-user.target" ];
160           after = [ "network.target" ];
161           description = "xrdp daemon";
162           requires = [ "xrdp-sesman.service" ];
163           preStart = ''
164             # prepare directory for unix sockets (the sockets will be owned by loggedinuser:xrdp)
165             mkdir -p /tmp/.xrdp || true
166             chown xrdp:xrdp /tmp/.xrdp
167             chmod 3777 /tmp/.xrdp
169             # generate a self-signed certificate
170             if [ ! -s ${cfg.sslCert} -o ! -s ${cfg.sslKey} ]; then
171               mkdir -p $(dirname ${cfg.sslCert}) || true
172               mkdir -p $(dirname ${cfg.sslKey}) || true
173               ${lib.getExe pkgs.openssl} req -x509 -newkey rsa:2048 -sha256 -nodes -days 365 \
174                 -subj /C=US/ST=CA/L=Sunnyvale/O=xrdp/CN=www.xrdp.org \
175                 -config ${cfg.package}/share/xrdp/openssl.conf \
176                 -keyout ${cfg.sslKey} -out ${cfg.sslCert}
177               chown root:xrdp ${cfg.sslKey} ${cfg.sslCert}
178               chmod 440 ${cfg.sslKey} ${cfg.sslCert}
179             fi
180             if [ ! -s /run/xrdp/rsakeys.ini ]; then
181               mkdir -p /run/xrdp
182               ${pkgs.xrdp}/bin/xrdp-keygen xrdp /run/xrdp/rsakeys.ini
183             fi
184           '';
185           serviceConfig = {
186             User = "xrdp";
187             Group = "xrdp";
188             PermissionsStartOnly = true;
189             ExecStart = "${pkgs.xrdp}/bin/xrdp --nodaemon --port ${toString cfg.port} --config ${confDir}/xrdp.ini";
190           };
191         };
193         services.xrdp-sesman = {
194           wantedBy = [ "multi-user.target" ];
195           after = [ "network.target" ];
196           description = "xrdp session manager";
197           restartIfChanged = false; # do not restart on "nixos-rebuild switch". like "display-manager", it can have many interactive programs as children
198           serviceConfig = {
199             ExecStart = "${pkgs.xrdp}/bin/xrdp-sesman --nodaemon --config ${confDir}/sesman.ini";
200             ExecStop  = "${pkgs.coreutils}/bin/kill -INT $MAINPID";
201           };
202         };
204       };
206       users.users.xrdp = {
207         description   = "xrdp daemon user";
208         isSystemUser  = true;
209         group         = "xrdp";
210       };
211       users.groups.xrdp = {};
213       security.pam.services.xrdp-sesman = {
214         allowNullPassword = true;
215         startSession = true;
216       };
218     })
219   ];