Jinja2 Usage in Ansible

Last updated: June 29, 2025

My Journey with Jinja2 Templates in Ansible

When I first started using Ansible, I quickly realized its power for automating system configurations. However, I also discovered that static configuration files weren't going to cut it in dynamic environments. That's when I began exploring Jinja2 templates in Ansible, and it completely changed my approach to configuration management.

In this blog post, I'll share my experience with Jinja2 templating in Ansible, demonstrating practical examples for both Linux and Windows environments. Whether you're managing a small homelab or enterprise infrastructure, mastering Jinja2 templates will elevate your automation capabilities significantly.

What is Jinja2?

Jinja2 is a modern and designer-friendly templating engine for Python. In the context of Ansible, it's the engine that powers template generation, variable expressions, and control structures in your playbooks and template files. With Jinja2, you can create dynamic configuration files that adapt based on host-specific variables, facts, and environment conditions.

The beauty of Jinja2 is that it combines the simplicity of templates with the power of programming constructs like conditionals and loops. This allows you to generate sophisticated configurations without duplicating code or resorting to complex scripting.

Jinja2 Delimiters and Syntax

Before diving into examples, let's understand the basic Jinja2 syntax used in Ansible:

  • {{ ... }} - For expressions (like variables, operations)

  • {% ... %} - For statements (like if conditions, for loops)

  • {# ... #} - For comments (won't appear in output)

  • # ... # - For line statements (alternative way to write statements)

Using Expressions with {{ ... }}

Expressions in Jinja2 are used to output values, such as variables, calculations, or function results. Here's a simple example:

You can also perform operations within expressions:

Using Statements with {% ... %}

Statements allow you to control the logic flow in templates with conditionals and loops:

Loops can be used to iterate through lists or dictionaries:

Using Comments with {# ... #}

Comments in Jinja2 templates don't appear in the final output:

Practical Examples for Linux and Windows

Let's look at some real-world examples of using Jinja2 templates in Ansible for both Linux and Windows environments.

Example 1: Configuring NGINX for Linux

Here's how you might create an NGINX configuration template:

And the corresponding playbook:

Example 2: Creating a Windows IIS Configuration

For Windows environments, you might create an IIS web.config template:

With the corresponding playbook:

Advanced Jinja2 Features

Filters in Jinja2

Jinja2 filters allow you to transform data within templates. They're applied using the pipe symbol (|). Ansible includes many built-in filters:

For Windows-specific work:

Control Structures and Conditionals

Jinja2 provides several control structures that can make your templates more powerful:

Practical Templating Workflow

Here's a practical sequence diagram showing how Ansible processes Jinja2 templates:

spinner

This sequence shows why Jinja2 templating is so powerful - it combines:

  1. Dynamic facts from target systems

  2. Variables defined in your playbooks, inventory, and other sources

  3. Template logic like conditionals and loops

  4. Consistent file deployment across multiple systems

Real-world Example: Multi-Environment Configuration

Let's put everything together with a more complex example that showcases how Jinja2 can help manage configurations across different environments (development, staging, production) for both Linux and Windows servers.

Configuration Template (config.j2)

Using the Template in a Playbook

Best Practices for Jinja2 Templates

After working extensively with Jinja2 templates in Ansible, here are some best practices I've found valuable:

  1. Keep Templates Readable: Add comments and organize your templates logically. What seems obvious today might be confusing months later.

  2. Use Default Values: Always provide default values for variables that might not be defined:

  3. Check If Variables Exist: Use conditionals to check if variables exist before using them:

  4. Use Indentation Consistently: Proper indentation makes templates much more readable:

  5. Use includes for Reusable Sections: Break down complex templates into smaller, reusable parts:

  6. Limit Logic in Templates: Keep complex logic in your playbooks or roles, and use simple logic in templates.

  7. Test Templates Before Deployment: Use the ansible-playbook --check mode to verify template rendering without making changes.

  8. Document Special Variables: Add comments for any special variables or conditionals in your templates.

Conclusion

Jinja2 templating is one of the most powerful features in Ansible, allowing you to create dynamic, adaptable configurations for diverse environments. By mastering Jinja2 syntax and combining it with Ansible's inventory, facts, and variables, you can build truly intelligent automation that adapts to your infrastructure's unique needs, whether you're working with Linux, Windows, or mixed environments.

I've found that the effort invested in learning and using Jinja2 properly has saved countless hours that would otherwise be spent maintaining duplicate configurations or writing complex scripts to handle variations between environments.

In my next blog post, I'll explore Ansible magic variables and how they can further enhance your automation workflows. Stay tuned!

Last updated