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>
This commit is contained in:
ryan 2025-08-02 18:59:46 -07:00
parent 248f3f88e6
commit d1e497cdc2
4 changed files with 21 additions and 15 deletions

View File

@ -6,10 +6,10 @@ config :systant, Systant.MqttClient,
client_id: "systant",
username: "mqtt",
password: "pleasework",
stats_topic: "system/stats",
command_topic: "system/commands",
stats_topic_base: "systant", # Will become systant/{hostname}/stats
command_topic_base: "systant", # Will become systant/{hostname}/commands
publish_interval: 30_000
config :logger, :console,
format: "$time $metadata[$level] $message\n",
metadata: [:request_id]
metadata: [:request_id]

View File

@ -1,5 +1,11 @@
import Config
# Get hostname for topic construction
hostname = case :inet.gethostname() do
{:ok, hostname} -> List.to_string(hostname)
_ -> "unknown"
end
# Runtime configuration that can use environment variables
config :systant, Systant.MqttClient,
host: System.get_env("SYSTANT_MQTT_HOST", "localhost"),
@ -7,6 +13,6 @@ config :systant, Systant.MqttClient,
client_id: System.get_env("SYSTANT_CLIENT_ID", "systant"),
username: System.get_env("SYSTANT_MQTT_USERNAME"),
password: System.get_env("SYSTANT_MQTT_PASSWORD"),
stats_topic: System.get_env("SYSTANT_STATS_TOPIC", "system/stats"),
command_topic: System.get_env("SYSTANT_COMMAND_TOPIC", "system/commands"),
stats_topic: System.get_env("SYSTANT_STATS_TOPIC", "systant/#{hostname}/stats"),
command_topic: System.get_env("SYSTANT_COMMAND_TOPIC", "systant/#{hostname}/commands"),
publish_interval: String.to_integer(System.get_env("SYSTANT_PUBLISH_INTERVAL", "30000"))

View File

@ -40,13 +40,13 @@ in
statsTopic = mkOption {
type = types.str;
default = "system/stats";
default = "systant/${config.networking.hostName}/stats";
description = "MQTT topic for publishing stats";
};
commandTopic = mkOption {
type = types.str;
default = "system/commands";
default = "systant/${config.networking.hostName}/commands";
description = "MQTT topic for receiving commands";
};
@ -64,13 +64,13 @@ in
wantedBy = [ "multi-user.target" ];
environment = {
SYSTEM_STATS_MQTT_HOST = cfg.mqttHost;
SYSTEM_STATS_MQTT_PORT = toString cfg.mqttPort;
SYSTEM_STATS_MQTT_USERNAME = mkIf (cfg.mqttUsername != null) cfg.mqttUsername;
SYSTEM_STATS_MQTT_PASSWORD = mkIf (cfg.mqttPassword != null) cfg.mqttPassword;
SYSTEM_STATS_STATS_TOPIC = cfg.statsTopic;
SYSTEM_STATS_COMMAND_TOPIC = cfg.commandTopic;
SYSTEM_STATS_PUBLISH_INTERVAL = toString cfg.publishInterval;
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";
};

View File

@ -10,7 +10,7 @@ beamPackages.mixRelease rec {
src = fetchgit {
url = "https://git.ryanpandya.com/ryan/systant.git";
rev = "f8173a1afb03623039ff504c587d7322a9876f3d";
rev = "54f8d23945bcea17127631a81f8ac318bf7047a6";
sha256 = "sha256-1cRfSoH+JdO4a7q4hRZSkoDMk2wMCYRIyCIN56FSUgg=";
};