Files
shelly-exporter/docs/operations.md
T
lostakj 9db7aa2560
Build Docker image on push / docker (push) Successful in 22s
Initila commit
2026-08-18 00:46:59 +02:00

210 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Operations and troubleshooting
## HTTP endpoints
| Path | Purpose | Device access |
| --- | --- | --- |
| `/metrics` | Prometheus/OpenMetrics output. Each request triggers collection from all configured devices. | yes |
| `/-/healthy` | Exporter process health; returns HTTP 200 and `OK`. | no |
The health endpoint proves that the HTTP process can respond. It deliberately does not contact Shelly devices. Use `shelly_up` to monitor individual device availability.
## Native deployment
```sh
go build -trimpath -o shelly-exporter .
./shelly-exporter -config config.yaml
```
The process handles `SIGINT` and `SIGTERM`, stops accepting requests, and gives the HTTP server up to 10 seconds to shut down.
Example systemd unit:
```ini
[Unit]
Description=Shelly Prometheus Exporter
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=shelly-exporter
Group=shelly-exporter
ExecStart=/usr/local/bin/shelly-exporter -config /etc/shelly-exporter/config.yaml
Restart=on-failure
RestartSec=5s
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadOnlyPaths=/etc/shelly-exporter/config.yaml
[Install]
WantedBy=multi-user.target
```
Ensure the service account can read the configuration and reach every device over the network.
## Docker deployment
Build the image:
```sh
docker build --rm -t shelly-exporter:latest .
```
Run it with a read-only configuration mount:
```sh
docker run --rm -d \
--name shelly-exporter \
-p 9090:9090 \
-v "$PWD/config.yaml:/opt/shelly-exporter/config.yaml:ro" \
shelly-exporter:latest
```
The image runs as an unprivileged user and includes a health check against `/-/healthy`. The configuration bundled in the image is only an example; mount the actual configuration for production.
## Prometheus setup
```yaml
scrape_configs:
- job_name: shelly
scrape_interval: 30s
scrape_timeout: 15s
static_configs:
- targets:
- shelly-exporter:9090
```
Keep the Prometheus `scrape_timeout` greater than `shelly.timeoutSeconds` plus a small allowance for metric encoding and network latency. Devices are queried concurrently, so the worst normal collection duration is close to the slowest device request rather than the sum of all requests.
The exporter contacts every device for every Prometheus scrape. Very short scrape intervals add unnecessary work to low-power hardware. A 1560 second interval is a reasonable starting point for powered devices.
### Battery-powered sensors
Shelly Gen1 H&T, Flood, Door/Window, Button1, and similar battery devices sleep to conserve power. They may be unavailable during most scheduled scrapes, causing expected `shelly_up == 0` results. Consider MQTT or event callbacks when continuous collection from these products is required.
## Useful PromQL
Current power per standard meter:
```promql
shelly_meter_power_watts
```
Consumed energy over 24 hours in kWh:
```promql
increase(shelly_meter_energy_watt_hours_total[24h]) / 1000
```
EM/3EM imported and exported energy over 24 hours in kWh:
```promql
increase(shelly_emeter_energy_watt_hours_total[24h]) / 1000
```
```promql
increase(shelly_emeter_returned_energy_watt_hours_total[24h]) / 1000
```
Devices currently unavailable:
```promql
shelly_up == 0
```
Free RAM percentage where both fields are reported:
```promql
100 * shelly_ram_free_bytes / shelly_ram_size_bytes
```
## Example alert rules
Adjust durations and exclude sleeping products according to the installation.
```yaml
groups:
- name: shelly
rules:
- alert: ShellyDeviceDown
expr: shelly_up == 0
for: 5m
labels:
severity: warning
annotations:
summary: "Shelly {{ $labels.device }} is unreachable"
- alert: ShellyDeviceOvertemperature
expr: shelly_overtemperature == 1
for: 1m
labels:
severity: critical
annotations:
summary: "Shelly {{ $labels.device }} reports overtemperature"
- alert: ShellyWeakWiFi
expr: shelly_wifi_rssi_dbm < -80
for: 10m
labels:
severity: warning
annotations:
summary: "Shelly {{ $labels.device }} has weak Wi-Fi signal"
```
## Security
- Store `config.yaml` outside source control and restrict it to the exporter account, for example with mode `0600` on Linux.
- Prefer a trusted management network or HTTPS because Basic Authentication does not encrypt credentials over plain HTTP.
- The exporter endpoints themselves do not require authentication. Restrict port 9090 with firewall, reverse proxy, or network policy when necessary.
- Device passwords are not metric labels, but request failures can include the target URL in logs. Do not put credentials in URL user-info; use `username` and `password` fields.
- HTTPS certificate verification is enabled and cannot be bypassed by configuration.
## Troubleshooting
### Exporter does not start
Read the fatal error first. Configuration loading is strict, and common causes are:
- an unknown or misspelled YAML key;
- a hostname in `host` instead of a literal IP address;
- an empty device list;
- duplicate device names;
- an unsupported product identifier;
- a URL missing `http://` or `https://`.
Increase `logLevel` to `5` or `6` only after configuration validation succeeds.
### `shelly_up` is zero
Test the same request from the exporter host or container network:
```sh
curl -v -u admin:password http://192.168.0.30/status
```
Check routing, firewall rules, device power, credentials, and the configured timeout. HTTP errors and JSON decoding failures increment `shelly_scrape_errors_total`.
### HTTP 401 Unauthorized
Confirm that the configured username and password match the device. The exporter uses HTTP Basic Authentication. A device configured for a different authentication scheme will not work with the current client.
### TLS certificate error
The device certificate must be trusted by the exporter operating system or container. Use a certificate issued by a trusted internal CA and add that CA to the runtime trust store.
### Device is up but an expected metric is absent
Metrics are intentionally conditional. Capture the raw `/status` JSON and verify that the corresponding field is present. Firmware versions and device modes can change response blocks—for example, Shelly 2.5 reports either relays or rollers depending on its operating mode.
For an unlisted Gen1 device, try `product: gen1`. If the field exists but is not modeled, follow the [extension guide](architecture.md#extending-the-gen1-schema).
### Scrapes time out
- Increase `shelly.timeoutSeconds` and Prometheus `scrape_timeout` together.
- Verify Wi-Fi RSSI and packet loss.
- Avoid overly short scrape intervals.
- Check whether a configured battery device is normally asleep.