Introduction to Ansible Templates and Jinja2
Ansible templates are powerful tools for creating dynamic configuration files and scripts based on variables and logic. Templates in Ansible use the Jinja2 templating engine, which enables you to programmatically control the contents of files generated during playbook runs. Jinja2 allows you to access variables, use conditional statements, loops, and filters, making your automation flexible and reusable.
What is Jinja2?
- Jinja2 is a modern, designer-friendly templating language for Python. In Ansible, it empowers the creation of files that can adapt based on the current data (like host variables or facts), supporting variables, logic, and complex data structures.
- Key Syntax:
{{ variable }}
for variable interpolation{% control structures %}
for logic (if, for, etc.)- Filters (e.g.,
{{ my_var | upper }}
)
Concepts and Features of Jinja2 in Ansible
- Variables: Insert values dynamically: text
Hello, {{ username }}!
- Expressions and Filters: Use built-in or custom filters to modify data: text
{{ mylist | join(', ') }}
- Conditionals: text
{% if is_admin %} You are an admin. {% else %} You are a user. {% endif %}
- Loops: text
{% for item in items %} - {{ item }} {% endfor %}
- Includes and Macros: Reuse chunks of templates.
Using Templates in Ansible
Templates in Ansible are typically stored as .j2
(Jinja2) files. The template
module copies these files to managed nodes, rendering them with variables and logic.
Basic Workflow
- Create the Template File
- Example:
templates/config.j2
textuser={{ app_user }} path={{ app_path }}
- Example:
- Reference in Playbook
- Use the
template
module: text- name: Copy app config template: src: config.j2 dest: /etc/myapp/config.cfg
- Use the
- Define Variables
- In inventory, playbook, or host/group vars: text
vars: app_user: alice app_path: /opt/myapp
- In inventory, playbook, or host/group vars: text
Practical Examples
1. Dynamic HTML Page
Template: templates/landing-page.html.j2
text<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{{ page_title }}</title>
<meta name="description" content="Created with Ansible">
</head>
<body>
<h1>{{ page_title }}</h1>
<p>{{ page_description }}</p>
</body>
</html>
Playbook:
text- name: Configure landing page
hosts: web
vars:
page_title: "Welcome"
page_description: "This is an Ansible-generated page"
tasks:
- name: Deploy HTML page
template:
src: landing-page.html.j2
dest: /var/www/html/index.html
Result: The index.html
on the target server will be customized per the defined vars.
2. Configuring Nginx Virtual Host with Logic and Loops
Template: templates/nginx_vhost.conf.j2
textserver {
listen {{ nginx_port }} default_server;
server_name {{ domain_name }};
root {{ document_root }};
index index.html index.htm;
access_log /var/log/nginx/{{ domain_name }}_access.log;
error_log /var/log/nginx/{{ domain_name }}_error.log;
location / {
try_files $uri $uri/ =404;
{% if enable_php %}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}
{% endif %}
}
}
Playbook:
text- name: Configure nginx virtual host
hosts: web_servers
vars:
nginx_port: 80
domain_name: "example.com"
document_root: "/var/www/html"
enable_php: true
tasks:
- name: Create Nginx configuration
template:
src: nginx_vhost.conf.j2
dest: /etc/nginx/sites-available/{{ domain_name }}.conf
Result: Nginx configs will dynamically adapt to each server or environment.
Advanced Jinja2 Usage in Ansible
- Facts: Use system facts collected by Ansible, e.g.,
{{ ansible_facts['os_family'] }}
- Dictionaries/Loops: Render configuration options dynamically: text
{% for opt in floaterm_options %} let g:{{ opt }} = {{ floaterm_options[opt] }} {% endfor %}
- Macros: Reuse complex snippets within templates.
- Includes/Extends: Organize and reuse base templates for consistency.
Best Practices
- Use clear variable names and document their purpose.
- Version control your templates for traceability.
- Leverage roles for reusability—combine variables, templates, and logic.
- Test templates locally using
ansible-playbook
in check mode or via dry runs.
Summary Table: Jinja2 Features in Ansible Templates
Jinja2 Feature | Example Syntax | Use-Case |
---|---|---|
Variables | {{ variable }} | Insert dynamic values |
Conditionals | {% if cond %}...{% endif %} | Show/hide content |
Loops | {% for item in items %}...{% endfor %} | Repeat content for lists |
Filters | `{{ var | upper }}` |
Includes | {% include "file.j2" %} | Code reuse within templates |
Macros | {% macro name(args) %}...{% endmacro %} | Reusable snippets |
Conclusion
Ansible templates powered by Jinja2 make configuration management dynamic, flexible, and adaptable. Mastering their syntax—along with how to combine variables, logic, loops, and facts—enables DevOps teams to automate at scale, reduce errors, and manage highly customizable infrastructure.
If you’re new, start with simple templates and gradually incorporate more advanced Jinja2 logic for maximum automation efficiency!
Refernece
- https://jinja.palletsprojects.com/en/2.11.x/
- https://codeburst.io/jinja-2-explained-in-5-minutes-88548486834e
- https://mydbops.wordpress.com/2019/04/17/jinja2-for-better-ansible/

















I’m a DevOps/SRE/DevSecOps/Cloud Expert passionate about sharing knowledge and experiences. I have worked at Cotocus. I share tech blog at DevOps School, travel stories at Holiday Landmark, stock market tips at Stocks Mantra, health and fitness guidance at My Medic Plus, product reviews at TrueReviewNow , and SEO strategies at Wizbrand.
Do you want to learn Quantum Computing?
Please find my social handles as below;
Rajesh Kumar Personal Website
Rajesh Kumar at YOUTUBE
Rajesh Kumar at INSTAGRAM
Rajesh Kumar at X
Rajesh Kumar at FACEBOOK
Rajesh Kumar at LINKEDIN
Rajesh Kumar at WIZBRAND