1{
2 lib,
3 pkgs,
4 config,
5 ...
6}:
7let
8 TCPPorts = [
9 21115
10 21116
11 21117
12 21118
13 21119
14 ];
15 UDPPorts = [ 21116 ];
16in
17{
18 imports = [
19 (lib.mkRemovedOptionModule [
20 "services"
21 "rustdesk-server"
22 "relayIP"
23 ] "This option has been replaced by services.rustdesk-server.signal.relayHosts")
24 (lib.mkRenamedOptionModule
25 [ "services" "rustdesk-server" "extraRelayArgs" ]
26 [ "services" "rustdesk-server" "relay" "extraArgs" ]
27 )
28 (lib.mkRenamedOptionModule
29 [ "services" "rustdesk-server" "extraSignalArgs" ]
30 [ "services" "rustdesk-server" "signal" "extraArgs" ]
31 )
32 ];
33
34 options.services.rustdesk-server =
35 with lib;
36 with types;
37 {
38 enable = mkEnableOption "RustDesk, a remote access and remote control software, allowing maintenance of computers and other devices";
39
40 package = mkPackageOption pkgs "rustdesk-server" { };
41
42 openFirewall = mkOption {
43 type = types.bool;
44 default = false;
45 description = ''
46 Open the connection ports.
47 TCP (${lib.concatStringsSep ", " (map toString TCPPorts)})
48 UDP (${lib.concatStringsSep ", " (map toString UDPPorts)})
49 '';
50 };
51
52 signal = {
53 enable = mkOption {
54 type = bool;
55 default = true;
56 description = ''
57 Whether to enable the RustDesk signal server.
58 '';
59 };
60
61 relayHosts = mkOption {
62 type = listOf str;
63 default = [ ];
64 # reference: https://rustdesk.com/docs/en/self-host/rustdesk-server-pro/relay/
65 description = ''
66 The relay server IP addresses or DNS names of the RustDesk relay.
67 '';
68 };
69
70 extraArgs = mkOption {
71 type = listOf str;
72 default = [ ];
73 example = [
74 "-k"
75 "_"
76 ];
77 description = ''
78 A list of extra command line arguments to pass to the `hbbs` process.
79 '';
80 };
81
82 };
83
84 relay = {
85 enable = mkOption {
86 type = bool;
87 default = true;
88 description = ''
89 Whether to enable the RustDesk relay server.
90 '';
91 };
92 extraArgs = mkOption {
93 type = listOf str;
94 default = [ ];
95 example = [
96 "-k"
97 "_"
98 ];
99 description = ''
100 A list of extra command line arguments to pass to the `hbbr` process.
101 '';
102 };
103 };
104
105 };
106
107 config =
108 let
109 cfg = config.services.rustdesk-server;
110 serviceDefaults = {
111 enable = true;
112 requiredBy = [ "rustdesk.target" ];
113 serviceConfig = {
114 Slice = "system-rustdesk.slice";
115 User = "rustdesk";
116 Group = "rustdesk";
117 DynamicUser = "yes";
118 Environment = [ ];
119 WorkingDirectory = "/var/lib/rustdesk";
120 StateDirectory = "rustdesk";
121 StateDirectoryMode = "0750";
122 LockPersonality = true;
123 PrivateDevices = true;
124 PrivateMounts = true;
125 PrivateUsers = true;
126 ProtectClock = true;
127 ProtectControlGroups = true;
128 ProtectHome = true;
129 ProtectHostname = true;
130 ProtectKernelLogs = true;
131 ProtectKernelModules = true;
132 ProtectKernelTunables = true;
133 ProtectProc = "invisible";
134 RestrictNamespaces = true;
135 };
136 };
137 in
138 lib.mkIf cfg.enable {
139 users.users.rustdesk = {
140 description = "System user for RustDesk";
141 isSystemUser = true;
142 group = "rustdesk";
143 };
144 users.groups.rustdesk = { };
145
146 networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall TCPPorts;
147 networking.firewall.allowedUDPPorts = lib.mkIf cfg.openFirewall UDPPorts;
148
149 systemd.slices.system-rustdesk = {
150 enable = true;
151 description = "RustDesk Remote Desktop Slice";
152 };
153
154 systemd.targets.rustdesk = {
155 enable = true;
156 description = "Target designed to group RustDesk Signal & RustDesk Relay";
157 after = [ "network.target" ];
158 wantedBy = [ "multi-user.target" ];
159 };
160
161 systemd.services.rustdesk-signal =
162 let
163 relayArg = builtins.concatStringsSep ":" cfg.signal.relayHosts;
164 in
165 lib.mkIf cfg.signal.enable (
166 lib.mkMerge [
167 serviceDefaults
168 {
169 serviceConfig.ExecStart = "${cfg.package}/bin/hbbs --relay-servers ${relayArg} ${lib.escapeShellArgs cfg.signal.extraArgs}";
170 }
171 ]
172 );
173
174 systemd.services.rustdesk-relay = lib.mkIf cfg.relay.enable (
175 lib.mkMerge [
176 serviceDefaults
177 {
178 serviceConfig.ExecStart = "${cfg.package}/bin/hbbr ${lib.escapeShellArgs cfg.relay.extraArgs}";
179 }
180 ]
181 );
182 };
183
184 meta.maintainers = with lib.maintainers; [ ppom ];
185}