systant/nixos-module.nix
ryan d1e497cdc2 Add hostname-aware MQTT topics
- Topics now default to systant/{hostname}/stats and systant/{hostname}/commands
- Runtime config automatically includes system hostname in topics
- NixOS module defaults use config.networking.hostName
- Supports multiple hosts without topic conflicts
- Environment variables can still override if needed

Example: systant/orion/stats, systant/server2/stats, etc.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-02 18:59:46 -07:00

99 lines
2.6 KiB
Nix

{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.systant;
in
{
options.services.systant = {
enable = mkEnableOption "Systant MQTT Daemon";
package = mkOption {
type = types.package;
description = "The systant package to use";
};
mqttHost = mkOption {
type = types.str;
default = "localhost";
description = "MQTT broker hostname";
};
mqttPort = mkOption {
type = types.int;
default = 1883;
description = "MQTT broker port";
};
mqttUsername = mkOption {
type = types.nullOr types.str;
default = null;
description = "MQTT username (null for no auth)";
};
mqttPassword = mkOption {
type = types.nullOr types.str;
default = null;
description = "MQTT password (null for no auth)";
};
statsTopic = mkOption {
type = types.str;
default = "systant/${config.networking.hostName}/stats";
description = "MQTT topic for publishing stats";
};
commandTopic = mkOption {
type = types.str;
default = "systant/${config.networking.hostName}/commands";
description = "MQTT topic for receiving commands";
};
publishInterval = mkOption {
type = types.int;
default = 30000;
description = "Interval between stats publications (milliseconds)";
};
};
config = mkIf cfg.enable {
systemd.services.systant = {
description = "Systant MQTT Daemon";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
environment = {
SYSTANT_MQTT_HOST = cfg.mqttHost;
SYSTANT_MQTT_PORT = toString cfg.mqttPort;
SYSTANT_MQTT_USERNAME = mkIf (cfg.mqttUsername != null) cfg.mqttUsername;
SYSTANT_MQTT_PASSWORD = mkIf (cfg.mqttPassword != null) cfg.mqttPassword;
SYSTANT_STATS_TOPIC = cfg.statsTopic;
SYSTANT_COMMAND_TOPIC = cfg.commandTopic;
SYSTANT_PUBLISH_INTERVAL = toString cfg.publishInterval;
# Override RELEASE_COOKIE to bypass file reading
RELEASE_COOKIE = "systant-bypass-cookie";
};
serviceConfig = {
Type = "exec";
User = "root";
Group = "root";
ExecStart = "${cfg.package}/bin/systant start";
ExecStop = "${cfg.package}/bin/systant stop";
Restart = "always";
RestartSec = 5;
StandardOutput = "journal";
StandardError = "journal";
SyslogIdentifier = "systant";
WorkingDirectory = "${cfg.package}";
# Security settings
NoNewPrivileges = true;
PrivateTmp = true;
ProtectHome = true;
ProtectSystem = false; # Need access to system stats
};
};
};
}