Here’s a comprehensive tutorial on Ansible Templates and Jinja2, suitable for engineers or anyone preparing for an advanced Ansible role.
1. What are Ansible Templates?
Ansible templates are files written in Jinja2 templating language that allow you to generate dynamic configuration files or scripts on your managed hosts. Templates let you insert variables, run loops, add conditional logic, and more—creating configuration files that are customized to each host or environment.
Templates in Ansible typically have the .j2
extension and are processed using the template
module.
2. What is Jinja2?
Jinja2 is a powerful templating engine for Python. It allows embedding dynamic expressions and logic into text files (like configuration files, scripts, HTML, etc.).
Key Jinja2 features used in Ansible:
- Variable substitution
- Filters for modifying output
- Conditionals (
if
,else
) - Loops (
for
) - Includes for reusing template parts
3. Why Use Templates in Ansible?
- DRY (Don’t Repeat Yourself): Write one template, render differently for each host.
- Environment-specific files: Custom config for dev, staging, production, etc.
- Host-specific configuration: Each server gets a config with its own variables (IP, hostname, ports, etc.).
- Automate tedious file creation: No more manual editing!
4. Basic Usage of the Template Module
Syntax:
- name: Deploy custom configuration file
template:
src: myconfig.conf.j2
dest: /etc/myapp/myconfig.conf
Code language: JavaScript (javascript)
src
: Path to your template (relative totemplates/
directory in your role/playbook).dest
: Destination path on the remote host.
5. Example 1: Simple Variable Substitution
Template file: greeting.txt.j2
Hello, my name is {{ name }} and I am a {{ role }}.
Playbook snippet:
- name: Generate greeting file
hosts: all
vars:
name: "Rajesh"
role: "DevOps Engineer"
tasks:
- name: Create greeting file
template:
src: greeting.txt.j2
dest: /tmp/greeting.txt
Code language: JavaScript (javascript)
Resulting /tmp/greeting.txt
:
Hello, my name is Rajesh and I am a DevOps Engineer.
6. Example 2: Looping with Jinja2
Template file: servers.txt.j2
Server List:
{% for server in servers %}
- {{ server }}
{% endfor %}
Code language: PHP (php)
Playbook snippet:
- name: Render list of servers
hosts: localhost
vars:
servers:
- web01.example.com
- db01.example.com
- cache01.example.com
tasks:
- name: Create server list file
template:
src: servers.txt.j2
dest: /tmp/servers.txt
Code language: PHP (php)
Result:
Server List:
- web01.example.com
- db01.example.com
- cache01.example.com
Code language: CSS (css)
7. Example 3: Conditionals in Templates
Template file: nginx.conf.j2
server {
listen 80;
server_name {{ server_name }};
{% if enable_ssl %}
listen 443 ssl;
ssl_certificate {{ ssl_cert }};
ssl_certificate_key {{ ssl_key }};
{% endif %}
}
Code language: PHP (php)
Playbook snippet:
- name: Render NGINX config
hosts: all
vars:
server_name: "example.com"
enable_ssl: true
ssl_cert: "/etc/nginx/ssl/cert.pem"
ssl_key: "/etc/nginx/ssl/key.pem"
tasks:
- name: Deploy nginx.conf
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
Code language: JavaScript (javascript)
8. Example 4: Using Filters
Filters let you modify variable values on the fly.
Template example:
All uppercase: {{ mystring | upper }}
Reversed: {{ mylist | reverse }}
Comma separated: {{ mylist | join(', ') }}
Code language: JavaScript (javascript)
Playbook snippet:
vars:
mystring: "ansible"
mylist:
- a
- b
- c
Code language: JavaScript (javascript)
Result:
All uppercase: ANSIBLE
Reversed: c, b, a
Comma separated: a, b, c
9. Example 5: Template Directory Structure in Roles
A typical role with templates:
myrole/
├── tasks/
│ └── main.yml
├── templates/
│ ├── app.conf.j2
│ └── nginx.conf.j2
In tasks/main.yml
:
- name: Configure app
template:
src: app.conf.j2
dest: /etc/myapp/app.conf
Code language: JavaScript (javascript)
10. Advanced: Template Includes and Macros
You can include other templates or define macros for repeated sections.
For most playbooks, this isn’t needed, but Jinja2 supports it if you need.
11. Tips and Best Practices
- Always use variables, not hardcoded values, in templates.
- Test your templates with
ansible-playbook --check
before running in production. - Use comments in your
.j2
files ({# comment #}
) for clarity. - Store templates in the
templates/
directory for roles or in the same directory as your playbook for small projects.
12. Common Jinja2 Expressions for Ansible
Expression | Description |
---|---|
{{ var }} | Print a variable |
{% for item in list %} | Loop through a list |
{% if condition %} | Conditional logic |
`{{ var | upper }}` |
{# This is a comment #} | Jinja2 comment |
13. Troubleshooting
- Template syntax errors: If your template fails, Ansible will show the error. Check for missing
{% ... %}
or{{ ... }}
. - Variable undefined: Use
default
filter to avoid errors:{{ myvar | default('defaultvalue') }}
.
14. Further Reading
Summary:
- Ansible templates use Jinja2 for dynamic configuration files.
- You can use variables, loops, conditionals, and filters in
.j2
files. - The
template
module copies the rendered file to the remote host.

















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