Dynamic Files with Jinja2
Jinja2 is a powerful templating engine used by Ansible. Instead of creating and maintaining dozens of static configuration files for different servers, you create one template, and Ansible dynamically injects the correct variables during execution.
Why do we need Jinja2?
Suppose you manage three different environments (Dev, Test, Prod). Each requires a configuration file with slightly different ports and debug modes.
The Static Nightmare
You would need to create and maintain three completely separate files (dev.conf, test.conf, prod.conf). As the number of servers scales up to 100+, maintaining multiple static files becomes impossible.
| Server Env | Port | Debug Mode |
|---|---|---|
| Dev | 8080 | true |
| Test | 8081 | true |
| Prod | 9090 | false |
How Jinja2 Works
# The values inside {{ }} are variables
PORT={{ app_port }}
DEBUG={{ debug }}[dev]
devserver app_port=8080 debug=true
[prod]
prodserver app_port=9090 debug=false---
- hosts: all
tasks:
- name: Generate configuration
template:
src: config.j2
dest: /tmp/config.confThe Output
The same template generates completely different files because Ansible provides different variable values for each server during execution.
- Dev Output
PORT=8080
DEBUG=true - Prod Output
PORT=9090
DEBUG=false
Where do the values come from?
Jinja2 does not read values directly from the server. It relies entirely on variables passed to it by Ansible. These variables can come from:
- Inventory files
group_varsandhost_varsdirectoriesvars:section inside a playbook- Extra variables passed via CLI (
-e) - Ansible Facts
Ansible Facts in Templates
# Facts are system data automatically collected by Ansible
$ Hostname: {{ ansible_hostname }}
$ IP Address: {{ ansible_default_ipv4.address }}
$ OS: {{ ansible_distribution }}
# Example Output rendered on the server:
Hostname: prod-server
IP Address: 192.168.1.10
OS: UbuntuJinja2 Syntax & Logic
Employee Name: {{ empname }}{% if environment == "production" %}
Debug=false
{% else %}
Debug=true
{% endif %}Users:
{% for user in users %}
- {{ user }}
{% endfor %}Rendered Loop Output
Users:
- alice
- bob
- charlieCopy Module vs Template Module
| Feature | Copy Module | Template Module (Jinja2) |
|---|---|---|
| Function | Copies the exact same static file to every server. | Generates a different, dynamic file for each server based on variables. |
| Source File | Usually a standard text file (.conf, .txt) | A Jinja2 template file (.j2) |
| Variables | Does not process variables inside the file. | Parses and replaces {{ variables }} and executes {% logic %}. |
| Code Example | - copy: src: config.conf dest: /tmp/config.conf | - template: src: config.j2 dest: /tmp/config.conf |
Real-Time Usage & Interview Prep
Common Use Cases
Jinja2 is heavily used in production environments to generate:
- Application configuration files (Nginx, Apache)
- Environment-specific properties (DB connections)
- System configuration files
- Custom shell scripts populated with server info