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,8 +6,8 @@ config :systant, Systant.MqttClient,
client_id: "systant", client_id: "systant",
username: "mqtt", username: "mqtt",
password: "pleasework", password: "pleasework",
stats_topic: "system/stats", stats_topic_base: "systant", # Will become systant/{hostname}/stats
command_topic: "system/commands", command_topic_base: "systant", # Will become systant/{hostname}/commands
publish_interval: 30_000 publish_interval: 30_000
config :logger, :console, config :logger, :console,

View File

@ -1,5 +1,11 @@
import Config 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 # Runtime configuration that can use environment variables
config :systant, Systant.MqttClient, config :systant, Systant.MqttClient,
host: System.get_env("SYSTANT_MQTT_HOST", "localhost"), 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"), client_id: System.get_env("SYSTANT_CLIENT_ID", "systant"),
username: System.get_env("SYSTANT_MQTT_USERNAME"), username: System.get_env("SYSTANT_MQTT_USERNAME"),
password: System.get_env("SYSTANT_MQTT_PASSWORD"), password: System.get_env("SYSTANT_MQTT_PASSWORD"),
stats_topic: System.get_env("SYSTANT_STATS_TOPIC", "system/stats"), stats_topic: System.get_env("SYSTANT_STATS_TOPIC", "systant/#{hostname}/stats"),
command_topic: System.get_env("SYSTANT_COMMAND_TOPIC", "system/commands"), command_topic: System.get_env("SYSTANT_COMMAND_TOPIC", "systant/#{hostname}/commands"),
publish_interval: String.to_integer(System.get_env("SYSTANT_PUBLISH_INTERVAL", "30000")) publish_interval: String.to_integer(System.get_env("SYSTANT_PUBLISH_INTERVAL", "30000"))

View File

@ -40,13 +40,13 @@ in
statsTopic = mkOption { statsTopic = mkOption {
type = types.str; type = types.str;
default = "system/stats"; default = "systant/${config.networking.hostName}/stats";
description = "MQTT topic for publishing stats"; description = "MQTT topic for publishing stats";
}; };
commandTopic = mkOption { commandTopic = mkOption {
type = types.str; type = types.str;
default = "system/commands"; default = "systant/${config.networking.hostName}/commands";
description = "MQTT topic for receiving commands"; description = "MQTT topic for receiving commands";
}; };
@ -64,13 +64,13 @@ in
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
environment = { environment = {
SYSTEM_STATS_MQTT_HOST = cfg.mqttHost; SYSTANT_MQTT_HOST = cfg.mqttHost;
SYSTEM_STATS_MQTT_PORT = toString cfg.mqttPort; SYSTANT_MQTT_PORT = toString cfg.mqttPort;
SYSTEM_STATS_MQTT_USERNAME = mkIf (cfg.mqttUsername != null) cfg.mqttUsername; SYSTANT_MQTT_USERNAME = mkIf (cfg.mqttUsername != null) cfg.mqttUsername;
SYSTEM_STATS_MQTT_PASSWORD = mkIf (cfg.mqttPassword != null) cfg.mqttPassword; SYSTANT_MQTT_PASSWORD = mkIf (cfg.mqttPassword != null) cfg.mqttPassword;
SYSTEM_STATS_STATS_TOPIC = cfg.statsTopic; SYSTANT_STATS_TOPIC = cfg.statsTopic;
SYSTEM_STATS_COMMAND_TOPIC = cfg.commandTopic; SYSTANT_COMMAND_TOPIC = cfg.commandTopic;
SYSTEM_STATS_PUBLISH_INTERVAL = toString cfg.publishInterval; SYSTANT_PUBLISH_INTERVAL = toString cfg.publishInterval;
# Override RELEASE_COOKIE to bypass file reading # Override RELEASE_COOKIE to bypass file reading
RELEASE_COOKIE = "systant-bypass-cookie"; RELEASE_COOKIE = "systant-bypass-cookie";
}; };

View File

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