Hi,
Yeah, I know. One shouldn’t use sudo in a systemd service script:
You don’t.
sudo
is for interactive use. Doing anything else with it is either incredibly cumbersome or rips security holes into your system. NixOS makes this rather hard anyway due to how setuid is handled.
But I’m trying to get rustdesk --service
, a background service that allows remote logins, to work with NixOS. And it calls sudo
- not much I can do about it.
Many gory (but perhaps irrelevant) details in Can’t get rustdesk to run under systemd in NixOS - works fine from terminal : r/rustdesk. The problem here was that rustdesk
didn’t have a sudo
in the path with setuid
.
This fix did the trick:
diff -u configuration.nix.doesnt-work configuration.nix
--- configuration.nix.doesnt-work 2025-03-23 16:43:42.150263373 +0100
+++ configuration.nix 2025-03-23 16:26:03.500585285 +0100
@@ -578,8 +578,11 @@
description = "RustDesk";
requires = [ "network.target" ];
after= [ "systemd-user-sessions.service" ];
+ script = ''
+ export PATH=/run/wrappers/bin:$PATH
+ ${pkgs.rustdesk}/bin/rustdesk --service
+ '';
serviceConfig = {
- ExecStart = "${pkgs.rustdesk}/bin/rustdesk --service";
ExecStop = "${pkgs.procps}/pkill -f 'rustdesk --'";
PIDFile = "/run/rustdesk.pid";
KillMode = "mixed";
(full service definition below)
Is this the best way of doing this? Does anyone have better recommendations? (Other than modifying rustdesk
which is out of scope).
I was thinking that instead of adding /run/wrappers/bin
to the path, I could perhaps create a temporary directory, copy sudo
from the path into it, chmod +s /path/to/sudo
(as script
runs as root), and add that directory to the path. And then I need to make sure I delete that temporary directory again. But that is cumbersome and for perhaps very little gain. And there’d be two sudo
executables with the setuid bit set in the system rather than only one.
systemd.services."rustdesk"
systemd.services."rustdesk" = {
enable = true;
path = with pkgs; [
pkgs.rustdesk
procps
# This doesn't work since the version of sudo that will then be in the
# path, won't have the setuid bit set
# sudo
# See the trick in `script` below modifying the path
];
description = "RustDesk";
requires = [ "network.target" ];
after= [ "systemd-user-sessions.service" ];
script = ''
export PATH=/run/wrappers/bin:$PATH
${pkgs.rustdesk}/bin/rustdesk --service
'';
serviceConfig = {
ExecStop = "${pkgs.procps}/pkill -f 'rustdesk --'";
PIDFile = "/run/rustdesk.pid";
KillMode = "mixed";
TimeoutStopSec = "30";
User = "root";
LimitNOFILE = "100000";
};
wantedBy = [ "multi-user.target" ];
};