Cloud-Native DevOps: Automating Deployment with Terraform, Ansible & Azure DevOps

Hi there! I'm Vineet Singh Negi and I have just started writing blogs. I'm passionate about DevOps and Machine Learning exploring all the different technologies involved in the process. I am constantly seeking new opportunities to expand my skill set and am actively working on various projects to improve my knowledge.
On my Hashnode blogs, you'll find a mix of tutorials and insights as I navigate the world of DevOps and Machine Learning. I will be sharing everything I learn along the way.
Introduction
In today’s DevOps world, automation is the backbone of efficiency and consistency.
In this project, I automated the Book Review Application deployment from end to end — provisioning infrastructure with Terraform, configuring servers with Ansible, and orchestrating the entire workflow using Azure DevOps Pipelines.
By the end of this pipeline, a fully functional Book Review web app runs on Azure, deployed through code, without a single manual click.
Project Overview
We’ll be building two key repositories and two pipelines:
Infra Repository (
book-review-infra)Contains Terraform code to provision:
Resource Group
Virtual Network and Subnet
Two Ubuntu VMs (frontend & backend)
MySQL (Flexible Server or VM-based)
App Repository (
book-review-app)Contains:
Book Review App source code (Frontend + Backend)
Ansible playbooks for configuration and deployment
Pipelines Overview
Infra Pipeline: Uses Terraform to create Azure resources.
App Pipeline: Uses Ansible to configure the servers and deploy the app.
Tools & Technologies
Azure DevOps — CI/CD orchestration
Terraform — Infrastructure as Code
Ansible — Configuration management
Azure Service Principal — Secure authentication
SSH Keys — Secure VM access
Ubuntu — OS for VMs
MySQL — Database for the app
Step 1: Setting up Azure and Service Connection
Create an Azure Service Principal
Run the following command to create a Service Principal:
az ad sp create-for-rbac --name "devops-terraform-sp" --role Contributor \ --scopes /subscriptions/<your-subscription-id>Copy the output — it will include:
appId (Client ID)
password (Client Secret)
tenant
subscriptionId
You’ll use these values to connect Azure DevOps to Azure.
Create a Service Connection in Azure DevOps
Go to Project Settings → Service Connections → New Service Connection
Choose Azure Resource Manager → Service Principal (Manual)
Paste the Client ID, Client Secret, Tenant ID, and Subscription ID
Verify and Save as
it-azure-connection

Step 2: Setting up Secure Files
- In Azure DevOps → Pipelines → Library → Secure Files, upload:
Your SSH private key (
id_rsa)Your SSH public key (
id_rsa.pub)
- Authorize them for use in pipelines.
These keys are essential for Ansible to connect to the provisioned VMs.
Step 3: Infrastructure Automation (Terraform)
Repository: book-review-infra
terraform/
├── main.tf
├── provider.tf
├── variables.tf
├── outputs.tf
├── envs/
│ └── dev.tfvars
├── modules/
└── compute
└── network
└── database
You can clone the repo here: https://github.com/VineetSnegi/book-review-infra
provider.tf
provider "azurerm" {
features {
resource_group {
prevent_deletion_if_contains_resources = false
}
}
}
outputs.tf
output "frontend_public_ip" {
value = azurerm_public_ip.frontend_pip.ip_address
}
output "backend_public_ip" {
value = azurerm_public_ip.backend_pip.ip_address
}
output "mysql_fqdn" {
value = azurerm_mysql_flexible_server.db.fqdn
}
Infra Pipeline YAML (azure-pipelines.yml)
trigger:
- main
pool:
name: 'self-hosted-agent-pool'
variables:
TF_VERSION: '1.9.2'
steps:
- task: DownloadSecureFile@1
name: download_ssh_key
inputs:
secureFile: 'id_rsa.pub'
- script: |
sudo apt-get update -y
sudo apt-get install -y unzip
curl -LO https://releases.hashicorp.com/terraform/${TF_VERSION}/terraform_${TF_VERSION}_linux_amd64.zip
unzip terraform_${TF_VERSION}_linux_amd64.zip
sudo mv terraform /usr/local/bin/
terraform -version
displayName: 'Install Terraform'
- script: |
terraform init
terraform plan -var-file="envs/dev.tfvars"
terraform apply -var-file="envs/dev.tfvars" -auto-approve
displayName: 'Terraform Apply'
Once the pipeline runs successfully, note down the frontend IP, backend IP, and MySQL FQDN from the Terraform outputs.

Confirm the resources creation on azure portal.

Step 4: Configuration Management (Ansible) Outputs)
For configuration of the application and other necessary, Ansible is the deal.
Step 5: Manual Handoff (Passing Infra Outputs)
Copy the Terraform outputs and update your Ansible inventory and variables.
ansible/inventory.ini:
[frontend]
<frontend_public_ip> ansible_user=azureuser
[backend]
<backend_public_ip> ansible_user=azureuser

ansible/group_vars/backend.yml
db_host: "<mysql_fqdn>"

ansible/group_vars/frontend.yml
backend_api_url: "http://<backend_public_ip>:5000"

Commit and push these updates.
Step 6: App Pipeline (Ansible Deployment)
Repository: book-review-app
Your azure-pipelines.yml:
trigger:
- main
pool:
name: 'self-hosted-agent-pool'
steps:
- task: DownloadSecureFile@1
name: download_private_key
inputs:
secureFile: 'id_rsa'
- script: |
sudo apt-get update
sudo apt-get install -y ansible sshpass
chmod 600 $(download_private_key.secureFilePath)
displayName: 'Install Ansible and Configure SSH'
- script: |
ansible-playbook -i ansible/inventory.ini ansible/site.yml \
--private-key $(download_private_key.secureFilePath)
displayName: 'Run Ansible Playbook'
This pipeline connects to the VMs provisioned by Terraform and configures:
Backend (Flask + MySQL connection)
Frontend (Nginx serving UI)
Press enter or click to view image in full size

Step 7: Validate the Deployment
After the app pipeline runs successfully:
Copy the frontend public IP from Terraform output.
Open it in your browser.
You should see the Book Review App running live
Register a user, add a review, and confirm backend connectivity.

Step 8: Destroy the Infrastructure (Cleanup)
Once you’re done testing:
terraform destroy -var-file="envs/dev.tfvars" -auto-approve
Or via Azure DevOps:
Edit the infra pipeline and change
applytodestroy.Commit and rerun the pipeline.
Conclusion
This project demonstrated a complete CI/CD workflow combining Terraform, Ansible, and Azure DevOps.
We achieved a fully automated environment, deploying a real-world app from scratch — all via code.
The pipelines are reusable, modular, and production-ready, representing a solid foundation for modern DevOps automation.
This journey deepened my understanding of end-to-end DevOps automation.
I learned how Terraform and Ansible complement each other — Terraform builds the infrastructure, and Ansible brings it to life.
Setting up Azure DevOps pipelines and secure connections provided a hands-on experience with enterprise-level CI/CD governance and best practices.
Future Work
Automate variable sharing: Pass Terraform outputs to Ansible dynamically using Azure variable groups.
Multi-environment setup: Extend pipelines for Dev → Test → Prod with approval gates.
Add post-deploy validation: Implement smoke tests after app deployment.
Integrate monitoring: Add Azure Monitor and Application Insights.
Containerization: Package the Book Review app in Docker and deploy with Kubernetes.



