refactor: change to systemd user service

Systant is designed as a userspace controller rather than a system
daemon, so it makes more sense to run as a user service with access
to the user's environment, PATH, and session (for audio control, etc).

Changes:
- Remove user/group options (runs as current user)
- Use systemd.user.services instead of systemd.services
- Remove hardening options (not needed and would restrict access)
- Add package to environment.systemPackages

Enable with: systemctl --user enable --now systant

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
ryan 2026-01-19 20:55:36 -08:00
parent 08bf13cc32
commit 4e46f3e0fc

View File

@ -3,6 +3,12 @@
let let
cfg = config.systant; cfg = config.systant;
settingsFormat = pkgs.formats.toml { }; settingsFormat = pkgs.formats.toml { };
configFile =
if cfg.configFile != null
then cfg.configFile
else if cfg.settings != { }
then settingsFormat.generate "systant-config.toml" cfg.settings
else null;
in in
{ {
options.systant = { options.systant = {
@ -53,70 +59,27 @@ in
} }
''; '';
}; };
user = lib.mkOption {
type = lib.types.str;
default = "systant";
description = "User account under which systant runs.";
};
group = lib.mkOption {
type = lib.types.str;
default = "systant";
description = "Group under which systant runs.";
};
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
# Create systant user/group if using defaults # Make the package available system-wide
users.users.${cfg.user} = lib.mkIf (cfg.user == "systant") { environment.systemPackages = [ cfg.package ];
isSystemUser = true;
group = cfg.group;
description = "Systant service user";
};
users.groups.${cfg.group} = lib.mkIf (cfg.group == "systant") { }; # Systemd user service - runs in user session with user's environment
systemd.user.services.systant = {
# Generate config file from settings if configFile not provided
environment.etc."systant/config.toml" = lib.mkIf (cfg.configFile == null && cfg.settings != { }) {
source = settingsFormat.generate "systant-config.toml" cfg.settings;
};
systemd.services.systant = {
description = "Systant system monitoring agent"; description = "Systant system monitoring agent";
wantedBy = [ "multi-user.target" ]; wantedBy = [ "default.target" ];
after = [ "network-online.target" ]; after = [ "network-online.target" ];
wants = [ "network-online.target" ]; wants = [ "network-online.target" ];
serviceConfig = { serviceConfig = {
Type = "simple"; Type = "simple";
User = cfg.user;
Group = cfg.group;
ExecStart = ExecStart =
let if configFile != null
configPath = then "${cfg.package}/bin/systant run --config ${configFile}"
if cfg.configFile != null else "${cfg.package}/bin/systant run";
then cfg.configFile
else "/etc/systant/config.toml";
in
"${cfg.package}/bin/systant run --config ${configPath}";
Restart = "on-failure"; Restart = "on-failure";
RestartSec = "5s"; RestartSec = "5s";
# Hardening
NoNewPrivileges = true;
ProtectSystem = "strict";
ProtectHome = true;
PrivateTmp = true;
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectControlGroups = true;
# Allow reading system metrics
ReadOnlyPaths = [
"/proc"
"/sys"
];
}; };
}; };
}; };