Skip to main content

Command Palette

Search for a command to run...

Ansible Part 3 - Variables, Because Hardcoding is a TRAP!

Updated
4 min read
Ansible Part 3 - Variables, Because Hardcoding is a TRAP!
A
DevOps engineer focused on building, automating, and securing cloud infrastructure. I work with AWS, Docker, Terraform, and CI/CD pipelines to ship scalable and reliable systems. I write about cloud services & architecture, deployment strategies, and real-world DevOps practices.

Variables are what turn a playbook from a one-trick script into something genuinely reusable. This part covers everything you need to know about them.


What is a Variable in Ansible?

Same concept as any programming language - a named container that holds a value.

In Ansible, you reference a variable like this, it is a Jinja2 syntax:

"{{ variable_name }}"

Way 1 - Inline Variables (vars:)

The simplest way, define variables directly in the playbook under vars section:

---
  - name: installing httpd package and creati9ng index file
    hosts: redhat
    vars:
      webserver_pack: httpd
    tasks:
      - name: installing httpd package
        yum:
          name: "{{ webserver_pack }}"
          state: present

      - name: starting http service
        service:
          name: "{{ webserver_pack }}"
          state: started
          enabled: true

      - name: creating index file
        lineinfile:
          path: /var/www/html/index.html
          line: "This is a test webserver"
          create: yes

Now if I want to switch from httpd to nginx, I just have to change one line.


Way 2 - External Variable Files (vars_files:)

Instead of defining variables inside the playbook, you put them in a separate YAML file and reference that file. The playbook stays clean, and the same variable file can be shared across multiple playbooks.

Create a external vars file:

# external_var.yml
webserver_pack: nginx

Reference it in your playbook:

---
  - name: installing httpd package and creati9ng index file
    hosts: redhat
    vars_files:
      - external_var.yml
    tasks:
      - name: installing httpd package
        yum:
          name: "{{ webserver_pack }}"
          state: present

      - name: starting http service
        service:
          name: "{{ webserver_pack }}"
          state: started
          enabled: true

      - name: creating index file
        lineinfile:
          path: /var/www/html/index.html
          line: "This is a test webserver"
          create: yes

The logic stays unchanged, only where the variable comes from is different. This is very useful when you have shared infrastructure varibles.


Way 3 - Command Line Variables (-e)

You can pass variables directly when running a playbook, overriding whatever's defined in the playbook or var files:

ansible-playbook 02-webserver.yml -e "webserver_pack=nginx"

This is useful for one-off overrides without touching any files.


Way 4 - host_vars and group_vars

Sometimes, different host need different values for same variables. In this case, you create a dir called host_vars, then create a file named after each host:

my-ansible-project/
├── ansible.cfg
├── hosts
├── host_vars/
│   ├── redhat.yml
│   └── ubuntu.yml
└── playbook.yml
# host_vars/redhat.yml
webserver_pack: httpd

# host_vars/ubuntu.yml
webserver_pack: nginx

Now when you run the same playbook against both hosts, each one uses its own value. Similarly, you can do it for group_vars.


The register keyword - Capturing the Output

The register keyword lets you capture the ansible output into a variable so you can use it later in the same playbook.

---
  - name: Uisng register variable to store output
    hosts: redhat
    tasks:
      - name: Creating a user named shinchan
        user:
          name: shinchan
          state: present
        register: user_output

      - name: printing user_output
        debug:
          var: user_output

debug module just print the variable value.

You can then reference specific fields in subsequent tasks like: {{ user_output.home }}


Variable Priority

Ansible lets you define the same variable in multiple places simultaneously, when they conflict, Ansible has a strict priority order.

1. -e on the command line  (highest)
2. ansible.cfg
3. vars: in the playbook
4. external vars_files
5. inventory file
6. host_vars
7. group_vars              (lowest)

A real-world example: you might have group_vars/all.yml with env: development as a safe default, and then pass -e "env=production" when running against your production inventory. The command line value overrides the group var, and your playbook doesn't need to change at all.


Next we'll get into Vault, Facts, and Conditionals, storing secrets encrypted with ansible-vault. Till then stay tuned! Keep Balling.