Add Home Assistant MQTT auto-discovery integration
- Implement `Systant.HaDiscovery` module for automatic device registration - Add comprehensive sensor discovery: CPU, memory, GPU, disk, network, temperature - Update MQTT client to publish discovery messages on startup - Add HomeAssistant configuration section to systant.toml - Create example configuration file with localhost MQTT broker - Update CLAUDE.md with complete HA integration documentation - Add mosquitto to development dependencies for testing 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
3399947eb0
commit
4ab0972870
34
CLAUDE.md
34
CLAUDE.md
@ -187,11 +187,35 @@ mosquitto_pub -t "systant/hostname/commands" -m '{"command":"restart","params":[
|
|||||||
mosquitto_sub -t "systant/+/responses"
|
mosquitto_sub -t "systant/+/responses"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Phase 3: Home Assistant Integration
|
### Phase 3: Home Assistant Integration (Completed)
|
||||||
- Custom MQTT integration following Home Assistant patterns
|
- ✅ **MQTT Auto-Discovery**: `server/lib/systant/ha_discovery.ex` - Publishes HA discovery configurations for automatic device registration
|
||||||
- Auto-discovery of systant hosts via MQTT discovery protocol
|
- ✅ **Device Registration**: Creates unified "Systant {hostname}" device in Home Assistant with comprehensive sensor suite
|
||||||
- Create entities for metrics (sensors) and commands (buttons/services)
|
- ✅ **Sensor Auto-Discovery**: CPU load averages, memory usage, system uptime, temperatures, GPU metrics, disk usage, network stats
|
||||||
- Dashboard cards and automation support
|
- ✅ **Configuration Integration**: TOML-based enable/disable with `homeassistant.discovery_enabled` setting
|
||||||
|
- ✅ **Value Templates**: Proper JSON path extraction for nested metrics data with error handling
|
||||||
|
- ✅ **Real-time Updates**: Seamless integration with existing MQTT stats publishing - no additional topics needed
|
||||||
|
|
||||||
|
#### Home Assistant Integration Features
|
||||||
|
- **Automatic Discovery**: No custom integration required - uses standard MQTT discovery protocol
|
||||||
|
- **Device Grouping**: All sensors grouped under single "Systant {hostname}" device for clean organization
|
||||||
|
- **Comprehensive Metrics**: CPU, memory, disk, GPU (NVIDIA/AMD), network, temperature, and system sensors
|
||||||
|
- **Configuration Control**: Enable/disable discovery via `systant.toml` configuration
|
||||||
|
- **Template Flexibility**: Advanced Jinja2 templates handle optional/missing data gracefully
|
||||||
|
- **Topic Structure**: Discovery on `homeassistant/#`, stats remain on `systant/{hostname}/stats`
|
||||||
|
|
||||||
|
#### Setup Instructions
|
||||||
|
1. **Configure MQTT Discovery**: Set `homeassistant.discovery_enabled = true` in `systant.toml`
|
||||||
|
2. **Start Systant**: Discovery messages published automatically on startup (1s after MQTT connection)
|
||||||
|
3. **Check Home Assistant**: Device and sensors appear automatically in MQTT integration
|
||||||
|
4. **Verify Metrics**: All sensors should show current values within 30 seconds
|
||||||
|
|
||||||
|
#### Available Sensors
|
||||||
|
- **CPU**: Load averages (1m, 5m, 15m), temperature
|
||||||
|
- **Memory**: Usage percentage, used/total in GB
|
||||||
|
- **Disk**: Root and home filesystem usage percentages
|
||||||
|
- **GPU**: NVIDIA/AMD utilization, temperature, memory usage
|
||||||
|
- **Network**: RX/TX bytes for primary interface
|
||||||
|
- **System**: Uptime in hours, kernel version, online status
|
||||||
|
|
||||||
### Future Plans
|
### Future Plans
|
||||||
- Multi-host deployment for comprehensive system monitoring
|
- Multi-host deployment for comprehensive system monitoring
|
||||||
|
|||||||
@ -45,6 +45,9 @@
|
|||||||
|
|
||||||
# Database for development
|
# Database for development
|
||||||
postgresql
|
postgresql
|
||||||
|
|
||||||
|
# Mosquito for MQTT support
|
||||||
|
mosquitto
|
||||||
];
|
];
|
||||||
|
|
||||||
shellHook = ''
|
shellHook = ''
|
||||||
|
|||||||
@ -70,6 +70,10 @@ defmodule Systant.Config do
|
|||||||
"password" => "",
|
"password" => "",
|
||||||
"qos" => 0
|
"qos" => 0
|
||||||
},
|
},
|
||||||
|
"homeassistant" => %{
|
||||||
|
"discovery_enabled" => true,
|
||||||
|
"discovery_prefix" => "homeassistant"
|
||||||
|
},
|
||||||
"logging" => %{
|
"logging" => %{
|
||||||
"level" => "info",
|
"level" => "info",
|
||||||
"log_config_changes" => true,
|
"log_config_changes" => true,
|
||||||
|
|||||||
182
server/lib/systant/ha_discovery.ex
Normal file
182
server/lib/systant/ha_discovery.ex
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
defmodule Systant.HaDiscovery do
|
||||||
|
@moduledoc """
|
||||||
|
Home Assistant MQTT Discovery integration for Systant.
|
||||||
|
|
||||||
|
Publishes device and entity discovery configurations to Home Assistant
|
||||||
|
via MQTT following the HA discovery protocol.
|
||||||
|
|
||||||
|
Discovery topic format: homeassistant/<component>/<node_id>/<object_id>/config
|
||||||
|
"""
|
||||||
|
|
||||||
|
require Logger
|
||||||
|
|
||||||
|
@manufacturer "Systant"
|
||||||
|
@model "System Monitor"
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Publish all discovery configurations for a host
|
||||||
|
"""
|
||||||
|
def publish_discovery(client_pid, hostname, config \\ nil) do
|
||||||
|
app_config = config || Systant.Config.load_config()
|
||||||
|
ha_config = Systant.Config.get(app_config, ["homeassistant"]) || %{}
|
||||||
|
|
||||||
|
if ha_config["discovery_enabled"] != false do
|
||||||
|
discovery_prefix = ha_config["discovery_prefix"] || "homeassistant"
|
||||||
|
device_config = build_device_config(hostname)
|
||||||
|
|
||||||
|
# Publish device discovery first
|
||||||
|
publish_device_discovery(client_pid, hostname, device_config, discovery_prefix)
|
||||||
|
|
||||||
|
# Publish sensor discoveries
|
||||||
|
publish_sensor_discoveries(client_pid, hostname, device_config, discovery_prefix)
|
||||||
|
|
||||||
|
Logger.info("Published Home Assistant discovery for #{hostname}")
|
||||||
|
else
|
||||||
|
Logger.info("Home Assistant discovery disabled in configuration")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Remove all discovery configurations for a host
|
||||||
|
"""
|
||||||
|
def remove_discovery(client_pid, hostname, config \\ nil) do
|
||||||
|
app_config = config || Systant.Config.load_config()
|
||||||
|
ha_config = Systant.Config.get(app_config, ["homeassistant"]) || %{}
|
||||||
|
discovery_prefix = ha_config["discovery_prefix"] || "homeassistant"
|
||||||
|
|
||||||
|
# Remove by publishing empty payloads to discovery topics
|
||||||
|
sensors = get_sensor_definitions(hostname)
|
||||||
|
|
||||||
|
Enum.each(sensors, fn {component, object_id, _config} ->
|
||||||
|
topic = "#{discovery_prefix}/#{component}/#{hostname}/#{object_id}/config"
|
||||||
|
Tortoise.publish(client_pid, topic, "", retain: true)
|
||||||
|
end)
|
||||||
|
|
||||||
|
Logger.info("Removed Home Assistant discovery for #{hostname}")
|
||||||
|
end
|
||||||
|
|
||||||
|
# Private functions
|
||||||
|
|
||||||
|
defp publish_device_discovery(client_pid, hostname, device_config, discovery_prefix) do
|
||||||
|
# Use device-based discovery for multiple components
|
||||||
|
components_config = %{
|
||||||
|
device: device_config,
|
||||||
|
components: build_all_components(hostname, device_config)
|
||||||
|
}
|
||||||
|
|
||||||
|
topic = "#{discovery_prefix}/device/#{hostname}/config"
|
||||||
|
payload = Jason.encode!(components_config)
|
||||||
|
|
||||||
|
Tortoise.publish(client_pid, topic, payload, retain: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp publish_sensor_discoveries(client_pid, hostname, device_config, discovery_prefix) do
|
||||||
|
sensors = get_sensor_definitions(hostname)
|
||||||
|
|
||||||
|
Enum.each(sensors, fn {component, object_id, config} ->
|
||||||
|
full_config = Map.merge(config, %{device: device_config})
|
||||||
|
topic = "#{discovery_prefix}/#{component}/#{hostname}/#{object_id}/config"
|
||||||
|
payload = Jason.encode!(full_config)
|
||||||
|
|
||||||
|
Tortoise.publish(client_pid, topic, payload, retain: true)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp build_device_config(hostname) do
|
||||||
|
%{
|
||||||
|
identifiers: ["systant_#{hostname}"],
|
||||||
|
name: "Systant #{hostname}",
|
||||||
|
manufacturer: @manufacturer,
|
||||||
|
model: @model,
|
||||||
|
sw_version: Application.spec(:systant, :vsn) |> to_string()
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp build_all_components(hostname, device_config) do
|
||||||
|
get_sensor_definitions(hostname)
|
||||||
|
|> Enum.map(fn {_component, object_id, config} ->
|
||||||
|
Map.merge(config, %{device: device_config})
|
||||||
|
|> Map.put(:object_id, object_id)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp get_sensor_definitions(hostname) do
|
||||||
|
base_topic = "systant/#{hostname}/stats"
|
||||||
|
|
||||||
|
[
|
||||||
|
# CPU Sensors
|
||||||
|
{"sensor", "cpu_load_1m", build_sensor_config("CPU Load 1m", "#{base_topic}", "cpu.avg1", "load", "mdi:speedometer")},
|
||||||
|
{"sensor", "cpu_load_5m", build_sensor_config("CPU Load 5m", "#{base_topic}", "cpu.avg5", "load", "mdi:speedometer")},
|
||||||
|
{"sensor", "cpu_load_15m", build_sensor_config("CPU Load 15m", "#{base_topic}", "cpu.avg15", "load", "mdi:speedometer")},
|
||||||
|
|
||||||
|
# Memory Sensors
|
||||||
|
{"sensor", "memory_used_percent", build_sensor_config("Memory Used", "#{base_topic}", "memory.used_percent", "%", "mdi:memory")},
|
||||||
|
{"sensor", "memory_used_gb", build_sensor_config("Memory Used GB", "#{base_topic}", "memory.used_kb", "GB", "mdi:memory", "{{ (value_json.memory.used_kb | float / 1024 / 1024) | round(2) }}")},
|
||||||
|
{"sensor", "memory_total_gb", build_sensor_config("Memory Total GB", "#{base_topic}", "memory.total_kb", "GB", "mdi:memory", "{{ (value_json.memory.total_kb | float / 1024 / 1024) | round(2) }}")},
|
||||||
|
|
||||||
|
# System Sensors
|
||||||
|
{"sensor", "uptime_hours", build_sensor_config("Uptime", "#{base_topic}", "system.uptime_seconds", "h", "mdi:clock-outline", "{{ (value_json.system.uptime_seconds | float / 3600) | round(1) }}")},
|
||||||
|
{"sensor", "kernel_version", build_sensor_config("Kernel Version", "#{base_topic}", "system.kernel_version", nil, "mdi:linux")},
|
||||||
|
|
||||||
|
# Temperature Sensors
|
||||||
|
{"sensor", "cpu_temperature", build_sensor_config("CPU Temperature", "#{base_topic}", "temperature.cpu", "°C", "mdi:thermometer")},
|
||||||
|
|
||||||
|
# GPU Sensors - NVIDIA
|
||||||
|
{"sensor", "gpu_nvidia_utilization", build_sensor_config("NVIDIA GPU Utilization", "#{base_topic}", "gpu.nvidia[0].utilization_percent", "%", "mdi:expansion-card", "{{ value_json.gpu.nvidia[0].utilization_percent if value_json.gpu.nvidia and value_json.gpu.nvidia|length > 0 else 0 }}")},
|
||||||
|
{"sensor", "gpu_nvidia_temperature", build_sensor_config("NVIDIA GPU Temperature", "#{base_topic}", "gpu.nvidia[0].temperature_c", "°C", "mdi:thermometer", "{{ value_json.gpu.nvidia[0].temperature_c if value_json.gpu.nvidia and value_json.gpu.nvidia|length > 0 else none }}")},
|
||||||
|
{"sensor", "gpu_nvidia_memory", build_sensor_config("NVIDIA GPU Memory", "#{base_topic}", "gpu.nvidia[0].memory_used_mb", "MB", "mdi:memory", "{{ value_json.gpu.nvidia[0].memory_used_mb if value_json.gpu.nvidia and value_json.gpu.nvidia|length > 0 else none }}")},
|
||||||
|
|
||||||
|
# GPU Sensors - AMD
|
||||||
|
{"sensor", "gpu_amd_utilization", build_sensor_config("AMD GPU Utilization", "#{base_topic}", "gpu.amd[0].utilization_percent", "%", "mdi:expansion-card", "{{ value_json.gpu.amd[0].utilization_percent if value_json.gpu.amd and value_json.gpu.amd|length > 0 else 0 }}")},
|
||||||
|
{"sensor", "gpu_amd_temperature", build_sensor_config("AMD GPU Temperature", "#{base_topic}", "gpu.amd[0].temperature_c", "°C", "mdi:thermometer", "{{ value_json.gpu.amd[0].temperature_c if value_json.gpu.amd and value_json.gpu.amd|length > 0 else none }}")},
|
||||||
|
|
||||||
|
# Disk Sensors - Main filesystem usage
|
||||||
|
{"sensor", "disk_root_usage", build_sensor_config("Root Disk Usage", "#{base_topic}", "disk.disks", "%", "mdi:harddisk", "{{ (value_json.disk.disks | selectattr('mounted_on', 'equalto', '/') | list | first).use_percent if value_json.disk.disks else 0 }}")},
|
||||||
|
{"sensor", "disk_home_usage", build_sensor_config("Home Disk Usage", "#{base_topic}", "disk.disks", "%", "mdi:harddisk", "{{ (value_json.disk.disks | selectattr('mounted_on', 'equalto', '/home') | list | first).use_percent if (value_json.disk.disks | selectattr('mounted_on', 'equalto', '/home') | list) else 0 }}")},
|
||||||
|
|
||||||
|
# Network Sensors - Primary interface
|
||||||
|
{"sensor", "network_rx_bytes", build_sensor_config("Network RX Bytes", "#{base_topic}", "network", "bytes", "mdi:download-network", "{{ value_json.network[0].rx_bytes if value_json.network and value_json.network|length > 0 else 0 }}")},
|
||||||
|
{"sensor", "network_tx_bytes", build_sensor_config("Network TX Bytes", "#{base_topic}", "network", "bytes", "mdi:upload-network", "{{ value_json.network[0].tx_bytes if value_json.network and value_json.network|length > 0 else 0 }}")},
|
||||||
|
|
||||||
|
# Binary Sensors for status
|
||||||
|
{"binary_sensor", "system_online", build_binary_sensor_config("System Online", "#{base_topic}", "mdi:server", "connectivity")}
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
defp build_sensor_config(name, state_topic, value_template_path, unit, icon, custom_template \\ nil) do
|
||||||
|
base_config = %{
|
||||||
|
name: name,
|
||||||
|
state_topic: state_topic,
|
||||||
|
value_template: custom_template || "{{ value_json.#{value_template_path} }}",
|
||||||
|
icon: icon,
|
||||||
|
unique_id: "systant_#{String.replace(state_topic, "/", "_")}_#{String.replace(value_template_path, ".", "_")}",
|
||||||
|
origin: %{
|
||||||
|
name: "Systant",
|
||||||
|
sw_version: Application.spec(:systant, :vsn) |> to_string(),
|
||||||
|
support_url: "https://github.com/user/systant"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if unit do
|
||||||
|
Map.put(base_config, :unit_of_measurement, unit)
|
||||||
|
else
|
||||||
|
base_config
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp build_binary_sensor_config(name, state_topic, icon, device_class) do
|
||||||
|
%{
|
||||||
|
name: name,
|
||||||
|
state_topic: state_topic,
|
||||||
|
value_template: "{{ 'ON' if value_json.timestamp else 'OFF' }}",
|
||||||
|
device_class: device_class,
|
||||||
|
icon: icon,
|
||||||
|
unique_id: "systant_#{String.replace(state_topic, "/", "_")}_online",
|
||||||
|
origin: %{
|
||||||
|
name: "Systant",
|
||||||
|
sw_version: Application.spec(:systant, :vsn) |> to_string(),
|
||||||
|
support_url: "https://github.com/user/systant"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -41,6 +41,10 @@ defmodule Systant.MqttClient do
|
|||||||
Process.send_after(self(), :publish_startup_stats, startup_delay)
|
Process.send_after(self(), :publish_startup_stats, startup_delay)
|
||||||
Logger.info("Will publish initial stats in #{startup_delay}ms")
|
Logger.info("Will publish initial stats in #{startup_delay}ms")
|
||||||
|
|
||||||
|
# Publish Home Assistant discovery after MQTT connection
|
||||||
|
Process.send_after(self(), :publish_ha_discovery, 1000)
|
||||||
|
Logger.info("Will publish HA discovery in 1000ms")
|
||||||
|
|
||||||
schedule_stats_publish(mqtt_config.publish_interval)
|
schedule_stats_publish(mqtt_config.publish_interval)
|
||||||
{:ok, state_config}
|
{:ok, state_config}
|
||||||
|
|
||||||
@ -50,6 +54,14 @@ defmodule Systant.MqttClient do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def handle_info(:publish_ha_discovery, state) do
|
||||||
|
Logger.info("Publishing Home Assistant discovery configuration")
|
||||||
|
# Get hostname from system metrics (reuse existing logic)
|
||||||
|
stats = Systant.SystemMetrics.collect_metrics(state.app_config)
|
||||||
|
Systant.HaDiscovery.publish_discovery(state.mqtt_config.client_id, stats.hostname, state.app_config)
|
||||||
|
{:noreply, state}
|
||||||
|
end
|
||||||
|
|
||||||
def handle_info(:publish_startup_stats, state) do
|
def handle_info(:publish_startup_stats, state) do
|
||||||
Logger.info("Publishing initial system metrics")
|
Logger.info("Publishing initial system metrics")
|
||||||
publish_stats(state.app_config, state.mqtt_config)
|
publish_stats(state.app_config, state.mqtt_config)
|
||||||
|
|||||||
@ -88,6 +88,11 @@ password = ""
|
|||||||
# QoS level (0, 1, or 2)
|
# QoS level (0, 1, or 2)
|
||||||
qos = 0
|
qos = 0
|
||||||
|
|
||||||
|
# Home Assistant MQTT Discovery Configuration
|
||||||
|
[homeassistant]
|
||||||
|
discovery_enabled = true # Enable/disable HA auto-discovery
|
||||||
|
discovery_prefix = "homeassistant" # HA discovery topic prefix
|
||||||
|
|
||||||
[logging]
|
[logging]
|
||||||
# Log level: "debug", "info", "warning", "error"
|
# Log level: "debug", "info", "warning", "error"
|
||||||
level = "info"
|
level = "info"
|
||||||
|
|||||||
108
server/systant.toml.example
Normal file
108
server/systant.toml.example
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
# Systant Configuration Example
|
||||||
|
# Copy to systant.toml and customize for your environment
|
||||||
|
|
||||||
|
[general]
|
||||||
|
enabled_modules = ["cpu", "memory", "disk", "gpu", "network", "temperature", "processes", "system"]
|
||||||
|
collection_interval = 30000 # milliseconds
|
||||||
|
startup_delay = 5000 # milliseconds
|
||||||
|
|
||||||
|
[mqtt]
|
||||||
|
host = "localhost" # MQTT broker hostname/IP
|
||||||
|
port = 1883 # MQTT broker port
|
||||||
|
client_id_prefix = "systant" # Prefix for MQTT client ID
|
||||||
|
username = "" # MQTT username (optional)
|
||||||
|
password = "" # MQTT password (optional)
|
||||||
|
qos = 0 # MQTT QoS level
|
||||||
|
|
||||||
|
# Home Assistant MQTT Discovery Configuration
|
||||||
|
[homeassistant]
|
||||||
|
discovery_enabled = true # Enable/disable HA auto-discovery
|
||||||
|
discovery_prefix = "homeassistant" # HA discovery topic prefix
|
||||||
|
|
||||||
|
[cpu]
|
||||||
|
enabled = true
|
||||||
|
|
||||||
|
[memory]
|
||||||
|
enabled = true
|
||||||
|
show_detailed = true
|
||||||
|
|
||||||
|
[disk]
|
||||||
|
enabled = true
|
||||||
|
include_mounts = [] # Only include these mounts (empty = all)
|
||||||
|
exclude_mounts = ["/snap", "/boot", "/dev", "/sys", "/proc", "/run", "/tmp"]
|
||||||
|
exclude_types = ["tmpfs", "devtmpfs", "squashfs", "overlay"]
|
||||||
|
min_usage_percent = 1 # Minimum usage to report
|
||||||
|
|
||||||
|
[gpu]
|
||||||
|
enabled = true
|
||||||
|
nvidia_enabled = true
|
||||||
|
amd_enabled = true
|
||||||
|
max_gpus = 8
|
||||||
|
|
||||||
|
[network]
|
||||||
|
enabled = true
|
||||||
|
include_interfaces = [] # Only include these interfaces (empty = all)
|
||||||
|
exclude_interfaces = ["lo", "docker0", "br-", "veth", "virbr"]
|
||||||
|
min_bytes_threshold = 1024 # Minimum traffic to report
|
||||||
|
|
||||||
|
[temperature]
|
||||||
|
enabled = true
|
||||||
|
cpu_temp_enabled = true
|
||||||
|
sensors_enabled = true
|
||||||
|
temp_unit = "celsius"
|
||||||
|
|
||||||
|
[processes]
|
||||||
|
enabled = true
|
||||||
|
max_processes = 10
|
||||||
|
sort_by = "cpu" # "cpu" or "memory"
|
||||||
|
min_cpu_percent = 0.0
|
||||||
|
min_memory_percent = 0.0
|
||||||
|
max_command_length = 50
|
||||||
|
|
||||||
|
[system]
|
||||||
|
enabled = true
|
||||||
|
include_uptime = true
|
||||||
|
include_load_average = true
|
||||||
|
include_kernel_version = true
|
||||||
|
include_os_info = true
|
||||||
|
|
||||||
|
[commands]
|
||||||
|
enabled = true
|
||||||
|
timeout_seconds = 30
|
||||||
|
log_executions = true
|
||||||
|
|
||||||
|
# Example commands - customize for your needs
|
||||||
|
[[commands.available]]
|
||||||
|
trigger = "restart"
|
||||||
|
command = "systemctl"
|
||||||
|
allowed_params = ["nginx", "apache2", "docker", "ssh"]
|
||||||
|
description = "Restart system services"
|
||||||
|
|
||||||
|
[[commands.available]]
|
||||||
|
trigger = "info"
|
||||||
|
command = "uname"
|
||||||
|
allowed_params = ["-a"]
|
||||||
|
description = "Show system information"
|
||||||
|
|
||||||
|
[[commands.available]]
|
||||||
|
trigger = "df"
|
||||||
|
command = "df"
|
||||||
|
allowed_params = ["-h", "/", "/home", "/var", "/tmp"]
|
||||||
|
description = "Show disk usage"
|
||||||
|
|
||||||
|
[[commands.available]]
|
||||||
|
trigger = "ps"
|
||||||
|
command = "ps"
|
||||||
|
allowed_params = ["aux", "--sort=-pcpu", "--sort=-pmem"]
|
||||||
|
description = "Show running processes"
|
||||||
|
|
||||||
|
[[commands.available]]
|
||||||
|
trigger = "ping"
|
||||||
|
command = "ping"
|
||||||
|
allowed_params = ["-c", "4", "8.8.8.8", "google.com", "1.1.1.1"]
|
||||||
|
description = "Network connectivity test"
|
||||||
|
|
||||||
|
[logging]
|
||||||
|
level = "info" # debug, info, warn, error
|
||||||
|
log_config_changes = true
|
||||||
|
log_metric_collection = false
|
||||||
Loading…
Reference in New Issue
Block a user