Ansible: Basic

Jun 20, 2026

Ansible usage examples with descriptive comments

#automation #configuration

Basic Ansible

# Verify inventory file / playbook syntax
ansible-inventory -i inventory.yaml --list
ansible-playbook <playbook-file> --check

# Run playbook
ansible-playbook -i <inventory-file> <playbook-file>

# Execute modules directly
ansible -i <inventory-file> -m <module-name> -a <module-args> <target>

# setup = Gather facts about target 
ansible -i inventory.yaml -m setup aws_linux_servers
ansible -i inventory.yaml -m setup -a 'filter=ansible_dns' aws_linux_servers

# Install collections
ansible-galaxy collection install cisco.ios
ansible-galaxy collection install -r requirements.yaml

# Vault
ansible-vault create vault.yaml
ansible-playbook -i inventory --vault-id @prompt playbook.yaml

playbook.yaml examples

# Collections
tasks:
- name: configure login banner
  cisco.ios.ios_banner:
	banner: login
	
# Tags; 
# running playbook with --tags ntp only the first task is run
- name: Enable and run ntpd
  ansible.builtin.service:
    name: ntpd
    state: started
    enabled: true
  tags: 
  - ntp
  - always    # will run unless skipped with --skip-tags=always
- name: Install NFS utils
  ansible.builtin.yum:
    name:
    - nfs-utils
    - nfs-util-lib
    state: present
  tags: 
  - filesharing
  - never    # Task won't run unless --tags=never 

# Loops
- name: add several users
	user:
	name: "{{ item.name }}"
	state: present
	groups: "{{ item.groups }}"
  loop:
	- { name: 'testuser1', groups: 'wheel' }
	- { name: 'testuser2', groups: 'root' }
	
# Vault 
# vault.yaml
username: user
password: secure
---
- hosts: switches
  connection: local
  vars_file:
	- vault.yaml
  vars:
    cli:
      username: "{{ username }}" # = user
      password: "{{ password }}" # = secure

# Register exit code of program
- name: Check if already present
  command: which docker
  failed_when: false
  changed_whene: false
  register: docker_available
# Use previous exit code to run task if docker is not available
- name: Download install script
  get_url:
    url: https://get.docker.com/
    dest: /tmp/get-docker.sh
    mode: u+x
  when: docker_available.rc == 1

Ansible Roles

ansible-galaxy init mccolly-example

common/               # this hierarchy represents a "role"
    tasks/            #
        main.yml      #  <-- tasks file can include smaller files if warranted
    handlers/         #
        main.yml      #  <-- handlers file
    templates/        #  <-- files for use with the template resource
        ntp.conf.j2   #  <------- templates end in .j2
    files/            #
        bar.txt       #  <-- files for use with the copy resource
        foo.sh        #  <-- script files for use with the script resource
    vars/             #
        main.yml      #  <-- variables associated with this role
    defaults/         #
        main.yml      #  <-- default lower priority variables for this role
    meta/             #
        main.yml      #  <-- role dependencies
    library/          # roles can also include custom modules
    module_utils/     # roles can also include custom module_utils
    lookup_plugins/   # or other types of plugins, like lookup in this case
	
# Usage
- hosts: webservers
  roles:
    - common
    - webservers
      
# Tags and roles
# !dynamic included roles won't inherit Tags!
- name: Static import cldop role
  import_role: cldop
  tags:
	- cldop
- name: Dynamic include cldop role
  include_role: cldop
	apply:
	  tags:
		- cldop
  tags:
    - cldop

requirements.yaml

collections:
  - cisco.ios                   # With just the collection name
  
  - name: geerlingguy.php_roles # With the collection name, version and source options
    version: 0.9.3
    source: https://galaxy.ansible.com

roles:
  - name: geerlingguy.java

Example AWS

all:
  children:
    webservers:
      hosts:
        ec2-98-81-199-113.compute-1.amazonaws.com:
        ec2-3-84-177-11.compute-1.amazonaws.com:
    loadbalancers:
      hosts:
        ec2-34-229-45-132.compute-1.amazonaws.com:
  vars:
    ansible_user: ec2-user
    ansible_ssh_private_key_file: ./my_ssh_key
- name: Play to install apache virtual hosts 
  hosts: webservers # targets
  become: true # defines privilege escalation to install as root
  vars:
    domain: example.com
    directories:
      - /var/www/{{ domain }}/html
      - /var/www/{{ domain }}/log
      - /etc/httpd/sites-available
      - /etc/httpd/sites-enabled
  tasks: # list of tasks
    - name: Install apache # task name
      ansible.builtin.dnf: # module
        name: httpd
        state: present

    - name: Create directories
      ansible.builtin.file:
        path: "{{ item }}"
        state: directory
        mode: "0655"
      loop: "{{ directories }}"

    - name: Copy the html content to the target using a template
      ansible.builtin.template:
        src: ./index.html.j2
        dest: /var/www/{{ domain }}/html/index.html
        mode: "0644"
    
    - name: Add line to Apache config
      ansible.builtin.lineinfile:
        path: /etc/httpd/conf/httpd.conf
        line: IncludeOptional sites-enabled/*.conf
    
    - name: Copy the virtual host file to the target using a template 
      ansible.builtin.template:
        src: ./virtual_host.conf.j2
        dest: /etc/httpd/sites-available/{{ domain }}.conf
        mode: "0644"
      notify: Restart apache

    - name: Create symlink
      ansible.builtin.file:
        src: /etc/httpd/sites-available/example.com.conf
        dest: /etc/httpd/sites-enabled/example.com.conf
        state: link
        mode: "0644"
      notify: Restart apache
     
    - name: Validating config
      ansible.builtin.command: httpd -t
      register: output
      changed_when: output.failed
      ignore_errors: true

    - name: Write error message
      ansible.builtin.fail:
        msg: "Wrong Apache Configuration"
      when: output.failed
    
  handlers:
    - name: Restart apache
      ansible.builtin.service:
        name: httpd
        state: restarted

Loadbalancer

- name: Play to install apache load balancer # play 1
  hosts: loadbalancers # targets
  become: true # defines privilege escalation to install as root
  vars:
    domain: example.com
  tasks: # list of tasks
    - name: Install apache # task name
      ansible.builtin.dnf: # module
        name: httpd
        state: present

    - name: Copy the load balancer configuration from template
      ansible.builtin.template:
        src: ./load_balancer.conf.j2
        dest: /etc/httpd/conf.d/lb.conf
        mode: '0644'
      notify: Restart apache

    - name: Validating config
      ansible.builtin.command: httpd -t
      register: output
      changed_when: output.failed
      ignore_errors: true

    - name: Write error message
      ansible.builtin.fail:
        msg: "Wrong Apache Configuration"
      when: output.failed
    
  handlers:
    - name: Restart apache
      ansible.builtin.service:
        name: httpd
        state: restarted

Templates

<VirtualHost *:80>
ServerName www.{{ domain }}
ServerAlias {{ domain }}
DocumentRoot /var/www/{{ domain }}/html
ErrorLog /var/www/{{ domain }}/log/error.log
CustomLog /var/www/{{ domain }}/log/requests.log combined
</VirtualHost>
ProxyRequests off
<Proxy balancer://webcluster >
ProxySet lbmethod=byrequests
{% for host in groups['webservers'] %}
BalancerMember http://{{host}}
{% endfor %}
</Proxy>
<Location /balancer-manager>
SetHandler balancer-manager
</Location>
ProxyPass /balancer-manager !
ProxyPass / balancer://webcluster/