Ansible Templating

What are Ansible templates

When you are creating complex files, you can use templates that will be processed and filled with variables that you have set.

This provides much greater flexibility than using the copy command, which requires a file not to change, or using lineinfile which can be difficult to place lines in the correct place

The templates are written in Jinja2, and support most of features that it does.

Creating a basic template

Lets assume that we wanted to create an Nginx server block for each of the sites that we are setting up.

We would need to change the server name and root directive for each site, so we can create a template that would look something like this

1
2
3
4
5
6
7
server {
    listen       80;
    server_name  {{ domain_name }};
    root {{ project_path }};

## The rest of the config
}

This should be created at templates/etc/nginx/conf.d/server.conf.j2, and can be included in the playbook with the following command

1
2
3
4
5
6
- name: Configure nginx for the site
  template:
    src: templates/etc/nginx/conf.d/server.conf.j2
    dest: "/etc/nginx/conf.d/{{ domain_name }}.conf"
    owner: root
    group: root

Now as long as the domain_name and project_path variables have been set, the template will be populated with them and placed in the correct directory

Template Inheritance

As jinja is a templating language, we have access to more complicated features. A useful one is inheritance, which is shown below

Create your base template

Using the Nginx config from above, let's create a base template at templates/etc/nginx/conf.d/baseServerBlock.j2 that we will inherit from

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
server {
    listen       {% block port %}80{% endblock %};
    server_name  {{ domain_name }};
    root {{ project_path }};

{% block ssl_certificates %}{% endblock %}

{% block location %}

    location / {
        {% block custom_location_rules %}{% endblock %}
        try_files $uri @handler;
    }
{% block endblock %}

## The rest of the config
}

And then extend this for a SSL config file using the following template at templates/etc/nginx/conf.c/port443.j2

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
{% extends "etc/nginx/conf.d/baseServerBlock.j2" %}

{% block port %}443{% endblock %}

{% block ssl_certificates %}

    ssl on;
    ssl_certificate      "/etc/ssl/{{ domain_name }}/certificate.crt";
    ssl_certificate_key  "/etc/ssl/{{ domain_name }}/certificate.key";
{% endblock %}

{% block custom_location_rules %}

    auth_basic "Restricted Area";
    auth_basic_user_file /etc/nginx/htpasswd;
{% endblock %}

Then if we call the template with a domain name of example.com the following file would be generated

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
server {
    listen       443;
    server_name  example.com;
    root /var/www/vhosts/example.com;

    ssl on;
    ssl_certificate      "/etc/ssl/example.com/certificate.crt";
    ssl_certificate_key  "/etc/ssl/example.com/certificate.key";


    location / {
        auth_basic "Restricted Area";
        auth_basic_user_file /etc/nginx/htpasswd;

        try_files $uri @handler;
    }

## The rest of the config
}