Skip to content
Ansible Guide — Automation and Configuration Management

Ansible Guide — Automation and Configuration Management

DodaTech Updated Jun 7, 2026 7 min read

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
  
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 (ansible-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 ansible-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

TopicDescription
Terraform
Infrastructure provisioning alongside Ansible
Docker Compose
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