Hello and welcome to the first in our series of Bitesize Ansible blog posts!

With these Bitesize Ansible posts, we hope to give people an easy access route to practicing with and gaining an understanding of, important Ansible concepts and best practices. So to kick things off, we're going to show you a really simple example of how the Template Module ( works and how to run it via a very simple playbook.

Before we begin, all of these examples will be hosted in our github library here; and if you need any help or have any questions, either comment on the post in question or email us at

Getting Started

In order to run through this example, you'll need python installed in your environment and then to install ansible using whichever package manager you're using for your distribution. For simplicity, we're using default python and pip as our package manager on a linux system.

* If you'd like some more structure info on using python to write code, we offer an in person training course to get you started here

Screen Shot 2019-03-19 at 19.36.44.png

Once you've got your Ansible install up and running, lets create a directory to hold our files;

Screen Shot 2019-03-19 at 19.36.51.png

All of the files apart from the jinja2 (.j2)template file and the inventory file (inventory) are written in YAML. This is the language of Ansible files and the key point to remember is that whitespace matters! Always ensure that your indents match up and you have the same amount of spaces for each of them.

Now, we're ready to Automate with Ansible!


Creating The Template

In this example, we're just going to create a little hello world html page to show you how jinja2 variable substitution works through the Ansible template module. So to start with, lets create the html page template we want to use. The below code snippet is an example of a template, so you can use this, or create one of your own. We're going to call our file html_template.j2;

Screen Shot 2019-03-19 at 19.39.08.png

For those of you that have written HTML before, you'll probably notice that there are some odd tags that have {{ }} in them. Good work! You've spotted the jinja2 template tags.

In Jinja2, all variables have double curly braces around them. Thus, our variable called website_username would be written as {{ website_username }}

Curly braces are special characters in Jinja2 and are reserved, along with some others, such as % (you can get more info on them and other syntax details here: Anything within the curly braces will be interpreted by the template module in Ansible as a variable and must be declared for the template module to succeed. This leads us on to where we define these variables...


I do declare! (Variables)

Variables are a massive and key, concept in the world of Ansible. They allow us to substitute in values to templates (like we're about to do here), perform simple and complex execution logic in single tasks or even whole plays or roles within a playbook. They have the ability to be overriden during execution and have a clearly defined precedence level. We won't go into detail about those features in this blog post, but we cover all the need to know aspects of variables in our Beginners Training Course

Our next objective is to create our website_vars.yml -  the file will contain declarations for all of the variables we've put in the HTML template you can see above. You can set these to whatever you want to, and even change the variable names, however, remember to update them in the template as well if you do;

Screen Shot 2019-03-19 at 19.40.21.png

You'll see that we've quoted some of the strings, particularly with non-alphanumeric characters in them, this is just to ensure they get interpreted as text, rather than any formula etc, now on to the playbook!

The Playbook

The following playbook is a simple example of how to execute the template module on the localhost using a template in the current directory to create a fully generated HTML file in the /tmp directory. For the purposes of simplicity, we're not going to collect facts (system information) about the host, so we have set gather_facts: false

Additionally, we have declared the variables file we created in the last step statically within the playbook, again for simplicity. We'll use an inventory file to set the connection type to local - Ansible by default attempts to use SSH, however, on localhost, we usually set it to default to the local connection_type for simplicity. As mentioned previously, we cover details like this more comprehensively in our Beginners Course

Finally, if you look at the task declaration for the template module, you'll see that we have only used the bare minimum src and dest parameters for the module. There are a great variety more options that can be declared, but for simplicity we've not included them here. This is the template_test.yml file;

Screen Shot 2019-03-19 at 19.41.15.png

For completeness, the inventory file contains the following to set the connection to local type;

Running with the (Ansible) pack

Now that we've got all our files in order, lets run the playbook!

All being well, you should now see Ansible go off and run the playbook and when it completes successfully, you should see the fully generated file in /tmp/hello_world.html or whichever path you set as the destination for the file. To open the file, startup your browser and enter file:///tmp/hello_world.html and you should see the webpage in all its glory! (tested on google chrome!)


What happens if our playbook doesn't work? Well, thankfully there are a few things we can try:

  1. Re-run your playbook with -vvvv before the -i inventory. This will output a verbose trace of the playbook run and should indicate any errors in the playbook run.

  2. Check the whitespace and indents on your playbook, remember whitespace matters!

  3. Check that your files are in the right place, with the right names and do the same for your variables

  4. If you're stuck, comment on this post or email us at

We hope that this has been useful and encouraging and we'd love to hear your feedback if you thought it was great and especially so if you thought it wasn't so great ( learning is a 2 way street!).

Follow us on LinkedInand on this blog for more updates about Ansible, Network Automation, Infrastructure as Code and all things DevOps!