In Ansible, facts are automatically gathered information pieces about the system that you are managing. These details generally include IP addresses, OS types, memory, disk size, and more. Facts act as the foundation for writing dynamic and responsive automation codes.
But instead of hardcoding values, you can make these variable decisions based on facts, enabling the playbooks to adapt to different environments, operating systems, and the infrastructure configurations.
There are two main types of facts in Ansible:
- Automatically gathered facts: Collected by the setup module when a playbook runs.
- User-defined facts: Created manually using tools like Ansible set_fact to store custom data during playbook execution.
In this guide, we shall walk through the basics of Ansible set_fact!
What Is Ansible set_fact
Ansible set_fact is a module that allows you to define variables, called facts, dynamically during playbook execution. Unlike variables defined in inventory files or playbooks, Ansible set_fact lets you assign values based on development conditions, task outputs, or other logic as the playbook runs.
These user-defined Ansible set_fact are stored temporarily for the duration of the playbook and are used like other regular variables. They are especially helpful for:
Get exclusive access to all things tech-savvy, and be the first to receive
the latest updates directly in your inbox.
- Storing intermediate results between tasks
- Creating conditional logic
- Simplifying complex expressions or control structures
For example:
– name: Set a dynamic fact
ansible.builtin.set_fact:
deploy_path: “/var/www/{{ inventory_hostname }}”
The above example, shows the deploy_path variable generated on the fly, allowing more flexible automation tailored to each host.
Basic Syntax of Ansible set_fact
The Ansible set_fact is used in a task within your playbook and follows a straightforward syntax. Here’s the basic structure:
– name: Set a fact
ansible.builtin.set_fact:
variable_name: value

- Example 1: Set a simple key-value pair
– name: Set custom greeting
ansible.builtin.set_fact:
greeting: “Hello, Ansible!”
This creates a variable named greeting with the value “Hello, Ansible!” that can be used in later tasks.
- Example 2: Use Jinja2 expressions
– name: Create a path using inventory hostname
ansible.builtin.set_fact:
full_path: “/opt/apps/{{ inventory_hostname }}”
Here, the fact is calculated dynamically using a Jinja2 expression.
- Example 3: Set multiple facts at once
– name: Set multiple facts
ansible.builtin.set_fact:
user_name: “admin”
user_shell: “/bin/bash”
Understanding the Difference: set_fact vs. ansible_facts
Feature | set_fact | ansible_facts |
Definition | Module used to define custom variables dynamically | Dictionary that stores automatically gathered facts |
Scope | Runtime-specific, per host | Automatically collected and host-specific |
Persistence | Temporary (during playbook execution) | Temporary unless manually saved |
How It’s Created | Explicitly with set_fact | Collected via the setup module |
Customization | Fully user-defined | Mostly system-generated |
Modifiable | Yes | Not directly editable (without override methods) |
Use Case | Store task output, conditional values, custom logic | Reference system info like IP, OS, CPU, etc. |
Syntax Example | set_fact: my_var: “value” | Accessed as ansible_facts[‘default_ipv4’] |
Using Ansible set_fact in Playbooks
The Ansible set_fact module is one of the most commonly used playbooks to define dynamic values and store intermediate results. Here is how you can integrate Ansible set_fact effectively within your playbooks.
Basic Usage in a Playbook
– name: Example Playbook Using set_fact
hosts: all
tasks:
– name: Set a static custom fact
ansible.builtin.set_fact:
app_path: “/opt/myapp”
– name: Display the custom fact
debug:
msg: “The application path is {{ app_path }}”
Using Output from a Previous Task
Using the output from the previous task, you can register it and then use Ansible set_fact to extract and process the value.
– name: Get system uptime
command: uptime
register: uptime_result
– name: Save the uptime output as a fact
ansible.builtin.set_fact:
system_uptime: “{{ uptime_result.stdout }}”
Conditionally Set a Fact
– name: Set fact only if a condition is met
ansible.builtin.set_fact:
status: “active”
when: ansible_os_family == “Debian”
Using set_fact with Loops
– name: Set dynamic fact inside a loop
ansible.builtin.set_fact:
port_{{ item }}: “{{ 8000 + item }}”
loop: [1, 2, 3]
This would result with facts like port_1, port_2, and port_3 being created with values 8001, 8002, and 8003.
Dynamic Variables with set_fact
Ansible set_fact is quite powerful when you need to define variables dynamically at runtime.
Example: Use with Conditions
– name: Set environment based on hostname
ansible.builtin.set_fact:
env: “production”
when: “‘prod’ in inventory_hostname”
Example: Use in Loops
– name: Set dynamic ports
ansible.builtin.set_fact:
“app_port_{{ item }}”: “{{ 8000 + item }}”
loop: [1, 2, 3]
These facts become:
app_port_1 = 8001, app_port_2 = 8002, etc.
Overriding Existing Facts
Using Ansible set_fact, you can easily override previously defined facts. Here is an intermediate example:
Example: Override a system fact
– name: Override ansible_hostname
ansible.builtin.set_fact:
ansible_hostname: “custom-host”
Persisting Facts Across Plays and Runs
By default, Ansible set_fact variables are usually only available during the current playbook run. If you want to persist them across plays or even different runs, you can make sure of fact caching.
Enable Fact Caching
In ansible.cfg:
[defaults]
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_facts
Mark Facts as Cacheable
– name: Set a persistent fact
ansible.builtin.set_fact:
my_cached_fact: “persistent value”
cacheable: yes
Use Cases for Ansible set_fact
The Ansible set_fact module is extremely useful for managing dynamic values throughout your playbooks. Here are some of the use cases that will help you out understand them better:
- Store Calculated Values
You can use Ansible set_fact to save results of expressions, task outputs, or runtime calculations.
Example:
– name: Calculate total disk space in GB
ansible.builtin.set_fact:
total_disk_gb: “{{ ansible_facts[‘devices’][‘sda’][‘size’] | int / 1024 }}”
This helps when you need to reuse calculated values in multiple places.
- Simplify Complex Conditionals
You can store values that are used repeatedly.
Example:
– name: Determine if the host is a production server
ansible.builtin.set_fact:
is_production: “{{ ‘prod’ in inventory_hostname }}”
Then use it cleanly later:
– name: Restart service in production
ansible.builtin.service:
name: myapp
state: restarted
when: is_production
- Control Flow Between Tasks
You can store an output from one task and use it to make important decisions.
Example:
– name: Check if file exists
ansible.builtin.stat:
path: /etc/myapp/config.yml
register: file_check
– name: Set config_exists variable
ansible.builtin.set_fact:
config_exists: “{{ file_check.stat.exists }}”
Later in the play:
– name: Load configuration if present
ansible.builtin.include_tasks: config_setup.yml
when: config_exists
Related Article: Ansible Cheat Sheet: A 2025 Complete Guide for Effective Automation
Common Mistakes and Troubleshooting
Even though Ansible set_fact is pretty easy to use, sometimes a few common issues can cause trouble. Here are the most common mistakes and a how-to guide to resolve them.
Mistake | Problem | Fix |
Referencing set_factvariables too early | Variables set with set_fact are only available after the task that defines them runs. | Ensure that any task referencing the fact comes after the set_fact task in the playbook. |
Incorrect variable name or syntax | Typos or incorrect syntax (e.g., missing curly braces) when referencing variables. | Always use the format {{ variable_name }} and double-check names. |
Overwriting critical facts unintentionally | Using set_fact to override built-in facts like ansible_hostname may cause issues. | Avoid using names of built-in Ansible facts for custom facts unless intentionally overriding. |
Using set_fact inside a loop without unique keys | In a loop, the fact gets overwritten in each iteration. | Use a list or dictionary to store each iteration’s result uniquely. |
Expecting set_fact to persist across plays by default | set_fact facts are temporary and do not persist across plays or runs. | Add cacheable: true to make facts persist:yaml<br>- name: Set a persistent fact<br> ansible.builtin.set_fact:<br> deployment_env: “staging”<br> cacheable: true<br> |
Wrapping Up – Ansible set_fact
Ansible set_fact is one of the most easy and straightforward tools out there that must be a part of your routine. Following and understanding this guide will enable you to easily navigate through facts and troubleshoot common issues.
How is set_fact
different from variables defined in vars
or defaults
?
Variables in vars
or defaults
are static, defined before playbook execution.set_fact
defines variables dynamically during runtime, based on task results or conditions.
Can I override an existing variable with set_fact
?
Yes, set_fact
can overwrite previously defined variables by assigning them new values during execution.
How do I set multiple facts at once in Ansible?
You can define multiple facts in one set_fact
task:- set_fact: var1: "value1" var2: "value2"