Skip to main content
In this lesson, you’ll learn how to harness Jinja2 templates in Ansible to dynamically generate configuration files. Imagine a scenario where you need to set up web servers by deploying a web page (index.html) from your local machine to the default directory on each remote server (for instance, the default directory for nginx). We assume that nginx is already installed on these servers.

Basic File Copy Using the Copy Module

At first, you might use Ansible’s copy module to transfer a static index.html file to each web server. For example, your inventory file and playbook could be configured as follows:
The local index.html file might look like this:
When you run the playbook, the index.html file is copied over to all web servers, displaying a static message upon access.

Introducing Variables into the Web Page

Suppose the requirement changes and you now need to display the hostname and IP address dynamically on each web server. One solution might involve creating separate versions of the index.html file for each server. For example:
This approach is impractical for scalability since the files differ only by the hostname. The better solution is to use a variable within a template file.

Converting an HTML File into a Jinja2 Template

By creating one consolidated template file with a variable placeholder, you can avoid managing multiple static files. Rename your file to indicate its templated nature, for example, index.html-template or, even better, index.html.j2. Insert a Jinja2 variable for the server name:
Remember, once you convert your static HTML file into a Jinja2 template, it will no longer serve directly as a static file. It is meant to generate a customized file on each remote host. Therefore, it is best practice to add the “.j2” extension:
!!! note “Note” Using the copy module will not process variables in the template. To render the variables, you need to switch to the template module.

Using the Template Module

The template module is designed to process Jinja2 templates. It replaces the variables with real values and then copies the resulting file to the target server. Update your playbook as follows and use the built-in Ansible variable to automatically insert the current host’s name:
With this configuration, when you run the playbook, Ansible processes the template for each host. It replaces with the corresponding host’s name, generating a unique index.html file for every server.

What Happens During Execution

When executing the playbook, Ansible spawns a separate process for each host. This process gathers facts—such as inventory_hostname and other host-specific information—and then executes the tasks. The template module generates a personalized index.html file with the correct hostname, and subsequently copies the file to the designated directory (/var/www/nginx-default/index.html). For example, after processing, the rendered file for web1 might appear as:
Similar customized files will be created for web2 and web3.

Applying the Template Approach to Other Configuration Files

The templating techniques showcased for the web page can be applied to various other configuration files like nginx or Redis configurations. For instance, an nginx configuration file with variable placeholders might look like this:
For a Redis configuration file, you can utilize Jinja2 filters to provide default values:
When rendered, if no explicit value is provided for redis_port or tcp_keepalive, the configuration defaults to 6379 and 300 respectively:
You can also incorporate Jinja2 control structures. For example, to generate multiple nameserver entries in an /etc/resolv.conf file using a loop:
Given the following array of nameservers:
The rendered file would be:
!!! note “Best Practice” When using templates within roles, it is recommended to place them under the role’s templates directory for better organization and maintenance. To further enhance your understanding, try applying these techniques in a hands-on exercise with Ansible templates. This practical experience will help solidify your grasp on dynamically generating configuration files with Jinja2 and Ansible.

Watch Video

Practice Lab