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

ToolLanguageAgent RequiredLearning Curve
AnsibleYAMLNoLow
ChefRubyYesHigh
PuppetPuppet DSLYesHigh
SaltStackYAML / PythonOptionalMedium

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.pem

Dynamic 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: restarted

Key Elements Explained

ElementPurpose
hostsWhich servers or groups to target
become: trueEscalate to sudo for privileged operations
tasksList of actions to perform in order
notifyTriggers a handler only when a task changes something
handlersTasks 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 --check

Variables 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: no

Variables 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        # Handlers

Using a role in a playbook:

---
- name: Configure web servers
  hosts: web_servers
  become: true
  roles:
    - nginx
    - firewall
    - monitoring

Ansible 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-pass

Ansible 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:

  1. Terraform creates three EC2 instances.
  2. Terraform outputs the IP addresses.
  3. CI/CD pipeline generates an Ansible inventory from those IPs.
  4. Ansible playbook runs: installs dependencies, deploys the application, configures Nginx.
  5. 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.

Leave a Comment