Skip to content

Operations

Everything runs through Task:

brew install go-task/tap/go-task   # macOS
task --list                        # all tasks
task help                          # detailed help

Task namespaces (taskfiles/*.yml, included from the root Taskfile.yml):

Namespace Purpose
provision:* Device provisioning (provision-device.sh, batch-provision.sh)
credentials:* Tunnel credential export
mqtt:* MQTT CA + client certificate lifecycle
sync:* Push config/certs to a device
ansible:* Deploy, health-check, restart, cert renewal
validate:* Validate deployment/infrastructure
workflows:* Composite end-to-end flows (setup-device, setup-fleet)
tf:* Terraform plan/apply
migrate:* Serial-number config migration
utils:* ssh, logs, status, docs, help

Root-level aliases exist for the common ones: task deploy, task provision, task setup-device, task validate, task ssh DEVICE=..., task logs DEVICE=... SERVICE=....

Fleet health

task ansible:health          # all environments
task ansible:health-dev
task ansible:health-staging
task ansible:health-prod
task ansible:health-lite

Runs ansible/playbooks/healthcheck.yml, which per device checks: Node-RED service status, cloudflared service status, MQTT certificate validity/expiry, and disk space, then prints a per-device summary.

Certificate renewal

task ansible:renew-certs

Renews any device's MQTT client cert when it has fewer than 30 days left (ansible/playbooks/renew-certificates.yml, threshold set by mqtt_cert_expiry_threshold_days). Safe to run on a schedule — it's a no-op for certs that aren't close to expiry.

Restarting services

task ansible:restart DEVICE=rpi-prod-<serial>
task ansible:restart-prod     # environment-wide, requires confirmation

Or directly:

ssh tagai@rpi-prod-<serial>-ssh.tagai.uk
sudo systemctl restart node-red
sudo systemctl restart cloudflared

Logs

task logs DEVICE=rpi-prod-<serial> SERVICE=node-red
# or directly:
ssh tagai@rpi-prod-<serial>-ssh.tagai.uk
sudo journalctl -u node-red -n 100 -f
sudo journalctl -u cloudflared -n 100 -f

Adding / removing a device

Add: edit config/devices.yml, then follow runbooks/provisioning.md.

Remove: delete the entry from config/devices.yml, then:

cd terraform && terraform apply
This tears down that device's tunnel and DNS records. The device itself isn't touched remotely — decommission it physically/on-network separately.

Deploying a Node-RED flow update

task deploy-nodered                    # all devices
task deploy-nodered LIMIT=rpi-prod-<serial>
task deploy-nodered VERSION=v1.0.0

See reference/nodered-git-deployment.md for rollback and CI/CD trigger details.

Troubleshooting

See the troubleshooting section of runbooks/provisioning.md for provisioning-time issues. For a device that's already deployed but unhealthy, start with task ansible:health-<env> and task logs DEVICE=... SERVICE=... above.