<p>Ansible <strong>facts</strong> are data collected about the (target) systems on which Ansible takes actions. They are variables, but set by Ansible (in a way like <em><strong>system defined variables</strong></em>). They are collected during <code>Gathering Facts</code> stage of a playbook run, and it is controlled by the <code>gather_facts</code> setting. Ansible calls this <a href="https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#id26" rel="noreferrer">variables discovered from systems</a>. That said, it is possible to set custom facts also.</p>
<p>Some examples are:</p>
<ul>
<li><code>ansible_hostname</code> - the FQDN of the target system</li>
<li><code>ansible_os_family</code> - the Operating System family of target system (RedHat, Debian, etc.)</li>
</ul>
<p>The other <strong>variables</strong> are the ones we can set as per our requirement (in a way like <em><strong>user defined variables</strong></em>).</p>
<p>Some examples are:</p>
<ul>
<li><code>my_fav_fruits: [ 'orange', 'apple', 'banana' ]</code> - yours might differ.</li>
<li><code>config_dir: '/etc/my_app/conf.d'</code> - for my application configuration files.</li>
</ul>
<hr />
<p><strong>Update:</strong></p>
<p><em>Updating answer to make it relevant to the edit(s) made in question.</em></p>
<p>As <a href="https://devops.stackexchange.com/a/12393/23904">@Bruce Becker's answer</a> rightly pointed out, there is a difference in the precedence of variables set with <code>set_fact</code>. Also variables that need to be set at &quot;run time&quot; can be set this way. Without further explanation, taking your example variables, if I create a play like below:</p>
<pre class="lang-yaml prettyprint-override"><code>- hosts: localhost
  vars:
    nginx_ssl: '/etc/nginx/ssl'
    nginx_conf_file: '/etc/nginx/nginx.conf'

  tasks:
  - name: set nginx path to /opt when running on Debian
    set_fact:
      nginx_ssl: '/opt/nginx/ssl'
      nginx_conf_file: '/opt/nginx/nginx.conf'
    when: ansible_distribution == 'Debian'
  - debug:
      msg: 'ssl: {{ nginx_ssl }} and conf: {{ nginx_conf_file }}'
</code></pre>
<p>Then the <code>set_fact</code> variables will take precedence (on Debian) and output will be:</p>
<pre><code>&quot;msg&quot;: &quot;ssl: /opt/nginx/ssl and conf: /opt/nginx/nginx.conf&quot;
</code></pre>
<p>On other distributions, it will be what was declared in <code>vars:</code>.</p>

CC BY-SA 4.0
2020-09-12T11:14:52.413Z
Understood the context now. I updated my answer too.
seshadri_c
CC BY-SA 4.0
2022-02-25T16:44:42.353Z
"On other distributions, it will be what was declared in vars:." I don't understand this statement. Why whould it be different on other distributions like Redhat for example?
timothepoznanski
CC BY-SA 4.0
2022-03-03T15:06:45.220Z
The vars declared in the `vars:` section of the play have lower precedence than `set_fact`, so it will be what was declared under `vars:`, unless it is overridden with `set_fact` again for Redhat,
seshadri_c
CC BY-SA 4.0
2020-09-11T15:24:19.200Z
2020-09-12T17:42:51.410Z
2020-09-12T17:42:51.410Z
seshadri_c
<p>Not to contradict anything written in <a href="https://devops.stackexchange.com/a/12389/354">@Ceshadri_C's answer</a>, but to focus more on the difference between facts and variables - perhaps the <a href="https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable" rel="nofollow noreferrer">variable precedence</a> page could be of greater insight.</p>
<p><strong>The difference between facts and variables set is defined by their precedence</strong>, <em>i.e.</em> all variables are important, but some variables are more important than others. In your case, <em>the same variable</em> set as a fact (priority 19) would take precedence declared as a variable in a task (priority 17) or play (priority 12).</p>

CC BY-SA 4.0
2020-09-12T07:06:42.037Z
2020-09-12T07:06:42.037Z
Bruce Becker
<p>Facts are also made available to subsequent plays. Variables are not.</p>

CC BY-SA 4.0
2023-06-14T04:52:36.060Z
2023-06-14T04:52:36.060Z
JonnyBuoy
<p>While I'm using Ansible for quite some time, I'm not sure I really understand the differences between a variable and a fact.</p>
<p>Would it be any difference doing</p>
<pre class="lang-yaml prettyprint-override"><code>- set_fact:
    nginx_ssl: /etc/nginx/ssl
    nginx_conf_file: /etc/nginx/nginx.conf
</code></pre>
<p>or</p>
<pre class="lang-yaml prettyprint-override"><code>  vars:
    nginx_ssl: /etc/nginx/ssl
    nginx_conf_file: /etc/nginx/nginx.conf
</code></pre>
<p>Could someone explain me, possibly with an example where it really make a difference ?</p>

<ansible><variables>
ansible: difference between a variable and a fact
Baptiste Mille-Mathias
# ansible: difference between a variable and a fact

(Asked by: username_0 on 2020-09-11)

While I'm using Ansible for quite some time, I'm not sure I really understand the differences between a variable and a fact.
Would it be any difference doing
- set_fact:
    nginx_ssl: /etc/nginx/ssl
    nginx_conf_file: /etc/nginx/nginx.conf

or
  vars:
    nginx_ssl: /etc/nginx/ssl
    nginx_conf_file: /etc/nginx/nginx.conf

Could someone explain me, possibly with an example where it really make a difference ?

**Tags:** ansible, variables


---

## 3 answers

### Answer by username_1 on 2020-09-11. Score: 7

Ansible facts are data collected about the (target) systems on which Ansible takes actions. They are variables, but set by Ansible (in a way like system defined variables). They are collected during Gathering Facts stage of a playbook run, and it is controlled by the gather_facts setting. Ansible calls this variables discovered from systems. That said, it is possible to set custom facts also.
Some examples are:

ansible_hostname - the FQDN of the target system
ansible_os_family - the Operating System family of target system (RedHat, Debian, etc.)

The other variables are the ones we can set as per our requirement (in a way like user defined variables).
Some examples are:

my_fav_fruits: [ 'orange', 'apple', 'banana' ] - yours might differ.
config_dir: '/etc/my_app/conf.d' - for my application configuration files.


Update:
Updating answer to make it relevant to the edit(s) made in question.
As @username_3's answer rightly pointed out, there is a difference in the precedence of variables set with set_fact. Also variables that need to be set at "run time" can be set this way. Without further explanation, taking your example variables, if I create a play like below:
- hosts: localhost
  vars:
    nginx_ssl: '/etc/nginx/ssl'
    nginx_conf_file: '/etc/nginx/nginx.conf'

  tasks:
  - name: set nginx path to /opt when running on Debian
    set_fact:
      nginx_ssl: '/opt/nginx/ssl'
      nginx_conf_file: '/opt/nginx/nginx.conf'
    when: ansible_distribution == 'Debian'
  - debug:
      msg: 'ssl: {{ nginx_ssl }} and conf: {{ nginx_conf_file }}'

Then the set_fact variables will take precedence (on Debian) and output will be:
"msg": "ssl: /opt/nginx/ssl and conf: /opt/nginx/nginx.conf"

On other distributions, it will be what was declared in vars:.

> **Comments:**
> **username_1**: Understood the context now. I updated my answer too.  
> **username_2**: "On other distributions, it will be what was declared in vars:." I don't understand this statement. Why whould it be different on other distributions like Redhat for example?  
> **username_1**: The vars declared in the `vars:` section of the play have lower precedence than `set_fact`, so it will be what was declared under `vars:`, unless it is overridden with `set_fact` again for Redhat,  

---

### Answer by username_3 on 2020-09-12. Score: 3

Not to contradict anything written in [@Ceshadri\_C's answer](https://devops.stackexchange.com/a/12389/354), but to focus more on the difference between facts and variables - perhaps the [variable precedence](https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable) page could be of greater insight.

**The difference between facts and variables set is defined by their precedence**, *i.e.* all variables are important, but some variables are more important than others. In your case, *the same variable* set as a fact (priority 19) would take precedence declared as a variable in a task (priority 17) or play (priority 12).


---

### Answer by username_4 on 2023-06-14. Score: 1

Facts are also made available to subsequent plays. Variables are not.


---

