- Python 70.8%
- Shell 24.6%
- JavaScript 2.2%
- Dockerfile 1.5%
- Just 0.9%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
All checks were successful
Container / publish (pull_request) Has been skipped
Release Tasmota reconciler chart / chart (pull_request) Successful in 13s
Container / validate (pull_request) Successful in 30s
Container / validate (push) Has been skipped
Container / publish (push) Successful in 56s
|
||
| .forgejo | ||
| charts/tasmota-reconciler | ||
| deploy | ||
| examples | ||
| resources/cosign | ||
| scripts | ||
| src/tasmota_reconciler | ||
| tests | ||
| .gitattributes | ||
| .gitignore | ||
| .python-version | ||
| .sops.yaml | ||
| Containerfile | ||
| justfile | ||
| pyproject.toml | ||
| README.md | ||
| renovate.json | ||
| requirements-dev.lock | ||
| requirements.lock | ||
| uv.lock | ||
Tasmota reconciler
tasmota-reconciler turns selected, stable Tasmota settings into Git-owned
desired state. It uses the upstream
decode-config utility for
version-aware configuration transport and restore, while this project adds:
- a multi-device manifest;
- MQTT credentials from mounted secret files;
- subset-aware drift detection;
- explicit
plan,apply, and encrypted.dmpbackup operations; - bounded retries for transient or truncated device observations;
- reboot-aware post-apply verification;
- native Tasmota MQTT command fallback when a restore fails to converge; and
- JSON-line output suitable for Kubernetes Jobs and log monitoring.
Runtime values such as relay state, uptime, signal strength, and accumulated energy are intentionally outside the reconciler unless explicitly present in a device's desired JSON. Secret-like fields are rejected from desired-state files; credentials belong in mounted SOPS-managed secret files.
Configuration
See examples/manifest.json and
examples/devices/winterstern.json.
Relative desiredFile paths are resolved from the manifest directory.
The broker URL must not contain credentials. If authentication is required,
use usernameFile and passwordFile. devicePasswordFile is the password
stored in the Tasmota device and is required by decode-config when its MQTT
broker identity uses a different password.
Individual device entries may override the global deviceMqtt identity with
mqttUsername and mqttPasswordFile. Both fields must be supplied together;
this allows each device to have a separately revocable broker credential.
Optional top-level wifi and deviceMqtt blocks inject their passwords only
into a short-lived restore file. This lets Git own the SSID and device MQTT
identity without putting either password in the manifest, desired JSON, drift
output, command arguments, or logs. Password values are intentionally not
verified because decode-config hides them when observing a device.
Commands
tasmota-reconciler --manifest /config/manifest.json plan
tasmota-reconciler --manifest /config/manifest.json apply
tasmota-reconciler --manifest /config/manifest.json backup \
--output-directory /backups
plan returns:
0when all selected devices are converged;2when drift exists; and1for configuration or communication errors.
apply reads current state, restores only devices with drift, and retries
verification while the device reboots. If the restore errors or persistent
drift remains, the reconciler translates the remaining supported fields into
native Tasmota commands, submits them with Backlog, and verifies the device a
second time. It still fails unless every Git-owned field converges.
The fallback covers the Wi-Fi and MQTT transition fields, energy calibration,
resolution, template/module, naming, topic, and telemetry fields used by the
managed fleet. It rejects values that cannot be represented safely in a
Backlog command instead of sending an ambiguous command.
Backups use Tasmota's encrypted .dmp format. They should be written to a
persistent volume and included in the cluster backup policy.
Development
The repository uses the managed Nix Python environment:
direnv exec . uv sync --frozen
direnv exec . uv run ruff check .
direnv exec . uv run pytest
Image publication
Pull requests build the complete image, execute tests and linting inside the build, and inspect the CLI without publishing. Merges and weekly scheduled runs publish signed images with SPDX SBOM and SLSA provenance to:
registry.ancofazi.de/homelab/tasmota-reconciler:<decode-config-version>-<run>
This repository owns the complete Tasmota Reconciler deployment in deploy/,
including device desired state and its SOPS-encrypted credentials. The chart's
image pin is in charts/tasmota-reconciler/values.yaml.
Chart tags publish the chart only; Flux reads this repository's deployment
tree after the separately reviewed source cutover in Andreas/homelab.
CronJob chart
charts/tasmota-reconciler packages only the reconciler CronJob. Its default
render matches the live Helm-owned CronJob, including the image tag and digest.
The chart references the ServiceAccount, ConfigMap and Secret defined in
deploy/; the chart values can override those references and the CronJob name.
Until the separate homelab source cutover, Flux still applies the identical
manifests from homelab.
The chart workflow validates pull requests and publishes an immutable OCI
chart only for a matching chart-v<Chart.yaml version> tag on main. It uses
the digest-pinned shared app-release action in publish-only mode. A tag does
not deploy the chart by itself; Renovate proposes chart-version updates to
deploy/helmrelease.yaml for review.
The live tasmota-reconciler CronJob already belongs to the app-owned Helm
chart. Its initial handoff used a distinct suspended canary, then suspended
and pruned the raw CronJob before installing and resuming the original name
under Helm. The first scheduled Helm-owned Job completed successfully.