API & Automation·7 min read·

Ansible Variables, Facts, and Conditionals Explained

Use Ansible variables, auto-gathered facts, and when conditions to tune one playbook so it runs correctly across every host in your fleet.

NB

Netbay Developer Relations

Netbay Engineering

On this page

A playbook that hardcodes values works exactly once. Variables are what turn a single playbook into something you can run across a fleet where hosts differ in distribution, memory, and role. This post covers the three pieces Ansible uses to make that work: variables, facts, and conditionals.

Variables: Where You Define Them

Ansible reads variables from several places, and precedence rules decide who wins when the same name appears twice. From weakest to strongest: role defaults, inventory file groups, inventory host settings, play vars, then variables passed at the command line with -e. The practical rule is simple — put environment-wide defaults in group_vars, put one-off overrides on the ansible-playbook command line, and never fight the precedence ladder by redefining the same variable in five files.

A play can also define vars directly for a single run:

yaml
- name: Tune per-host services
  hosts: webservers
  gather_facts: true
  vars:
    nginx_port: 8080
    health_path: /healthz
  tasks:
    - name: Write nginx site config
      ansible.builtin.template:
        src: site.conf.j2
        dest: /etc/nginx/sites-enabled/site.conf
      notify: reload nginx
  handlers:
    - name: reload nginx
      ansible.builtin.service:
        name: nginx
        state: reloaded

The template referenced above can then print the port as {{ nginx_port }} inside a Jinja2 file without any shell quoting to worry about.

Facts: What Ansible Already Knows

Before it runs tasks, Ansible walks each host and records facts — the distribution, kernel version, total memory, IP addresses, and dozens more. These live under ansible_facts and let your playbooks adapt without you hardcoding anything. Facts are gathered once per play unless you disable them with gather_facts: false, which matters on very large fleets where gathering is the slowest phase.

bash
ansible webservers -i hosts.ini -m setup --tree facts/
ansible webservers -i hosts.ini -m debug -a 'var=ansible_facts.memtotal_mb'

The first command dumps every fact for the group into files, handy for inspection; the second prints one fact to the terminal. Custom facts are just files or scripts dropped into /etc/ansible/facts.d on the host, which is a clean way to let machine-local knowledge (a custom agent version, a license count) flow back into playbooks.

Conditionals with when

The when keyword gates a task on an expression. It reads variables, facts, or the result of a previous task, which is what makes a single playbook safe across heterogeneous hosts:

yaml
- name: Start nginx only on Ubuntu nodes
  hosts: webservers
  tasks:
    - name: Start nginx
      ansible.builtin.service:
        name: nginx
        state: started
      when: ansible_facts['distribution'] == "Ubuntu"

    - name: Add extra swap on small-memory hosts
      ansible.builtin.command:
        cmd: dd if=/dev/zero of=/swapfile bs=1M count=2048
      when:
        - ansible_facts['memtotal_mb'] < 2048
        - ansible_facts['distribution'] == "Ubuntu"

Expressions combine with the usual and, or, and not, and you can reference any registered result, so one play can branch on the outcome of the task before it. Notice the command task above is intentionally a one-shot; later posts in this series show why re-runnable alternatives like the swapfile module are usually the better call.

Variables, facts, and conditionals Playbook runs hosts: webservers Gather facts ansible_facts when condition distribution check run skip not satisfied

Takeaway

Master the trio in order: define variables in the weakest sensible place, lean on auto-gathered facts instead of assumptions, and gate everything uncertain behind when. The payoff is a single playbook you can trust across production and staging alike. To get realistic facts to play with, deploy a couple of Ubuntu test nodes on Netbay from the dashboard — netbayhosts.in provisions in under 60 seconds.

Keep reading

Follow along on a real VPS

Deploy Linux in under 60 seconds

These guides are written against Ubuntu, Debian, and RHEL-family images — the same ones on NetBay.

Deploy an instance