feat: push metrics from smart plugs using mqtt and from truenas using graphite

Changed files
+173 -6
butane
configs
+66
butane/fcos.yml.tftpl
···
# all keys on machine, reaching the limit.
MaxAuthTries 10
+
# Firewall configuration
+
- path: /etc/sysconfig/nftables.conf
+
overwrite: true
+
mode: 0644
+
contents:
+
inline: |
+
include "/etc/nftables/main.nft"
+
+
- path: /etc/nftables/main.nft
+
overwrite: true
+
mode: 0644
+
contents:
+
inline: |
+
#!/usr/sbin/nft -f
+
+
flush ruleset
+
+
table inet filter {
+
chain input {
+
type filter hook input priority filter; policy drop;
+
+
# allow established/related connections
+
ct state {established, related} accept
+
+
# early drop of invalid connections
+
ct state invalid drop
+
+
# allow from loopback
+
iifname lo accept
+
+
# allow icmp
+
ip protocol icmp accept
+
ip6 nexthdr icmpv6 counter accept
+
+
# allow ssh
+
tcp dport ssh accept
+
+
# allow http and https
+
tcp dport 8080 accept
+
tcp dport 8443 accept
+
+
# allow truenas to report metrics using graphite
+
ip saddr 192.168.100.3 tcp dport 2003 accept
+
ip saddr 192.168.100.3 udp dport 2003 accept
+
+
# allow plugs to access mqtt broker
+
ip saddr 192.168.100.1 tcp dport 1883 accept
+
}
+
+
chain forward {
+
type filter hook forward priority filter; policy drop;
+
+
ct state {established, related} accept
+
ct state invalid drop
+
+
ct status dnat accept
+
}
+
+
chain output {
+
type filter hook output priority 0; policy accept;
+
}
+
}
+
systemd:
units:
- name: install-additional-software.service
···
[Install]
WantedBy=remote-fs.target
+
+
- name: nftables.service
+
enabled: true
kernel_arguments:
should_exist:
+25 -4
configs/alloy/config.alloy
···
discovery.relabel "docker" {
targets = discovery.docker.fcos.targets
-
+
rule {
action = "labelmap"
regex = "^__meta_docker_(.*)$"
···
loki.source.docker "podman" {
host = "unix:///var/run/docker.sock"
targets = discovery.docker.fcos.targets
-
labels = { "source_name" = "podman" }
+
labels = { "source_name" = "podman" }
forward_to = [loki.process.copy_msg.receiver]
relabel_rules = discovery.relabel.docker.rules
}
···
}
}
-
// Just Traefik for now
prometheus.scrape "scrape_metrics" {
-
targets = [{ __address__ = "traefik:8082" }]
+
targets = [{ __address__ = "traefik:8082" }, {__address__ = "rmqtt:6060", __metrics_path__ = "/api/v1/metrics/prometheus" }]
forward_to = [prometheus.remote_write.victoria_metrics.receiver]
scrape_interval = "10s"
}
···
url = "http://victoria:8428/prometheus/api/v1/write"
}
}
+
+
// Receive metrics from MQTT
+
otelcol.receiver.otlp "telegraf" {
+
http {}
+
grpc {}
+
+
output {
+
metrics = [otelcol.processor.batch.telegraf.input]
+
}
+
}
+
+
otelcol.processor.batch "telegraf" {
+
output {
+
metrics = [otelcol.exporter.otlphttp.victoria_metrics.input]
+
}
+
}
+
+
otelcol.exporter.otlphttp "victoria_metrics" {
+
client {
+
endpoint = "http://victoria:8428/opentelemetry"
+
}
+
}
+4 -1
configs/containers/systemd/pods/victoria.pod
···
[Pod]
PodName=victoria
Network=victoria.network
-
Network=reverse-proxy.network
+
Network=reverse-proxy.network
+
# Publish Graphite collector ports
+
PublishPort=2003:2003/tcp
+
PublishPort=2003:2003/udp
+27
configs/containers/systemd/rmqtt.container.tftpl
···
+
[Unit]
+
Description=RMQTT Broker Quadlet
+
+
[Container]
+
Image=docker.io/rmqtt/rmqtt:latest
+
AutoUpdate=registry
+
ContainerName=rmqtt
+
+
User=1000:1000
+
UserNS=keep-id:uid=1000,gid=1000
+
+
Label="glance.parent=victoria-metrics"
+
Label="glance.name=MQTT Broker"
+
Label="glance.hide=false"
+
+
Volume=/var/mnt/docker/app_data/rmqtt/logs:/var/log/rmqtt:Z
+
+
Network=reverse-proxy.network
+
PublishPort=1883:1883
+
PublishPort=6060:6060
+
+
[Service]
+
TimeoutStartSec=900
+
Restart=always
+
+
[Install]
+
WantedBy=multi-user.target default.target
+26
configs/containers/systemd/telegraf.container.tftpl
···
+
[Unit]
+
Description=Telegraf Agent Quadlet
+
+
[Container]
+
Image=docker.io/telegraf:alpine
+
AutoUpdate=registry
+
ContainerName=telegraf
+
HostName=telegraf
+
+
User=1000:1000
+
UserNS=keep-id:uid=1000,gid=1000
+
+
Label="glance.parent=victoria-metrics"
+
Label="glance.name=Telegraf Agent"
+
Label="glance.hide=false"
+
+
Volume=%E/telegraf/telegraf.conf:/etc/telegraf/telegraf.conf:Z
+
+
Network=reverse-proxy.network
+
+
[Service]
+
TimeoutStartSec=900
+
Restart=always
+
+
[Install]
+
WantedBy=multi-user.target default.target
+4 -1
configs/containers/systemd/victoria/victoria-metrics.container.tftpl
···
User=1000:1000
UserNS=keep-id:uid=1000,gid=1000
+
Label="glance.id=victoria-metrics"
Label="glance.name=VictoriaMetrics"
Label="glance.icon=di:victoriametrics-light"
Label="glance.url=https://metrics.${base_domain}"
Label="glance.description=Metrics Storage"
Label="glance.hide=false"
+
+
Exec="--graphiteListenAddr=:2003"
Volume=/var/mnt/observability/metrics:/victoria-metrics-data:Z
···
Restart=always
[Install]
-
WantedBy=multi-user.target default.target
+
WantedBy=multi-user.target default.target
+21
configs/telegraf/telegraf.conf
···
+
[[inputs.mqtt_consumer]]
+
servers = ["tcp://rmqtt:1883"]
+
topics = [
+
"shelly/+/status/+"
+
]
+
+
data_format = "json_v2"
+
[[inputs.mqtt_consumer.json_v2]]
+
[[inputs.mqtt_consumer.json_v2.field]]
+
path = "apower"
+
[[inputs.mqtt_consumer.json_v2.field]]
+
path = "voltage"
+
[[inputs.mqtt_consumer.json_v2.field]]
+
path = "freq"
+
[[inputs.mqtt_consumer.json_v2.field]]
+
path = "current"
+
[[inputs.mqtt_consumer.json_v2.field]]
+
path = "temperature.tC"
+
+
[[outputs.opentelemetry]]
+
service_address = "grafana-alloy:4317"