DevOps Configuration Management with Ansible
Configuration management is the practice of automating the setup and maintenance of servers. Instead of SSH-ing into each server and running commands manually, configuration management tools define the desired server state in code and apply it across dozens or hundreds of machines at once.
Ansible is the most popular configuration management tool in DevOps. It is agentless — nothing gets installed on the target servers. Ansible connects over SSH and runs tasks defined in simple YAML files called Playbooks.
Ansible vs Other Configuration Tools
| Tool | Language | Agent Required | Learning Curve |
|---|---|---|---|
| Ansible | YAML | No | Low |
| Chef | Ruby | Yes | High |
| Puppet | Puppet DSL | Yes | High |
| SaltStack | YAML / Python | Optional | Medium |
Ansible's agentless design and YAML syntax make it the easiest entry point into configuration management.
Core Ansible Concepts
Control Node
The machine where Ansible is installed and from which all commands are run. This is typically a CI/CD server or a DevOps engineer's workstation.
Managed Nodes (Hosts)
The servers that Ansible configures. These need only Python and SSH access — no Ansible installation required.
Inventory
An inventory file lists the managed servers and organizes them into groups.
Module
A module is a reusable unit of work Ansible can execute — installing a package, copying a file, restarting a service, running a command. Ansible includes hundreds of built-in modules.
Task
A task is a single call to a module with specific parameters. It answers: "Do what, to what, with what settings?"
Playbook
A Playbook is a YAML file containing an ordered list of tasks to run on a group of servers. Playbooks are the primary way to use Ansible.
Role
A Role is a reusable, structured collection of tasks, templates, and variables for a specific purpose — like configuring Nginx, deploying a Java app, or setting up a MySQL database.
Ansible Inventory File
Simple Static Inventory
# inventory.ini
[web_servers]
web01 ansible_host=192.168.1.10
web02 ansible_host=192.168.1.11
[db_servers]
db01 ansible_host=192.168.1.20
[all:vars]
ansible_user=ubuntu
ansible_ssh_private_key_file=~/.ssh/mykey.pemDynamic Inventory
For cloud environments, Ansible supports dynamic inventories that pull the current list of servers directly from AWS, Azure, or GCP — no manual updates needed as servers scale up and down.
Writing Playbooks
Simple Example – Install and Start Nginx
---
- name: Configure web servers
hosts: web_servers
become: true # Run tasks as sudo
tasks:
- name: Update apt cache
apt:
update_cache: yes
- name: Install Nginx
apt:
name: nginx
state: present
- name: Start and enable Nginx
service:
name: nginx
state: started
enabled: yes
- name: Copy website configuration
copy:
src: files/nginx.conf
dest: /etc/nginx/nginx.conf
owner: root
group: root
mode: '0644'
notify: Restart Nginx
handlers:
- name: Restart Nginx
service:
name: nginx
state: restartedKey Elements Explained
| Element | Purpose |
|---|---|
| hosts | Which servers or groups to target |
| become: true | Escalate to sudo for privileged operations |
| tasks | List of actions to perform in order |
| notify | Triggers a handler only when a task changes something |
| handlers | Tasks that run only when notified — ideal for restarts |
Running Playbooks
# Run a playbook
ansible-playbook -i inventory.ini site.yml
# Run with verbose output for debugging
ansible-playbook -i inventory.ini site.yml -v
# Run only on specific hosts
ansible-playbook -i inventory.ini site.yml --limit web01
# Dry run (check mode) — shows what would change without making changes
ansible-playbook -i inventory.ini site.yml --checkVariables in Ansible
Variables make playbooks flexible and reusable across environments.
---
- name: Deploy application
hosts: app_servers
vars:
app_version: "2.1.0"
app_port: 8080
deploy_dir: "/var/www/myapp"
tasks:
- name: Create app directory
file:
path: "{{ deploy_dir }}"
state: directory
owner: www-data
- name: Deploy application
unarchive:
src: "myapp-{{ app_version }}.tar.gz"
dest: "{{ deploy_dir }}"
remote_src: noVariables can also come from separate files (vars/main.yml), inventory groups, or passed directly on the command line:
ansible-playbook deploy.yml -e "app_version=2.2.0"Ansible Roles – Reusable Configuration
Roles organize related tasks into a standard directory structure, making them reusable across multiple playbooks and projects.
roles/
└── nginx/
├── tasks/
│ └── main.yml # Task list
├── templates/
│ └── nginx.conf.j2 # Jinja2 templates
├── files/
│ └── index.html # Static files
├── vars/
│ └── main.yml # Role variables
└── handlers/
└── main.yml # HandlersUsing a role in a playbook:
---
- name: Configure web servers
hosts: web_servers
become: true
roles:
- nginx
- firewall
- monitoringAnsible Vault – Protecting Secrets
Ansible Vault encrypts sensitive data like passwords and API keys stored in YAML files:
# Create an encrypted variables file
ansible-vault create secrets.yml
# Edit an encrypted file
ansible-vault edit secrets.yml
# Run a playbook that uses an encrypted file
ansible-playbook deploy.yml --ask-vault-passAnsible in a DevOps Pipeline
Terraform provisions infrastructure (creates the servers). Ansible configures it (installs software, sets up the app). Together they automate the full environment setup:
- Terraform creates three EC2 instances.
- Terraform outputs the IP addresses.
- CI/CD pipeline generates an Ansible inventory from those IPs.
- Ansible playbook runs: installs dependencies, deploys the application, configures Nginx.
- The environment is fully ready — zero manual steps.
Real-World Example
A DevOps team manages 20 application servers. Every new server needs: Node.js 18, PM2 process manager, Nginx as reverse proxy, and the application code deployed from Git. An Ansible playbook does all of this in under 5 minutes on all 20 servers simultaneously. Adding a 21st server? Run the same playbook — identical setup, guaranteed.
Summary
- Ansible automates server configuration using agentless, SSH-based connections.
- Playbooks are YAML files that define ordered tasks to run on target servers.
- Modules are the building blocks — covering packages, services, files, users, and more.
- Roles package reusable configuration for specific components like Nginx or MySQL.
- Ansible Vault protects sensitive values like passwords and API keys.
- Ansible complements Terraform: Terraform builds infrastructure, Ansible configures it.
