From 4e46f3e0fcbebe7b8eeeb30e8e782f5b11d2f6f2 Mon Sep 17 00:00:00 2001 From: ryan Date: Mon, 19 Jan 2026 20:55:36 -0800 Subject: [PATCH] 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 --- nix/nixos-module.nix | 65 ++++++++++---------------------------------- 1 file changed, 14 insertions(+), 51 deletions(-) diff --git a/nix/nixos-module.nix b/nix/nixos-module.nix index dbfc177..0ef7210 100644 --- a/nix/nixos-module.nix +++ b/nix/nixos-module.nix @@ -3,6 +3,12 @@ let cfg = config.systant; 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 { 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 { - # Create systant user/group if using defaults - users.users.${cfg.user} = lib.mkIf (cfg.user == "systant") { - isSystemUser = true; - group = cfg.group; - description = "Systant service user"; - }; + # Make the package available system-wide + environment.systemPackages = [ cfg.package ]; - users.groups.${cfg.group} = lib.mkIf (cfg.group == "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 = { + # Systemd user service - runs in user session with user's environment + systemd.user.services.systant = { description = "Systant system monitoring agent"; - wantedBy = [ "multi-user.target" ]; + wantedBy = [ "default.target" ]; after = [ "network-online.target" ]; wants = [ "network-online.target" ]; serviceConfig = { Type = "simple"; - User = cfg.user; - Group = cfg.group; ExecStart = - let - configPath = - if cfg.configFile != null - then cfg.configFile - else "/etc/systant/config.toml"; - in - "${cfg.package}/bin/systant run --config ${configPath}"; + if configFile != null + then "${cfg.package}/bin/systant run --config ${configFile}" + else "${cfg.package}/bin/systant run"; Restart = "on-failure"; RestartSec = "5s"; - - # Hardening - NoNewPrivileges = true; - ProtectSystem = "strict"; - ProtectHome = true; - PrivateTmp = true; - ProtectKernelTunables = true; - ProtectKernelModules = true; - ProtectControlGroups = true; - - # Allow reading system metrics - ReadOnlyPaths = [ - "/proc" - "/sys" - ]; }; }; };