← Back to Home 🐳 Docker ☸️ K8s
πŸ”§ Configuration Management

Ansible Complete Guide

Automate server configuration, application deployment, and infrastructure management β€” from ad-hoc commands to production roles and playbooks.

12
Chapters
40+
Playbooks
100%
Free
01πŸ”§

Introduction to Ansible

Agentless Automation

Ansible automates server configuration without installing anything on the target servers. You write YAML files (playbooks) that describe the desired state, and Ansible connects via SSH and makes it happen. Think of it as: instead of manually running 50 commands on 100 servers, you write a playbook once and Ansible does it on all 100 servers simultaneously.
πŸ”Œ
Agentless
No software to install on servers. Ansible connects via SSH. This is the #1 advantage over Puppet and Chef.
πŸ“
YAML
Playbooks are written in YAML β€” human-readable, no programming needed.
πŸ”„
Idempotent
Run a playbook 100 times, same result. If nginx is already installed, Ansible skips it.
πŸ“¦
Push-Based
You push configuration FROM your control machine TO target servers. No central server needed.
FeatureAnsiblePuppetChef
AgentNo agent (SSH)Agent on every serverAgent on every server
LanguageYAMLPuppet DSLRuby
ArchitecturePush (agentless)Pull (agent pulls config)Pull (agent pulls config)
Learning CurveLow (YAML)MediumHigh (Ruby)
Best ForDevOps automationLarge enterprise configComplex deployments
02πŸ“₯

Installation & Setup

Get Ansible Running

TERMINAL# Install on Ubuntu/Debian (control node only!) sudo apt update sudo apt install ansible -y # Install on CentOS/RHEL sudo yum install epel-release -y sudo yum install ansible -y # Install via pip (any OS) pip install ansible # Verify ansible --version # ansible [core 2.16.x] # Key point: Install Ansible ONLY on YOUR machine (control node) # Target servers need NOTHING installed β€” just SSH access
03πŸ“‹

Inventory

Define Your Servers

The inventory file lists ALL servers Ansible manages. You organize them into groups (web servers, database servers, etc.) and Ansible targets specific groups.
INVENTORY# /etc/ansible/hosts (or inventory.ini) [webservers] web1 ansible_host=10.0.1.10 ansible_user=deploy web2 ansible_host=10.0.1.11 ansible_user=deploy web3 ansible_host=10.0.1.12 ansible_user=deploy [dbservers] db1 ansible_host=10.0.2.10 ansible_user=deploy db2 ansible_host=10.0.2.11 ansible_user=deploy [monitoring] prometheus ansible_host=10.0.3.10 [production:children] # Group of groups! webservers dbservers monitoring [all:vars] # Variables for ALL servers ansible_ssh_private_key_file=~/.ssh/deploy_key ansible_python_interpreter=/usr/bin/python3
04⚑

Ad-hoc Commands

Quick One-Liners

Ad-hoc commands run a single task on multiple servers without writing a playbook. Great for quick checks and one-time tasks.
TERMINAL# Ping all servers (test connectivity) ansible all -m ping -i inventory.ini # Check uptime on web servers ansible webservers -a "uptime" -i inventory.ini # Install nginx on all web servers ansible webservers -m apt -a "name=nginx state=present" -b -i inventory.ini # -b = become root (sudo) # Restart a service ansible webservers -m service -a "name=nginx state=restarted" -b # Copy a file to all servers ansible all -m copy -a "src=config.yml dest=/opt/app/config.yml" -b # Check disk space on all servers ansible all -a "df -h /" -i inventory.ini
05πŸ“

Playbooks β€” Basics

YAML Automation Scripts

Playbooks are YAML files that describe a series of tasks. Each task uses a module (like apt, copy, service) to do something on the target servers. A playbook is your automation recipe.
Complete Playbook β€” Explained Line by Line
YAML# deploy_nginx.yml --- # YAML document start - name: Install and configure Nginx # Play name (description) hosts: webservers # Target group from inventory become: yes # Run as root (sudo) vars: # Variables app_port: 3000 server_name: myapp.com tasks: # List of things to do - name: Update apt cache apt: update_cache: yes cache_valid_time: 3600 # Only update if older than 1 hour - name: Install Nginx apt: name: nginx state: present # present=install, absent=remove - name: Copy Nginx config template: src: nginx.conf.j2 # Jinja2 template dest: /etc/nginx/sites-available/myapp.conf notify: Restart Nginx # Trigger handler if file changed - name: Enable site file: src: /etc/nginx/sites-available/myapp.conf dest: /etc/nginx/sites-enabled/myapp.conf state: link # Create symbolic link - name: Start Nginx service: name: nginx state: started enabled: yes # Start on boot handlers: # Only run when "notified" - name: Restart Nginx service: name: nginx state: restarted # Run: ansible-playbook deploy_nginx.yml -i inventory.ini
Handlers are Smart

Handlers only run when notified AND only run ONCE at the end of all tasks. If the config file did not change, the handler does not run. This prevents unnecessary restarts.

06πŸš€

Advanced Playbook Features

Variables, Templates, Conditions, Loops

Jinja2 Templates
JINJA2# templates/nginx.conf.j2 server { listen 80; server_name {{ server_name }}; # Variable from playbook location / { proxy_pass http://localhost:{{ app_port }}; } } # {{ variable }} gets replaced with actual values when Ansible runs
Loops β€” Do Something for Multiple Items
YAML- name: Install multiple packages apt: name: "{{ item }}" state: present loop: - nginx - docker.io - git - curl - htop - name: Create multiple users user: name: "{{ item.name }}" groups: "{{ item.groups }}" state: present loop: - { name: deploy, groups: sudo } - { name: monitor, groups: docker }
Conditions β€” When to Run a Task
YAML- name: Install on Ubuntu only apt: name: nginx state: present when: ansible_os_family == "Debian" - name: Install on CentOS only yum: name: nginx state: present when: ansible_os_family == "RedHat"
07πŸ“

Roles

Organize Playbooks Professionally

Roles break a large playbook into reusable, shareable components. Instead of one 500-line playbook, you have clean folders: tasks, templates, handlers, variables. Like Python modules β€” import and use.
DIRECTORY# Role directory structure roles/ nginx/ tasks/ main.yml # What to do handlers/ main.yml # Restart handlers templates/ nginx.conf.j2 # Config templates vars/ main.yml # Variables defaults/ main.yml # Default values (overridable) files/ index.html # Static files to copy # Use role in playbook: # site.yml --- - hosts: webservers become: yes roles: - nginx - docker - monitoring
08πŸ—οΈ

Real-World Playbooks

Production Examples

Setup Docker on All Servers
YAML--- - name: Install Docker hosts: all become: yes tasks: - name: Install prerequisites apt: name: [apt-transport-https, ca-certificates, curl, gnupg] state: present - name: Add Docker GPG key apt_key: url: https://download.docker.com/linux/ubuntu/gpg - name: Add Docker repository apt_repository: repo: "deb https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable" - name: Install Docker apt: name: [docker-ce, docker-ce-cli, containerd.io] state: present update_cache: yes - name: Add deploy user to docker group user: name: deploy groups: docker append: yes - name: Start Docker service: name: docker state: started enabled: yes
09πŸ”

Ansible Vault

Encrypt Secrets

Vault encrypts sensitive data β€” passwords, API keys, certificates. You can safely commit encrypted files to Git. Only people with the vault password can decrypt them.
TERMINAL# Encrypt a file ansible-vault encrypt secrets.yml # Enter password β†’ file is now encrypted # Edit encrypted file ansible-vault edit secrets.yml # Run playbook with vault ansible-playbook site.yml --ask-vault-pass # Or use a password file: ansible-playbook site.yml --vault-password-file .vault_pass
10🌌

Ansible Galaxy

Community Roles

Galaxy is a marketplace of pre-built roles. Need Docker installed? Download geerlingguy.docker. Need MySQL? Download geerlingguy.mysql. Save hours of writing playbooks.
TERMINAL# Search roles ansible-galaxy search docker # Install a role ansible-galaxy install geerlingguy.docker ansible-galaxy install geerlingguy.nginx # Use in playbook --- - hosts: all become: yes roles: - geerlingguy.docker - geerlingguy.nginx
11πŸ†

Best Practices

Write Ansible Like a Pro

βœ“Use roles for anything reused across 2+ playbooks
βœ“Keep inventory separate from playbooks (different repos or directories)
βœ“Use ansible-vault for ALL secrets β€” never plain text passwords
βœ“Name every task clearly β€” ansible output shows task names
βœ“Use tags to run specific parts: ansible-playbook site.yml --tags deploy
βœ“Test in dev/staging before production (always)
βœ“Use --check mode for dry run: ansible-playbook site.yml --check
βœ“Idempotent tasks: running twice should produce same result
βœ“Use variables for anything that changes between environments
βœ“Group variables in group_vars/ directory (auto-loaded by Ansible)
12πŸ’Ό

Interview Questions

Ansible Q&A

❓
What is Ansible?
Agentless automation tool. Connects via SSH, runs YAML playbooks, configures servers. No agent needed on targets. Push-based.
❓
Ansible vs Terraform?
Ansible: configuration management (install packages, configure services). Terraform: infrastructure provisioning (create VMs, networks, databases). Use both: Terraform creates infra, Ansible configures it.
❓
What is idempotency?
Running a playbook multiple times gives the same result. If nginx is already installed, Ansible skips installation. Safe to run repeatedly.
❓
Playbook vs Role?
Playbook: a YAML file with tasks. Role: organized directory structure (tasks, handlers, templates, vars). Roles are reusable across projects.
❓
What are handlers?
Special tasks that run only when notified. Used for service restarts. If config file changes β†’ notify handler β†’ handler restarts service. If no change β†’ handler does not run.
❓
What is Ansible Vault?
Encrypts sensitive files (passwords, keys). Encrypted files can be committed to Git safely. Decrypt with vault password at runtime.
❓
Ad-hoc vs Playbook?
Ad-hoc: single command for quick tasks (check uptime, install one package). Playbook: multiple tasks in YAML for complex automation. Playbooks are repeatable and version-controlled.
❓
What is inventory?
File listing all servers Ansible manages. Organized into groups (webservers, dbservers). Can be static (INI/YAML file) or dynamic (script that queries AWS/Azure).