Skip to content
AyoKoding

Quick Start

Want to automate infrastructure management without writing complex scripts? This quick start introduces essential Ansible concepts through practical examples. You'll build from simple playbooks to multi-host automation workflows.

This tutorial provides 5-30% coverage using the touchpoints approach - 10 core concepts with runnable examples. After completing this guide, continue to By Example - Beginner for comprehensive 0-40% coverage.

Prerequisites

Before starting, ensure you have completed Initial Setup. You should have:

  • Ansible installed and verified
  • Experience running basic playbooks
  • Understanding of localhost targeting
  • A terminal and text editor ready

Learning Path

This quick start covers 10 essential Ansible touchpoints:

%% Color Palette: Blue #0173B2, Orange #DE8F05, Teal #029E73, Purple #CC78BC
graph TD
    A["1. Playbook Structure"] --> B["2. Inventory Files"]
    B --> C["3. Core Modules"]
    C --> D["4. Variables"]
    D --> E["5. Facts"]
    E --> F["6. Handlers"]
    F --> G["7. Conditionals"]
    G --> H["8. Loops"]
    H --> I["9. Roles"]
    I --> J["10. Vault"]
 
    style A fill:#0173B2,color:#fff
    style B fill:#0173B2,color:#fff
    style C fill:#029E73,color:#fff
    style D fill:#029E73,color:#fff
    style E fill:#DE8F05,color:#fff
    style F fill:#DE8F05,color:#fff
    style G fill:#CC78BC,color:#fff
    style H fill:#CC78BC,color:#fff
    style I fill:#0173B2,color:#fff
    style J fill:#DE8F05,color:#fff

Concept 1: Playbook Structure

What: YAML files declaring desired system state with plays and tasks.

Why: Foundation for all Ansible automation - declarative infrastructure as code.

Example: Multi-Task Playbook

Create playbook-structure.yml:

---
- name: Demonstrate playbook structure
  hosts: localhost
  gather_facts: false
 
  tasks:
    - name: Create directory
      ansible.builtin.file:
        path: /tmp/ansible-demo
        state: directory
        mode: "0755"
 
    - name: Create file with content
      ansible.builtin.copy:
        dest: /tmp/ansible-demo/info.txt
        content: |
          Ansible playbook executed successfully
          Timestamp: {{ ansible_date_time.iso8601 | default('Unknown') }}
        mode: "0644"
 
    - name: Display success message
      ansible.builtin.debug:
        msg: "Playbook completed - check /tmp/ansible-demo/info.txt"

Run:

ansible-playbook playbook-structure.yml

Key points:

  • One playbook file can contain multiple plays
  • Each play targets specific hosts
  • Tasks execute sequentially within a play
  • Idempotent - safe to run multiple times

Concept 2: Inventory Files

What: Define target hosts and groups for automation.

Why: Manage infrastructure at scale with organized host groupings.

Example: Static Inventory

Create inventory.ini:

# Web servers group
[webservers]
web1.example.com
web2.example.com
 
# Database servers group
[databases]
db1.example.com
db2.example.com
 
# All production servers
[production:children]
webservers
databases
 
# Group variables
[production:vars]
ansible_user=deploy
ansible_port=22

Create inventory-demo.yml:

---
- name: Inventory demonstration
  hosts: localhost
  gather_facts: false
 
  tasks:
    - name: Show inventory structure
      ansible.builtin.debug:
        msg: |
          Inventories organize hosts into groups
          Groups enable targeted automation
          Variables can be set per-group
          This playbook uses localhost as safe demo

Run with custom inventory:

ansible-inventory -i inventory.ini --list
 
ansible-playbook -i inventory.ini inventory-demo.yml

Key points:

  • Inventory organizes hosts into logical groups
  • Groups enable selective task execution
  • Variables set at group level apply to all hosts
  • INI or YAML format supported

Concept 3: Core Modules

What: Built-in functions performing specific infrastructure operations.

Why: Ansible's power comes from 3000+ modules for every task.

Example: Essential Modules

Create core-modules.yml:

---
- name: Core modules demonstration
  hosts: localhost
  gather_facts: false
 
  tasks:
    - name: File module - create directory
      ansible.builtin.file:
        path: /tmp/ansible-modules
        state: directory
        mode: "0755"
 
    - name: Copy module - write file
      ansible.builtin.copy:
        dest: /tmp/ansible-modules/data.txt
        content: "Sample data\n"
 
    - name: Lineinfile module - modify file
      ansible.builtin.lineinfile:
        path: /tmp/ansible-modules/data.txt
        line: "Added by lineinfile module"
        state: present
 
    - name: Command module - execute command
      ansible.builtin.command:
        cmd: cat /tmp/ansible-modules/data.txt
      register: file_content
      changed_when: false
 
    - name: Debug module - show output
      ansible.builtin.debug:
        var: file_content.stdout_lines

Run:

ansible-playbook core-modules.yml

Key points:

  • file: Manage files, directories, symlinks
  • copy: Copy files with inline content
  • lineinfile: Edit specific lines in files
  • command: Execute shell commands
  • debug: Display variables and messages
  • Each module is idempotent by default

Concept 4: Variables

What: Store reusable values for flexibility and parameterization.

Why: Make playbooks generic and environment-agnostic.

Example: Variable Usage

Create variables.yml:

---
- name: Variables demonstration
  hosts: localhost
  gather_facts: false
 
  vars:
    app_name: "myapp"
    app_version: "1.0.0"
    deploy_path: "/tmp/{{ app_name }}"
    config:
      port: 8080
      host: "localhost"
 
  tasks:
    - name: Create app directory
      ansible.builtin.file:
        path: "{{ deploy_path }}"
        state: directory
 
    - name: Create config file
      ansible.builtin.copy:
        dest: "{{ deploy_path }}/config.txt"
        content: |
          Application: {{ app_name }}
          Version: {{ app_version }}
          Port: {{ config.port }}
          Host: {{ config.host }}
 
    - name: Display deployment info
      ansible.builtin.debug:
        msg: "Deployed {{ app_name }} v{{ app_version }} to {{ deploy_path }}"

Run:

ansible-playbook variables.yml

Run with extra variables:

ansible-playbook variables.yml -e "app_version=2.0.0"

Key points:

  • Define with vars: keyword in play
  • Access with Jinja2 template syntax {{ variable }}
  • Override with -e flag at runtime
  • Support nested dictionaries and lists
  • Variable precedence: extra vars > play vars > inventory vars

Concept 5: Facts

What: Automatically gathered system information about target hosts.

Why: Make decisions based on OS, hardware, network configuration.

Example: Using Facts

Create facts.yml:

---
- name: Facts demonstration
  hosts: localhost
  gather_facts: true
 
  tasks:
    - name: Display operating system
      ansible.builtin.debug:
        msg: "OS: {{ ansible_distribution }} {{ ansible_distribution_version }}"
 
    - name: Display hostname
      ansible.builtin.debug:
        msg: "Hostname: {{ ansible_hostname }}"
 
    - name: Display Python version
      ansible.builtin.debug:
        msg: "Python: {{ ansible_python_version }}"
 
    - name: Display memory info
      ansible.builtin.debug:
        msg: "Total RAM: {{ ansible_memtotal_mb }} MB"
 
    - name: Display CPU cores
      ansible.builtin.debug:
        msg: "CPU cores: {{ ansible_processor_vcpus }}"
 
    - name: Show all network interfaces
      ansible.builtin.debug:
        msg: "Interfaces: {{ ansible_interfaces | join(', ') }}"

Run:

ansible-playbook facts.yml

View all available facts:

ansible localhost -m ansible.builtin.setup

Key points:

  • gather_facts: true collects system info automatically
  • Facts stored in variables like ansible_*
  • Access facts with Jinja2 templates
  • Use for conditional logic based on OS/hardware
  • Disable with gather_facts: false for faster execution

Concept 6: Handlers

What: Tasks that run only when notified and only once per play.

Why: Restart services only when configuration changes occur.

Example: Handlers for Service Restart

Create handlers.yml:

---
- name: Handlers demonstration
  hosts: localhost
  gather_facts: false
 
  handlers:
    - name: Restart application
      ansible.builtin.debug:
        msg: "APPLICATION RESTARTED (simulated)"
 
    - name: Reload configuration
      ansible.builtin.debug:
        msg: "CONFIGURATION RELOADED (simulated)"
 
  tasks:
    - name: Create config directory
      ansible.builtin.file:
        path: /tmp/app-config
        state: directory
      notify: Reload configuration
 
    - name: Update application config
      ansible.builtin.copy:
        dest: /tmp/app-config/app.conf
        content: |
          port=8080
          debug=false
      notify:
        - Reload configuration
        - Restart application
 
    - name: Another task without changes
      ansible.builtin.debug:
        msg: "This task does not trigger handlers"

Run:

ansible-playbook handlers.yml

Key points:

  • Handlers run at end of play (after all tasks)
  • Only run when notified by notify: keyword
  • Run once even if notified multiple times
  • Execute in order defined, not order notified
  • Perfect for service restarts after config changes

Concept 7: Conditionals

What: Execute tasks only when specific conditions are met.

Why: Support multi-OS playbooks and environment-specific logic.

Example: Conditional Execution

Create conditionals.yml:

---
- name: Conditionals demonstration
  hosts: localhost
  gather_facts: true
 
  vars:
    environment: "production"
    enable_debug: false
 
  tasks:
    - name: Production-only task
      ansible.builtin.debug:
        msg: "Running in PRODUCTION mode"
      when: environment == "production"
 
    - name: Development-only task
      ansible.builtin.debug:
        msg: "Running in DEVELOPMENT mode"
      when: environment == "development"
 
    - name: Debug mode task
      ansible.builtin.debug:
        msg: "Debug logging enabled"
      when: enable_debug
 
    - name: Linux-specific task
      ansible.builtin.debug:
        msg: "Detected Linux system"
      when: ansible_system == "Linux"
 
    - name: Multiple conditions (AND)
      ansible.builtin.debug:
        msg: "Production Linux system"
      when:
        - environment == "production"
        - ansible_system == "Linux"
 
    - name: Multiple conditions (OR)
      ansible.builtin.debug:
        msg: "Either production OR debug enabled"
      when: environment == "production" or enable_debug

Run:

ansible-playbook conditionals.yml

Run with different environment:

ansible-playbook conditionals.yml -e "environment=development"

Key points:

  • Use when: keyword for conditions
  • Conditions use Jinja2 expressions
  • Multiple conditions: list for AND, or for OR
  • Combine with facts for OS-specific tasks
  • Skip tasks cleanly without errors

Concept 8: Loops

What: Execute same task multiple times with different inputs.

Why: Avoid repetitive task definitions for similar operations.

Example: Looping Through Lists

Create loops.yml:

---
- name: Loops demonstration
  hosts: localhost
  gather_facts: false
 
  vars:
    packages:
      - name: package1
        version: "1.0"
      - name: package2
        version: "2.0"
      - name: package3
        version: "1.5"
 
  tasks:
    - name: Create multiple directories
      ansible.builtin.file:
        path: "/tmp/loop-demo/{{ item }}"
        state: directory
      loop:
        - dir1
        - dir2
        - dir3
 
    - name: Create files with different content
      ansible.builtin.copy:
        dest: "/tmp/loop-demo/{{ item.name }}.txt"
        content: "Version: {{ item.version }}\n"
      loop: "{{ packages }}"
 
    - name: Loop with index
      ansible.builtin.debug:
        msg: "Item {{ idx }}: {{ item }}"
      loop:
        - first
        - second
        - third
      loop_control:
        index_var: idx
 
    - name: Loop dictionary
      ansible.builtin.debug:
        msg: "Key: {{ item.key }}, Value: {{ item.value }}"
      loop: "{{ {'a': 1, 'b': 2, 'c': 3} | dict2items }}"

Run:

ansible-playbook loops.yml

Key points:

  • loop: keyword iterates over lists
  • Access current item with {{ item }}
  • Loop over complex data structures (dictionaries)
  • loop_control provides additional options
  • Use index_var to access loop index
  • Prefer loop over deprecated with_* keywords

Concept 9: Roles

What: Organize playbooks into reusable, structured components.

Why: Share automation code across projects and teams.

Example: Creating and Using Roles

Create role structure:

mkdir -p roles/webserver/{tasks,handlers,templates,vars,defaults}

Create roles/webserver/tasks/main.yml:

---
- name: Create web directory
  ansible.builtin.file:
    path: "{{ web_root }}"
    state: directory
    mode: "0755"
 
- name: Deploy index page
  ansible.builtin.template:
    src: index.html.j2
    dest: "{{ web_root }}/index.html"
    mode: "0644"
  notify: Reload webserver

Create roles/webserver/handlers/main.yml:

---
- name: Reload webserver
  ansible.builtin.debug:
    msg: "Webserver reloaded (simulated)"

Create roles/webserver/templates/index.html.j2:

<!DOCTYPE html>
<html>
  <head>
    <title>{{ server_name }}</title>
  </head>
  <body>
    <h1>{{ server_name }}</h1>
    <p>Deployed by Ansible</p>
    <p>Environment: {{ environment }}</p>
  </body>
</html>

Create roles/webserver/defaults/main.yml:

---
web_root: /tmp/webserver
server_name: "Demo Server"
environment: "development"

Create roles.yml playbook:

---
- name: Roles demonstration
  hosts: localhost
  gather_facts: false
 
  roles:
    - role: webserver
      vars:
        server_name: "Production Web Server"
        environment: "production"

Run:

ansible-playbook roles.yml

Verify:

cat /tmp/webserver/index.html

Key points:

  • Roles organize automation into reusable units
  • Standard directory structure: tasks, handlers, templates, vars, defaults
  • Include roles with roles: keyword
  • Override role variables in playbook
  • Share roles via Ansible Galaxy
  • Role dependencies managed in meta/main.yml

Concept 10: Vault (Secrets Management)

What: Encrypt sensitive data in playbooks and inventory.

Why: Secure passwords, API keys, certificates in version control.

Example: Encrypted Variables

Create unencrypted file secrets.yml:

---
db_password: "super_secret_password"
api_key: "abc123xyz789"

Encrypt with Vault:

# Encrypt file
ansible-vault encrypt secrets.yml
 
# Enter password when prompted

Create vault-demo.yml:

---
- name: Vault demonstration
  hosts: localhost
  gather_facts: false
 
  vars_files:
    - secrets.yml
 
  tasks:
    - name: Use encrypted variable (safe - not displayed)
      ansible.builtin.debug:
        msg: "Database password is configured"
 
    - name: Create config with secret
      ansible.builtin.copy:
        dest: /tmp/app-config.txt
        content: |
          # Configuration file
          DB_PASSWORD={{ db_password }}
          API_KEY={{ api_key }}
        mode: "0600"

Run with vault password:

ansible-playbook vault-demo.yml --ask-vault-pass
 
echo "my_vault_password" > .vault-pass
ansible-playbook vault-demo.yml --vault-password-file .vault-pass
rm .vault-pass

Other vault operations:

ansible-vault view secrets.yml
 
ansible-vault edit secrets.yml
 
ansible-vault decrypt secrets.yml
 
ansible-vault rekey secrets.yml

Key points:

  • Vault encrypts YAML files containing secrets
  • Use --ask-vault-pass or --vault-password-file
  • Encrypt entire files or specific variables
  • Safe to commit encrypted files to version control
  • Multiple vault IDs for different secret scopes
  • Never commit vault password files

Learning Path Summary

You've completed 10 essential Ansible touchpoints:

%% Color Palette: Blue #0173B2, Orange #DE8F05, Teal #029E73, Purple #CC78BC
graph TD
    A["Playbooks &<br/>Inventory"] --> B["Modules &<br/>Variables"]
    B --> C["Facts &<br/>Handlers"]
    C --> D["Conditionals &<br/>Loops"]
    D --> E["Roles &<br/>Vault"]
 
    style A fill:#0173B2,color:#fff
    style B fill:#029E73,color:#fff
    style C fill:#DE8F05,color:#fff
    style D fill:#CC78BC,color:#fff
    style E fill:#0173B2,color:#fff

Next Steps

Now that you understand core Ansible concepts:

  1. By Example - Beginner: Deep dive into 0-40% coverage with 25+ annotated examples
  2. By Example - Intermediate: Advance to 40-75% coverage with complex workflows
  3. By Example - Advanced: Master 75-95% coverage with enterprise patterns

Further Resources

Official Documentation:

Key Concepts:

  • Playbooks: YAML files declaring desired state
  • Inventory: Host and group organization
  • Modules: Built-in functions for infrastructure tasks
  • Variables: Parameterize playbooks for flexibility
  • Facts: Auto-discovered system information
  • Handlers: Conditional task execution (service restarts)
  • Roles: Reusable automation components
  • Vault: Encrypted secrets management

Summary

You've completed the Ansible Quick Start with 5-30% coverage! You now understand:

  • Playbook structure and multi-task workflows
  • Inventory organization and host grouping
  • Core modules for common operations
  • Variable definition and usage
  • Fact gathering and system information
  • Handlers for conditional actions
  • Conditional execution and loops
  • Role-based code organization
  • Vault secrets management

Continue your journey with comprehensive By Example tutorials for deeper mastery of Ansible automation.

Last updated January 28, 2025

Command Palette

Search for a command to run...