Infrastructure as Code with Azure Pipelines: Terraform + SaltStack in Production
From a working Azure DevOps project to a fully automated infrastructure pipeline.
This workshop takes engineers from a working Azure DevOps project to a fully automated infrastructure pipeline using Terraform for provisioning and SaltStack for configuration management — the exact stack delivered in production at Pune DevCon 2019. It assumes working Azure DevOps access and basic familiarity with cloud infrastructure concepts, and moves through five hands-on segments.
Real-World Modules
Terraform structure that survives beyond a single tutorial repo.
Policy Gates
Nothing reaches production without passing an enforced check.
1. Structuring Terraform for Real-World Modules
Most Terraform tutorials teach you to write a single main.tf that provisions everything in one flat file. Production infrastructure needs the opposite: composable modules with clear input/output contracts, versioned independently, so a change to the networking module doesn't force a re-plan of every environment that consumes it. This segment covers module boundaries, variable design that avoids leaking implementation details to callers, and a repo layout that scales past the first three environments.
2. Integrating State Management in Azure Pipelines
Remote state in Azure Storage with locking is the easy part. The harder part is pipeline design: separating plan from apply as distinct stages with a manual approval gate between them, scoping state files per environment so a mistake in staging can't touch production state, and handling drift detection as a scheduled pipeline run rather than discovering it during the next deploy.
# Two-stage pipeline: plan requires approval before apply runs
stages:
- stage: Plan
jobs:
- job: TerraformPlan
steps:
- script: terraform plan -out=tfplan
- stage: Apply
dependsOn: Plan
condition: succeeded()
jobs:
- deployment: TerraformApply
environment: production # manual approval gate lives here
strategy:
runOnce:
deploy:
steps:
- script: terraform apply tfplan3. Managing Secrets Without Putting Them in YAML
Pipeline YAML files end up in Git history forever, which makes them the wrong place for anything sensitive. This segment covers pulling secrets from Azure Key Vault at pipeline runtime via variable groups, scoping service connections to the minimum permissions each stage actually needs, and the specific mistake to avoid: passing secrets as plain pipeline variables, which shows up unmasked in the vast majority of custom task logs.
4. SaltStack Configuration Runs as Pipeline Stages
Terraform provisions the infrastructure; SaltStack configures what runs on it. Treating a Salt highstate run as its own pipeline stage — with its own success criteria and rollback path — keeps provisioning and configuration failures distinguishable instead of tangled into one opaque "deployment failed" error. This segment walks through structuring Salt states alongside Terraform modules so the two stay in version-controlled lockstep.
Provision, Configure, Gate
The three-stage shape this workshop builds toward — each stage independently testable, independently rollback-able.
5. Enforcing Policy Gates Before Production
The final segment covers policy-as-code checks that run between plan and apply — blocking changes that would create publicly exposed storage, remove encryption settings, or exceed a cost threshold — using pipeline-native policy evaluation rather than a manual reviewer reading a plan output line by line. This is the difference between infrastructure as code that's merely automated and infrastructure as code that's actually governed.
Drift, the Recurring Cost
Drift detection is not a one-time setup task — it's a scheduled pipeline run (nightly or per-environment cadence) that compares live infrastructure against state and opens a ticket automatically when they diverge. Without this, "the pipeline is the source of truth" quietly stops being true within a few weeks of any team having console access.
Conclusion
None of these five segments are exotic. What makes the stack production-grade isn't a clever Terraform trick — it's the discipline of separating plan from apply, keeping secrets out of YAML, treating configuration as its own gated stage, and catching drift before it becomes an incident. That discipline, delivered in production at Pune DevCon 2019, is what this workshop hands to participants directly.
Bringing this workshop to your team?
Naval Thakur delivers this as a hands-on session for teams running Terraform and configuration management in Azure Pipelines.