{ config, lib, pkgs, ... }: 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 = { enable = lib.mkEnableOption "systant system monitoring agent"; package = lib.mkOption { type = lib.types.package; default = pkgs.systant; defaultText = lib.literalExpression "pkgs.systant"; description = "The systant package to use."; }; configFile = lib.mkOption { type = lib.types.nullOr lib.types.path; default = null; description = '' Path to the systant configuration file (TOML). If set, this takes precedence over the settings option. ''; }; settings = lib.mkOption { type = settingsFormat.type; default = { }; description = '' Configuration for systant in Nix attribute set form. Will be converted to TOML. Ignored if configFile is set. ''; example = lib.literalExpression '' { mqtt = { broker = "mqtt://localhost:1883"; topicPrefix = "systant"; }; entities = { cpu_usage = { type = "sensor"; state_command = "awk '/^cpu / {u=$2+$4; t=$2+$4+$5; print int(u*100/t)}' /proc/stat"; unit = "%"; icon = "mdi:cpu-64-bit"; name = "CPU Usage"; }; }; homeassistant = { discovery = true; discoveryPrefix = "homeassistant"; }; } ''; }; }; config = lib.mkIf cfg.enable { # Make the package available system-wide environment.systemPackages = [ cfg.package ]; # Systemd user service - runs in user session with user's environment systemd.user.services.systant = { description = "Systant system monitoring agent"; wantedBy = [ "default.target" ]; after = [ "network-online.target" ]; wants = [ "network-online.target" ]; serviceConfig = { Type = "simple"; ExecStart = if configFile != null then "${cfg.package}/bin/systant run --config ${configFile}" else "${cfg.package}/bin/systant run"; Restart = "on-failure"; RestartSec = "5s"; }; }; }; }