Skip to content

Ansible Guide — Automation and Configuration Management

DodaTech Updated 2026-06-07 7 min read

In this tutorial, you'll learn about Ansible Guide. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.

Ansible is an open-source automation tool that lets you manage servers, deploy applications, and configure infrastructure using simple YAML playbooks — with no agent software required on managed nodes, just SSH and Python.

What You'll Learn

  • Setting up Ansible with inventory files and SSH connectivity
  • Writing playbooks with tasks, handlers, and variables
  • Using Ansible modules for system administration
  • Organizing automation with roles and directory structures
  • Understanding idempotency and running ad-hoc commands

Why Ansible Matters

Configuration Management tools like Puppet and Chef require agents installed on every node, a master server, and a complex Domain-Specific Language. Ansible uses SSH (no agents), YAML (no new language to learn), and push-based execution — you run a playbook and it takes effect immediately. This makes Ansible ideal for teams that need automation without the overhead of a full Configuration Management platform. DodaTech uses Ansible to provision Durga Antivirus Pro's update servers — the playbooks ensure every server has the correct Nginx config, SSL certificates, and update repositories with a single command.

flowchart LR
    A[Bash & Linux Basics] --> B[Ansible]
    B --> C[Inventory]
    B --> D[Playbooks]
    B --> E[Modules]
    B --> F[Roles]
    C --> G[Server Groups]
    D --> H[Task Automation]
    E --> I[System Operations]
    F --> J[Reusable Automation]
    style B fill:#e0002b,color:#fff
â„šī¸ Info

Prerequisites: Basic Bash and Linux command-line experience. SSH access to at least one Linux server for practice.

Core Concepts

Inventory and Ad-Hoc Commands

# Install Ansible
# Ubuntu/Debian: sudo apt install ansible
# macOS: brew install ansible
# RHEL/CentOS: sudo yum install epel-release && sudo yum install ansible

# Inventory file — define your servers
# hosts.ini
[webservers]
web1.example.com
web2.example.com

[databases]
db1.example.com ansible_user=ubuntu

[all:vars]
ansible_user=deploy
ansible_ssh_private_key_file=~/.ssh/prod_key
# Ad-hoc commands — run commands without a playbook
ansible all -i hosts.ini -m ping

# Output:
# web1.example.com | SUCCESS => {
#     "changed": false,
#     "ping": "pong"
# }
# web2.example.com | SUCCESS => { "ping": "pong" }
# db1.example.com | SUCCESS => { "ping": "pong" }

# Check system uptime
ansible webservers -i hosts.ini -m shell -a "uptime"

# Copy a file to all servers
ansible all -i hosts.ini -m copy -a "src=/etc/hosts dest=/tmp/hosts"

Playbooks

Playbooks are YAML files that define automation workflows:

---
- name: Configure web server
  hosts: webservers
  become: yes
  vars:
    nginx_port: 8080
    app_version: "1.2.3"

  tasks:
    - name: Install Nginx
      apt:
        name: nginx
        state: present
      notify: Restart Nginx

    - name: Create app directory
      file:
        path: /var/www/myapp
        state: directory
        owner: www-data
        group: www-data
        mode: "0755"

    - name: Deploy application config
      template:
        src: nginx.conf.j2
        dest: /etc/nginx/sites-available/myapp
      notify: Restart Nginx

    - name: Enable site
      file:
        src: /etc/nginx/sites-available/myapp
        dest: /etc/nginx/sites-enabled/myapp
        state: link
      notify: Restart Nginx

    - name: Check if app is responding
      uri:
        url: "http://localhost:{{ nginx_port }}/health"
        status_code: 200

  handlers:
    - name: Restart Nginx
      service:
        name: nginx
        state: restarted
# Run the playbook
ansible-playbook -i hosts.ini webserver.yml

# Output:
# PLAY [Configure web server] ************************************************
# TASK [Install Nginx] *******************************************************
# changed: [web1.example.com]
# TASK [Create app directory] ************************************************
# ok: [web1.example.com]
# ...
# PLAY RECAP *****************************************************************
# web1.example.com : ok=5 changed=3 unreachable=0 failed=0

Output: Each task reports ok (no change needed) or changed (Ansible made a change). This is idempotency — running the playbook again produces no changes unless the server state drifts from the desired state.

Variables and Templates

# group_vars/webservers.yml — variables per server group
---
nginx_port: 8080
app_domain: "app.example.com"
ssl_cert_path: "/etc/ssl/certs/{{ app_domain }}.pem"
{# templates/nginx.conf.j2 — Jinja2 template #}
server {
    listen {{ nginx_port }};
    server_name {{ app_domain }};

    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
    }

    location /health {
        return 200 "healthy\n";
    }
}

Roles — Reusable Automation

Roles organize playbooks into reusable components:

# Create a role structure
ansible-galaxy init nginx

# Output:
# nginx/
# ├── tasks/
# │   └── main.yml
# ├── handlers/
# │   └── main.yml
# ├── templates/
# ├── files/
# ├── vars/
# │   └── main.yml
# ├── defaults/
# │   └── main.yml
# └── meta/
#     └── main.yml
# nginx/tasks/main.yml
---
- name: Install Nginx
  apt:
    name: nginx
    state: present

- name: Configure Nginx
  template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
  notify: Restart Nginx

- name: Start Nginx
  service:
    name: nginx
    state: started
    enabled: yes
# playbook.yml — using the role
---
- hosts: webservers
  become: yes
  roles:
    - role: nginx
      vars:
        nginx_port: 8080
    - role: app_deploy

Common Mistakes

  1. Not using become: yes for system-level tasks: Installing packages, editing system configs, and restarting services require root. Forgetting become: yes causes permission denied errors.

  2. Writing non-idempotent tasks: A task that appends to a file without checking if the line already exists will add duplicates on every run. Use lineinfile or blockinfile modules instead of shell.

  3. Storing secrets in plaintext variables: Never put passwords or API keys in playbooks. Use Ansible Vault (<a href="/devops/ansible/">ansible</a>-vault encrypt) or external secret managers.

  4. Not using handlers for service restarts: Calling service: state=restarted in a task restarts the service every run. Handlers only restart when a task reports changed.

  5. Running playbooks against production without --check: The --check flag does a dry run. Always run <a href="/devops/ansible/">ansible</a>-playbook --check --diff to see what changes will be made before executing.

Practice Questions

  1. What does it mean for Ansible to be "agentless"? Answer: Ansible doesn't require software installed on managed nodes. It connects via SSH and runs Python scripts that are removed after execution.

  2. How do handlers differ from regular tasks? Answer: Handlers run only when notified by a task that reports changed. They run once, at the end of the play, even if multiple tasks notify them.

  3. What is the purpose of an inventory file? Answer: The inventory defines which servers Ansible manages, groups them logically (webservers, databases), and specifies connection variables (user, key, port).

  4. How does Ansible ensure idempotency? Answer: Each module checks the current state before making changes. If the desired state matches the current state, no change is made. Running the same playbook twice is safe.

Challenge

Automate a LAMP stack deployment: create an inventory with one server, write a playbook that installs Apache, MySQL, and PHP, configure virtual hosts with a Jinja2 template, deploy a PHP application from Git, set up a firewall with ufw module, use Ansible Vault to store the MySQL root password, and test idempotency by running the playbook twice.

FAQ

Does Ansible work with Windows?

: Yes. Ansible manages Windows nodes via WinRM instead of SSH. Control node must be Linux/macOS.

What is Ansible Tower / AWX?

: Tower is Red Hat's enterprise UI for Ansible. AWX is the open-source upstream. Both provide dashboards, RBAC, and scheduling for playbooks.

How does Ansible compare to Terraform?

: Ansible focuses on Configuration Management (installing software, configuring settings). Terraform focuses on infrastructure provisioning (VMs, networks, clouds). They complement each other.

Can Ansible manage Docker containers?

: Yes. The docker_container, docker_image, and docker_compose modules manage containers. For complex Orchestration, pair Ansible with Docker Compose or Kubernetes.

Is Ansible free?

: Yes. Ansible Core is open-source (MIT license). Ansible Automation Platform (formerly Tower) is commercial.

Try It Yourself

# Install Ansible locally
sudo apt install ansible -y

# Create a local inventory
echo -e "localhost ansible_connection=local" > hosts.ini

# Run a ping test
ansible all -i hosts.ini -m ping

# Run a playbook that creates a file
ansible localhost -m file -a "path=/tmp/ansible-test state=touch"
ls -la /tmp/ansible-test

What's Next

Topic Description
{{< card link="../terraform" title="Terraform" icon="code" >}} Infrastructure provisioning alongside Ansible
{{< card link="../docker-compose" title="Docker Compose" icon="code" >}} Container Orchestration with automation

Related topics: Bash, Linux, AWS, Docker

What's Next

Congratulations on completing this Ansible tutorial! Here's where to go from here:

  • Practice daily — Consistency is more important than long study sessions
  • Build a project — Apply what you learned by building something real
  • Explore related topics — Check out other tutorials in the same category
  • Join the community — Discuss with other learners and share your progress

Remember: every expert was once a beginner. Keep coding!

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro