1{ lib, pkgs, config, ... }:
2let
3 TCPPorts = [21115 21116 21117 21118 21119];
4 UDPPorts = [21116];
5in {
6 options.services.rustdesk-server = with lib; with types; {
7 enable = mkEnableOption "RustDesk, a remote access and remote control software, allowing maintenance of computers and other devices.";
8
9 package = mkPackageOption pkgs "rustdesk-server" {};
10
11 openFirewall = mkOption {
12 type = types.bool;
13 default = false;
14 description = ''
15 Open the connection ports.
16 TCP (${lib.concatStringsSep ", " (map toString TCPPorts)})
17 UDP (${lib.concatStringsSep ", " (map toString UDPPorts)})
18 '';
19 };
20
21 relayIP = mkOption {
22 type = str;
23 description = ''
24 The public facing IP of the RustDesk relay.
25 '';
26 };
27
28 extraSignalArgs = mkOption {
29 type = listOf str;
30 default = [];
31 example = [ "-k" "_" ];
32 description = ''
33 A list of extra command line arguments to pass to the `hbbs` process.
34 '';
35 };
36
37 extraRelayArgs = mkOption {
38 type = listOf str;
39 default = [];
40 example = [ "-k" "_" ];
41 description = ''
42 A list of extra command line arguments to pass to the `hbbr` process.
43 '';
44 };
45 };
46
47 config = let
48 cfg = config.services.rustdesk-server;
49 serviceDefaults = {
50 enable = true;
51 requiredBy = [ "rustdesk.target" ];
52 serviceConfig = {
53 Slice = "system-rustdesk.slice";
54 User = "rustdesk";
55 Group = "rustdesk";
56 DynamicUser = "yes";
57 Environment = [];
58 WorkingDirectory = "/var/lib/rustdesk";
59 StateDirectory = "rustdesk";
60 StateDirectoryMode = "0750";
61 LockPersonality = true;
62 PrivateDevices = true;
63 PrivateMounts = true;
64 PrivateUsers = true;
65 ProtectClock = true;
66 ProtectControlGroups = true;
67 ProtectHome = true;
68 ProtectHostname = true;
69 ProtectKernelLogs = true;
70 ProtectKernelModules = true;
71 ProtectKernelTunables = true;
72 ProtectProc = "invisible";
73 RestrictNamespaces = true;
74 };
75 };
76 in lib.mkIf cfg.enable {
77 users.users.rustdesk = {
78 description = "System user for RustDesk";
79 isSystemUser = true;
80 group = "rustdesk";
81 };
82 users.groups.rustdesk = {};
83
84 networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall TCPPorts;
85 networking.firewall.allowedUDPPorts = lib.mkIf cfg.openFirewall UDPPorts;
86
87 systemd.slices.system-rustdesk = {
88 enable = true;
89 description = "Slice designed to contain RustDesk Signal & RustDesk Relay";
90 };
91
92 systemd.targets.rustdesk = {
93 enable = true;
94 description = "Target designed to group RustDesk Signal & RustDesk Relay";
95 after = [ "network.target" ];
96 wantedBy = [ "multi-user.target" ];
97 };
98
99 systemd.services.rustdesk-signal = lib.mkMerge [ serviceDefaults {
100 serviceConfig.ExecStart = "${cfg.package}/bin/hbbs -r ${cfg.relayIP} ${lib.escapeShellArgs cfg.extraSignalArgs}";
101 } ];
102
103 systemd.services.rustdesk-relay = lib.mkMerge [ serviceDefaults {
104 serviceConfig.ExecStart = "${cfg.package}/bin/hbbr ${lib.escapeShellArgs cfg.extraRelayArgs}";
105 } ];
106 };
107
108 meta.maintainers = with lib.maintainers; [ ppom ];
109}