Skip to main content

RHCE Certification Course

Chapter #22: How to Create and Use Templates in Ansible

In this chapter, you will learn how to use Jinja2 templates in Ansible to automate the creation of dynamic and customized configuration files on managed nodes.

In this chapter, you will learn how to create and use templates in Ansible to create customized configurations on managed nodes.

Templating in Ansible is an easy and friendly way of pushing custom configurations to managed nodes running different systems with minimal editing of playbook files.

What is Templating in Ansible?

To get a better sense of what a template is, let’s consider an IT manager drafting an email to invite his department to a cocktail party. The email is sent to each of the members and also invites them to tag along with their spouses.

The email has been customized such that the body of the email remains the same, but the addressees and the names of their respective spouses vary. The email becomes the template, while the recipients and respective spouses are variables.

That was a generic example. Ansible uses Jinja2, which is a modern templating engine for Python frameworks used to generate dynamic content or expressions.

Templating is extremely useful when creating custom configuration files for multiple servers but unique for each of them.

Templates in Ansible are stored as .j2 files (Jinja2 templates) and are processed during the playbook run to produce final configuration files.

Jinja2 uses the double curly braces {{ ... }} to enclose a variable that has been defined. For comments, use {# #} and for conditional statements use {% … %}.

Note: Mistaken curly brace usage like {{# #} should be avoided; instead use {# This is a comment #}.

Let’s assume that you have a data model of VLANs in your network with host systems that you want to push to their respective VLANs as shown.

vlans:
  - id: 10
    name: LB
  - id: 20
    name: WB_01
  - id: 30
    name: WB_02
  - id: 40
    name: DB

To render this configuration, the corresponding Jinja2 template called vlans.j2 would appear as shown. As you can see, the variables vlan.id and vlan.name have been enclosed in curly braces.

vlan {{ vlan.id }}
  name {{ vlan.name }}

To iterate through the VLANs list in your template, use a loop. The full template might look like this:

{% for vlan in vlans %}
vlan {{ vlan.id }}
  name {{ vlan.name }}
{% endfor %}

Putting it all together in a playbook that places different host machines, this would appear as shown:

- hosts
  tasks:
    - name: Rendering VLAN configuration
      template:
         src: vlans.j2
         dest: "vlan_configs/{{ inventory_hostname }}.conf"

Example 1: Configuring Web Servers in Different Distros

In this example, we shall create index.html files that will display information about the hostname & the OS of 2 web servers running Rocky Linux & Ubuntu.

Setup:

Ubuntu - IP address: 173.82.202.239
Rocky Linux -  IP address: 173.82.115.165

The Apache web server has already been installed on both servers. So let’s create a playbook test_server.yml as shown.