Answers: <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>
  
Answers: CC BY-SA 4.0
Answers: 2020-09-12T11:14:52.413Z
Answers: Understood the context now. I updated my answer too.
Answers: seshadri_c
Answers: CC BY-SA 4.0
Answers: 2022-02-25T16:44:42.353Z
Answers: "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?
Answers: timothepoznanski
Answers: CC BY-SA 4.0
Answers: 2022-03-03T15:06:45.220Z
Answers: 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,
Answers: seshadri_c
Answers: CC BY-SA 4.0
Answers: 2020-09-11T15:24:19.200Z
Answers: 2020-09-12T17:42:51.410Z
Answers: 2020-09-12T17:42:51.410Z
Answers: seshadri_c
Answers: <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>
  
Answers: CC BY-SA 4.0
Answers: 2020-09-12T07:06:42.037Z
Answers: 2020-09-12T07:06:42.037Z
Answers: Bruce Becker
Answers: <p>Facts are also made available to subsequent plays. Variables are not.</p>
  
Answers: CC BY-SA 4.0
Answers: 2023-06-14T04:52:36.060Z
Answers: 2023-06-14T04:52:36.060Z
Answers: JonnyBuoy
Body: <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>
  
Tags: <ansible><variables>
Title: ansible: difference between a variable and a fact
UserDisplayName: Baptiste Mille-Mathias
ThreadText: # 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
  
  ```yaml
  - set_fact:
      nginx_ssl: /etc/nginx/ssl
      nginx_conf_file: /etc/nginx/nginx.conf
  
  ```
  
  or
  
  ```yaml
    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](https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#id26). 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](https://devops.stackexchange.com/a/12393/23904) 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:
  
  ```yaml
  - 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.
  
  
  ---
  
  