Skip to content

Azure DevOps Pipelines

All pipelines (pipelines/*.yml) run on the truenas-dr-pool agent pool — the self-hosted agent described in Self-Hosted Azure DevOps Agent — since every one of them needs to reach lab-only infrastructure a Microsoft-hosted agent never could.

Pipeline Trigger What it does
terraform.yml Manual Start infra, then plan/apply base and compute Terraform stacks, stage by stage
power-state.yml Manual Start/stop any single server (vcsa, dke-mgmt, esxid, esxid2) or all of them, in parallel
backup.yml Daily cron (03:00) Runs ansible/backup-playbook.yml — NAS/UniFi/pfSense/TrueNAS-DR config backups
ssl-renew.yml Certificate renewal, paired with pfSense's ACME setup
recording-cleanup.yml Daily cron (01:00) Prunes old camera/NVR recordings via ansible/recording_cleanup.yml
openvpn-azure-dns-A-record.yml Daily cron (01:00) Keeps openvpn.devhome.cloud's A record pointed at the home connection's current public IP

The make-target pattern

terraform.yml and power-state.yml don't call ansible-playbook/terraform directly — they shell out to Makefile targets (make start-dke-mgmt, make tf-plan-base, make tf-apply-compute, etc.), keeping the actual command construction (inventory paths, working directories, flags) in one place instead of duplicated across every pipeline YAML. power-state.yml's server/power_state pipeline parameters compose directly into a Make target name ("${power_state}-${server}"), so adding a new manageable server is a Makefile change, not a pipeline-YAML change.

power-state.yml -> all and terraform.yml's StartInfra stage both run their per-server Make targets in parallel (backgrounded with &, then wait) — starting vcsa, dke-mgmt, and both ESXi hosts concurrently rather than serially, which matters when the whole lab is coming back from a full power-down.

Ansible-specific pipeline settings worth knowing

  • ANSIBLE_HOST_KEY_CHECKING: 'false' everywhere — hosts get rebuilt/reinstalled often enough that host-key churn is expected, not something worth failing a pipeline over.
  • failOnStdErr: false on the Ansible@0 task — Ansible prints [WARNING]s (group-name characters, Python interpreter discovery) to stderr even on a fully successful run; the task's actual return code is what determines success, not the presence of stderr output.
  • Inventory is always the repo's ansible/hosts file (DNS names, current users) — never inline IPs in a pipeline, which is exactly what went stale across the network redesign.

Terraform-specific pipeline settings

terraform.yml exposes every TF_VAR_*/ARM_* credential from a pipeline variable group (terraform-secrets) as job environment variables — this is the one place credentials flow through ADO's own variable-group secrets rather than a runtime Vault lookup, since Terraform itself needs ARM_* present in the environment before it can even reach the vault provider to pull everything else. Compare with Vault Consumers for how every other tool authenticates.