Skip to content

Ansible Templates

Overview

Learn how to effectively use Jinja2 templates in Ansible for dynamic configuration management.

Basic Syntax

Simple Variable Substitution

# nginx.conf.j2
server {
    listen {{ http_port }};
    server_name {{ server_name }};
    root {{ web_root }};
}

Loops and Conditionals

# vhosts.conf.j2
{% for vhost in virtual_hosts %}
server {
    listen {{ vhost.port | default(80) }};
    server_name {{ vhost.domain }};

    {% if vhost.ssl | default(false) %}
    listen 443 ssl;
    ssl_certificate {{ vhost.ssl_cert }};
    ssl_certificate_key {{ vhost.ssl_key }};
    {% endif %}

    root {{ vhost.root }};

    {% for alias in vhost.aliases | default([]) %}
    server_alias {{ alias }};
    {% endfor %}
}
{% endfor %}

Advanced Features

Filters

# app.conf.j2
app_name: {{ application_name | upper }}
version: {{ version | default('1.0.0') }}
port: {{ port | string }}
memory_limit: {{ memory_limit | human_to_bytes }}
timestamp: {{ ansible_date_time.iso8601 }}
admin_email: {{ admin_email | regex_replace('@', ' at ') }}

Complex Data Structures

# config.yaml.j2
database:
  host: {{ db.host }}
  port: {{ db.port }}
  credentials:
    {% for user in db.users %}
    - username: {{ user.name }}
      permissions: {{ user.perms | join(', ') }}
    {% endfor %}

cache:
  {% for server in cache_servers %}
  - host: {{ server.host }}
    port: {{ server.port }}
    weight: {{ server.weight | default(1) }}
  {% endfor %}

Template Inheritance

{# base.conf.j2 #}
{% block server_config %}
server {
    listen 80;
}
{% endblock %}

{# site.conf.j2 #}
{% extends "base.conf.j2" %}
{% block server_config %}
server {
    listen {{ http_port }};
    server_name {{ server_name }};
}
{% endblock %}

Security Features

Escaping Content

# security.conf.j2
# HTML Escaping
description: {{ user_input | escape }}

# Shell Command Escaping
command: {{ shell_command | quote }}

# JSON Escaping
json_data: {{ data | to_json }}

Handling Sensitive Data

# database.conf.j2
{% if vault_enabled %}
password: {{ db_password | vault }}
{% else %}
password: {{ db_password }}
{% endif %}

Best Practices

Template Organization

templates/
├── nginx/
│   ├── nginx.conf.j2
│   ├── vhost.conf.j2
│   └── ssl.conf.j2
├── mysql/
│   ├── my.cnf.j2
│   └── users.sql.j2
└── app/
    ├── config.yml.j2
    └── environment.j2

Error Handling

# config.j2
{% if required_variable is defined %}
value: {{ required_variable }}
{% else %}
{% error "Required variable 'required_variable' is not defined" %}
{% endif %}

Documentation

{# 
  Template: nginx.conf.j2
  Purpose: Main NGINX configuration file
  Variables required:
    - http_port: Port for HTTP traffic
    - server_name: Server domain name
    - ssl_enabled: Boolean for SSL configuration
#}

Common Patterns

Environment Configuration

# environment.j2
{% for key, value in environment_vars.items() %}
export {{ key }}={{ value }}
{% endfor %}

Multi-Environment Support

# app_config.j2
{% if environment == 'production' %}
log_level: ERROR
debug: false
{% elif environment == 'staging' %}
log_level: INFO
debug: true
{% else %}
log_level: DEBUG
debug: true
{% endif %}

Dynamic Service Discovery

# haproxy.cfg.j2
backend web_servers
    {% for host in groups['webservers'] %}
    server {{ host }} {{ hostvars[host]['ansible_host'] }}:80 check
    {% endfor %}