Automate App Deployment: Azure DevOps + Terraform + Ansible

Imagine deploying your app without touching a server. One engineer's four-project saga delivers a live Azure pipeline using Terraform for infra and Ansible for config. It's slick, but don't drink the automation Kool-Aid without caveats.

Zero-Touch App Deploys: Azure DevOps, Terraform, and Ansible Finally Click – But At What Cost? — theAIcatchup

Key Takeaways

  • Split infra and app repos for clean pipelines and team sanity.
  • Service Principals are mandatory for Terraform in Azure DevOps – no shortcuts.
  • Static IPs and Secure Files prevent common deployment pitfalls.

Your weekend’s ruined again because some VM decided to reboot and eat your static IP. Real people — devs, ops folks, that harried startup CTO — waste hours on this crap. But here’s a pipeline that nukes manual deploys entirely: Azure DevOps orchestrating Terraform for infra, Ansible for app config. EpicBook lives at a public IP, zero touches.

Punchy, right?

Why Does Splitting Infra and App Repos Actually Matter?

Look, monorepos sound sexy — everything in one git palace. But try a frontend pixel tweak that triggers your whole cloud rebuild. Chaos. Teams trip over each other. Rollbacks? Nightmare.

This guy’s fix: two repos, two pipelines. Infra repo spits out VMs, networks, NSGs via Terraform. App repo slaps code and config via Ansible. Clean. Intentional. Mirrors how real squads operate — devs tweak apps, infra wranglers don’t flinch.

Separating them means each repository has one clear responsibility. The infra repo manages what exists on Azure. The app repo manages what runs on that infrastructure. Two repos, two concerns, two pipelines.

Spot on. That’s your quote of the day.

And the infra? Resource group, VNet (10.2.0.0/16), NSG opening 22, 80, 3306. Two D2s_v3 VMs — frontend, backend — with static public IPs. No dynamic IP roulette screwing your Ansible inventory. Outputs like frontend_public_ip = “20.25.48.139”. Gold.

But.

Terraform in a pipeline? First rodeo disaster waiting. Can’t use your personal Azure login — needs a Service Principal. Whip one up: az ad sp create-for-rbac –name “EpicBookTerraformSP” –role Contributor –scopes /subscriptions/YOUR_SUBSCRIPTION_ID. Snag appId, password, tenant, sub ID. Pipe ‘em into Azure DevOps service connection. Pipeline’s AzureCLI@2 task with addSpnToEnvironment: true feeds vars to Terraform. Secure. No hardcodes.

Skip it? Fail city.

SSH keys? Local gen: ssh-keygen -t rsa -b 4096 -f ~/.ssh/epicbook_key -N “”. Pubkey in Terraform, privkey to Secure Files. Pipeline downloads, chmod 400. Ansible connects clean. Loose perms? SSH rage-quits.

Security 101, kids. Repos stay virgin.

Is Azure DevOps Pipeline Magic or Just Glorified Glue?

Self-hosted agent from Project 1 — nice callback. Infra pipeline: Terraform apply. App pipeline: Ansible playbooks. Hosts: frontend/backend. Roles: common (updates, basics), nginx (frontend), epicbook_frontend/backend.

Four roles, two VMs. Boom — app live.

What went wrong? Plenty, he admits. Terraform auth flubs. Key perms. Dynamic IPs (fixed with statics). Real sweat.

Here’s my hot take the original skips: this reeks of early 2010s DevOps wars. Remember Puppet Chef hell? Ansible won by being agentless YAML poetry. Pair with Terraform’s declarative infra-as-code, gated by Azure DevOps YAML pipelines — it’s IaC 2.0. But Azure lock-in? You’re betting on Microsoft’s forever-sub. Multi-cloud dreams? Terraform helps, but DevOps pipelines scream vendor hug.

Prediction: in two years, GitHub Actions eats this lunch. Native, free-ish, less agent fiddling.

Dry humor break — imagine your boss: “Great pipeline! Now do it on AWS.” Cue existential scream.

The design shines on separation. Infra changes? App pipeline idles. App bug? Rollback sans infra drama. Scales to teams. But solo? Overhead. Two repos mean twice the PRs, branches, reviews.

Worth it? For anything beyond toy app, yes. EpicBook proves it: live at public IP, automated end-to-end.

What he’d tweak next: dynamic inventories maybe, or container pivot. Smart.

But call the hype — this ain’t revolutionary. It’s solid engineering catching up to 2024. Real people win: less on-call pain, more code time. Still, if you’re AWS diehard or open-source purist, squint hard.

How Do You Avoid the Gotchas in Your Own Pipeline?

Service Principal dance — non-negotiable. Test local first: terraform login with SP creds.

Secure Files for keys. Chmod every time. Ansible inventory from Terraform outputs — use terraform output -json piped to dynamic inv.

NSG rules tight: only what’s needed. D2s_v3? Cheap start, scale later.

And agents: self-hosted beats Microsoft-hosted for custom tools, but maintain ‘em.

One sentence warning: don’t cargo-cult without your sub ID handy.

Deeper dive — Ansible roles. Common on both: apt update, users, firewalls. Nginx frontend proxy? Obvious. Backend MySQL? (Ports hint). EpicBook roles deploy code, configs. Pull from repo artifacts? Pipeline magic.

He built it over weeks, four projects. Culmination. Respect.

Corporate spin check: Azure pushes this hard. Free tier agents? Nah, self-host. Costs lurk. But output? Tangible.

Unique insight time — parallel to Unix philosophy: do one thing well. Repos as pipes. Terraform provisions, Ansible configures. No monolith bloat.

Why Bother When Docker + Kubernetes Exists?

Fair. But VMs persist for legacy, cost, simplicity. EpicBook ain’t microservices poster child. Start here, evolve.

Humor: Kubernetes? Sure, when you want YAML nightmares on steroids.

Real win: zero manual server steps. Scale to prod? Add approvals, tests, blue-green.

Prediction bold: this pattern dominates mid-market. Not FAANG, but your SaaS grind.

FAQ time, because Google hungers.


🧬 Related Insights

Frequently Asked Questions

How do I create a Service Principal for Terraform in Azure DevOps?

Run az ad sp create-for-rbac –name “YourSP” –role Contributor –scopes /subscriptions/YOUR_SUB_ID. Grab appId, password, tenant. Add Azure RM service connection in DevOps. Pipeline task: AzureCLI@2 with addSpnToEnvironment: true.

Why use static IPs with Terraform VMs for Ansible?

Dynamic IPs change on reboot, breaking inventory links. Static outputs feed Ansible reliably. Simple fix, huge sanity.

What’s the best way to handle SSH keys in Azure DevOps pipelines?

Generate locally, pubkey to Terraform, privkey to Secure Files. Download in pipeline, chmod 400. Never repo-commit.

Sarah Chen
Written by

AI research editor covering LLMs, benchmarks, and the race between frontier labs. Previously at MIT CSAIL.

Frequently asked questions

🧬 Related Insights?
- **Read more:** [Why Wallet Devs Are Ditching Keys for Frictionless Swap APIs in 2026](https://theaicatchup.com/article/5-best-swap-apis-for-web3-wallet-developers/) - **Read more:** [npm's a Sucker Punch — Here's Your Guard](https://theaicatchup.com/article/saving-yourself-from-npm/) Frequently Asked Questions **How do I create a Service Principal for Terraform in Azure DevOps?** Run az ad sp create-for-rbac --name "YourSP" --role Contributor --scopes /subscriptions/YOUR_SUB_ID. Grab appId, password, tenant. Add Azure RM service connection in DevOps. Pipeline task: AzureCLI@2 with addSpnToEnvironment: true. **Why use static IPs with Terraform VMs for Ansible?** Dynamic IPs change on reboot, breaking inventory links. Static outputs feed Ansible reliably. Simple fix, huge sanity. **What's the best way to handle SSH keys in Azure DevOps pipelines?** Generate locally, pubkey to Terraform, privkey to Secure Files. Download in pipeline, chmod 400. Never repo-commit.

Worth sharing?

Get the best AI stories of the week in your inbox — no noise, no spam.

Originally reported by Dev.to

Stay in the loop

The week's most important stories from theAIcatchup, delivered once a week.