Driver FixRecommendedSound, Wi-Fi or graphics acting up? Check drivers firstFind missing or outdated drivers fast.Check DriversHalloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run Scan×
Skip to content
World desk12 min

How to Create and Use Templates in Ansible Playbooks

A practical, complete guide to Ansible templates: create UTF-8 .j2 files, interpolate variables and facts, add conditionals and loops, render safely, and choose between the template module and lookup.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Ansible templates are UTF-8 text files that combine fixed configuration text with Jinja2 expressions. An ansible.builtin.template task renders the file on the Ansible control node, substitutes variables and facts, and writes the resulting text to a managed host. A practical template workflow is therefore: create a .j2 file, provide its data through playbook or inventory variables, render it with src and dest, inspect the change, and then apply it.

This guide shows the complete workflow for playbooks and roles, including conditionals, loops, facts, filters, Windows behavior, whitespace control, the difference between the template module and template lookup, and checks to perform when upgrading ansible-core.

As an Amazon Associate I earn from qualifying purchases.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What an Ansible template does

Ansible uses Jinja2 templating to make dynamic expressions and access variables and facts. The template file remains ordinary text for the target application, while expressions such as {{ app_port }} are replaced during a run. Rendering occurs on the control node before the task is sent to the managed machine; the managed machine receives the rendered result rather than the original Jinja2 source.

A template is normally a UTF-8 file with a .j2 suffix. The suffix is a convention, not a requirement, but it makes the file’s purpose obvious to people and tooling. Keep the target application’s literal syntax unchanged and add Jinja2 only where output must vary.

#1 Best Overall
Sale
TOZO A1 Wireless Earbuds Bluetooth 5.3 Light Weight in Ear Headphones | IPX5 Waterproof,2 Mics for AI Calls,Immersive Premium Sound Bass Headset with Charging Case,32 EQ via App Black
  • [Ultra-Lightweight Ear Buds Designed for Small Ears] Each earbud weighs only 3.7g and features a compact, ergonomic in-ear design made especially for small ears. Secure, low-profile, and comfortable for workouts, all-day wear or overnight sleeping.The ultra-slim profile sits flush in your ear with no hard edges poking or rubbing, so you can even sleep on your side without discomfort.
  • [Immersive Stereo Sound with TOZO OrigX Technology] TOZO OrigX tuning delivers clear vocals, balanced mids, and natural stereo sound for music, podcasts, and videos.
  • [Long Battery Life for Daily Use] Get up to 7 hours of playtime on a single charge, with up to 32 hours total using the charging case—ideal for workdays, commuting, and extended listening sessions.
  • [Bluetooth 5.3 & Stable Connection] Bluetooth 5.3 provides fast pairing, stable wireless performance, and reduced dropouts as you move around home or office.
  • [Deep Bass with Clear Vocals] High-performance drivers produce punchy bass while keeping vocals clean and detailed for everyday listening.
  • Literal text: configuration keys, comments, and punctuation required by the target program.
  • Expressions: {{ variable_name }} inserts a value.
  • Statements: {% if %} and {% for %} control which lines are emitted.
  • Comments: {# explanation for the template author #} are removed from the rendered output.

Both the template file and any data read by the template module must be UTF-8 encoded. If a source file uses another encoding, convert it before running Ansible instead of trying to diagnose the resulting parser or character errors on the target host.

Minimal working example

Create this layout next to your playbook:

site.yml
templates/
  app.conf.j2

Define a variable and render the template with the fully qualified module name:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
---
- name: Deploy application configuration
  hosts: all
  vars:
    app_port: 8080
  tasks:
    - name: Render application configuration
      ansible.builtin.template:
        src: app.conf.j2
        dest: /etc/myapp/app.conf
        mode: '0644'

The corresponding templates/app.conf.j2 file can be:

port={{ app_port }}
host={{ ansible_facts['hostname'] }}

{% if inventory_hostname in groups['webservers'] %}
role=web
{% else %}
role=other
{% endif %}

With app_port set to 8080, Ansible gathers the current host name, evaluates the group membership test, and writes a normal text file such as port=8080, the host name, and either role=web or role=other. The official Ansible pattern uses this same combination of a templates directory, a .j2 file, the template module, src, dest, and a hostname fact.

Build a template step by step

1. Define the output contract

Start with the exact file the managed service expects: a service configuration, environment file, hosts file, or another text format. Write a static version first. This gives you a reference for required keys, quoting, indentation, separators, and trailing newlines before you introduce Jinja2.

2. Create the file in the correct templates directory

For a playbook, place the file in a templates/ directory associated with the playbook. For a role, place it in that role’s templates/ directory. The task’s src names the template relative to the location Ansible searches; do not point src at a file that exists only on the managed host.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Save the file as UTF-8. Keep the .j2 suffix unless a target application or an established project convention requires another name.

3. Supply the input data

Template values may come from several normal Ansible sources:

  • Playbook variables: values under vars for a small, local example.
  • Inventory and group variables: host-specific or group-specific settings.
  • Included variable files: data maintained separately from the playbook.
  • Registered results: output captured from an earlier task.
  • Command-line variables: values supplied with -e for a deployment-specific override.

Use variable names made from letters, numbers, and underscores. Avoid names that collide with Ansible or Jinja2 internals, and prefer descriptive names such as app_port or tls_certificate_path over one-letter names.

Rank #2
Sale
Smart Watch for Men Women Compatible with iPhone Samsung Android Phone 1.69 inch Full Touch Screen IP68 Waterproof Bluetooh Fitness Tracker Heart Rate/Sleep Monitor (Black)
  • 【IP68 Waterproof Multifunctinal Smart Watch】Torjalph fitness activity tracker smart watch is IP68 waterproof technology ,you can wear it when swimming,handwashing,it's rain-proof which means that you perform multiple exercise modes outside without worrying about sweat or rain corroding your fitness smart watch,and this watch equipped with a 230 mAh large capacity battery magnetic charging ,and this sports activity tracker watch can be used 5-7 days If fully charged.
  • 【Larger 1.83'' Full Screen Watch & Multi-dial Selection】1.83 inch full HD color touch screen smart watch for men / women provides excellent 240*284 resolution image quality ,This Bluetooth smart watch offers a better touch experience and remarkable immersion and ,more than 200 watch faces for you to choose from App"Da Fit ", you can change the dial style according to your mood to wear keeping the world on your wrist
  • 【Accurate Activity Tracker Smart Watch 】sports watch activity tracker uses sweat and dust resistant breathable silicone strap, our Fitness Tracker Smart Watch for Android iOS Phones supports 12 sports modes,walking,running,bicycle,swimming,badminton,basketball,football,rope skipping. This bluetooth calls smart watch for men women is lightweight and stylish, bringing more convenient and relaxing sports experience while also providing more protection.
  • 【Your 24 Hour Personal Daily Health Monitor】Fitness watch for women men full touch screen IP67 waterproof bluetooth smartwatch for Android iOS Phones with heart rate blood pressure monitor multifunction Andriod smart watch with steps counter sleep monitor sports fitness watch, monitoring blood oxygen saturation allows you to understand your physical condition in real time to track fitness progress ,to know your health status in time.
  • 【More Functions Bluetooth Call Smart Watch】This fitness activity smart watch full screen for iPhone and Android phones includes a bunch of new features including:The bluetooth smart watch can hang up the phone, receive and display WhatsAPP /Text /Facebook /Twitter /Messenger reminder.Support sedentary reminder, alarm clock, stopwatch, timer,weather information,music control, remote camera control compatible with Android 5.0 and above or iOS 9.0 and above smartphones.

4. Insert scalar and structured values

Use double curly braces for interpolation:

port={{ app_port }}
log_level={{ app_log_level }}

Nested dictionaries and facts can use bracket notation:

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
address={{ ansible_facts['eth0']['ipv4']['address'] }}

Dot notation can be convenient for simple keys, but bracket notation makes the key boundaries explicit and works well when a key contains characters that are not valid in a dotted expression. Ensure the fact or dictionary key exists for every host that will render the file. If a network interface is not consistently named, use a variable or a fact structure that is stable in your environment rather than hard-coding one interface name.

Filters transform a value to the syntax required by the destination. For example:

settings={{ application_settings | to_json }}
metadata:
{{ service_metadata | to_yaml }}

Choose a filter based on the target parser. JSON embedded in a JSON file, YAML embedded in a YAML file, or an unquoted value in an INI-style file each has different escaping requirements.

5. Put variation in Jinja2 statements

Use {% if %} when a line or block should appear only for some hosts:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
{% if enable_metrics %}
metrics_endpoint={{ metrics_endpoint }}
{% endif %}

Use {% for %} for repeated output:

allowed_user={{ item }}
{% for item in allowed_users %}
allowed_user={{ item }}
{% endfor %}

Keep indentation and blank lines intentional. Many target formats treat whitespace as significant, and even formats that ignore spaces can be difficult to review when templates emit accidental blank lines.

6. Add the template task

Use the fully qualified collection name:

- name: Render service configuration
  ansible.builtin.template:
    src: service.conf.j2
    dest: /etc/example/service.conf
    mode: '0644'

The FQCN avoids ambiguity if another collection provides a module with a similar short name. The module is designed to generate text files; it is not a general-purpose serializer for native Python or Jinja2 data types.

7. Preview and apply

Run a syntax check first, then use check and diff mode where the target and module support it:

ansible-playbook --syntax-check site.yml
ansible-playbook --check --diff site.yml
ansible-playbook site.yml

Check mode and diff mode are operational safeguards: they let you inspect the rendered text and the proposed file change before making it. Review diffs for secrets, unintended whitespace, missing variables, and changes outside the lines you expected.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #3
New Bee Guitar Cable 10ft Electric Instrument Bass AMP Cord
  • [Low Noise High Fidelity] New bee guitar cord with 22AWG oxygen-free-copper center conductors provides enhanced signal transfer, the PVC insulation material and the high-density stranded copper double shield provide noise rejection for quiet operation
  • [Ideal for Choice] New bee 1/4 straight and right angle metal connectors, ensures a secure connection in any instrument, pedal, or amp jack. L shape great fro on stage guitar stands
  • [Wide Compatible] Suitable for mixer, power amplifier, microphone, effector, decoder, equalizer, electoronic organ, electric guitar, electric bass and other electronic equipments. Widely used in the installation of smart home, karaoke speaker, professional stage audio, etc
  • [Easy Disassemble] Making incidental repairs quick and easy! Very nice, flexible cable
  • [Dont Hesite to Order] 24 hours customer services and professional technology team are standing by

Playbook templates versus role templates

Playbook-level organization

A playbook-level templates/ directory is useful when one playbook owns a small set of configuration files. The minimal example uses this arrangement. Keep the playbook and its templates together so a reader can find the source without searching a role collection.

Role-level organization

Reusable roles should put template files under the role’s templates/ directory and invoke them from tasks in that role:

roles/
  web_config/
    defaults/
      main.yml
    tasks/
      main.yml
    templates/
      app.conf.j2
# roles/web_config/tasks/main.yml
- name: Render application configuration
  ansible.builtin.template:
    src: app.conf.j2
    dest: /etc/myapp/app.conf
    mode: '0644'

Role defaults provide safe values that callers can override with inventory, group variables, included data, or extra variables. Keep the role’s template and the task that renders it together; this makes the reuse boundary clear and prevents a role from depending on an unrelated playbook directory.

How variables reach a template

The template does not fetch inventory or command-line data by itself. Ansible assembles the variable context for the host, and Jinja2 evaluates expressions against that context while rendering. A practical mapping looks like this:

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Data source Typical use Template expression
Playbook vars A value used by one play or a compact example {{ app_port }}
Inventory or group variables Different settings for environments or host groups {{ api_backend }}
Included variable file Separating larger or environment-specific data sets {{ database.host }}
Registered task result Rendering information discovered earlier in the run {{ command_result.stdout }}
Extra variables with -e Per-run overrides and deployment parameters {{ release_id }}
Ansible facts Host properties gathered at the start of a play {{ ansible_facts['hostname'] }}

If a play disables fact gathering, fact expressions such as ansible_facts['hostname'] will not be available unless you gather or define the needed data another way. Treat missing data as a template input problem: verify the variable name, its scope, and whether the host actually receives the variable source you intended.

Conditionals, loops, and host-specific output

Conditional sections

Conditionals are best for optional directives, platform-specific settings, and role- or group-specific lines. Include the complete line inside the conditional so the output cannot contain a key with an empty value accidentally:

{% if inventory_hostname in groups['webservers'] %}
role=web
{% else %}
role=other
{% endif %}

Repeated sections

Loops turn a list or dictionary into repeated text. A firewall template, for example, might emit one rule per host:

{% for host in groups['appservers'] %}
allow_host={{ host }} address={{ hostvars[host]['ansible_facts']['default_ipv4']['address'] }}
{% endfor %}

Always confirm that the facts referenced for every loop item are gathered and have the same shape. A host without the expected address fact can make the whole rendering task fail.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Do not confuse template loops with task loops

Ansible permits Jinja2 loops and conditionals in templates, but not as a substitute for YAML playbook structure. A template loop creates multiple lines in one output file; it does not create multiple Ansible tasks, retries, handlers, or remote commands. Use YAML task loops when each item needs its own module invocation, error handling, or notification, and use Jinja2 loops when the result is repeated text in one file.

Rank #4
BSIMB 15.6" Digital Family Calendar & Chore Chart, No Subscription Fees
  • Digital Family Calendar: BSIMB digital calendar wall touch screen puts an end to your chaotic life. Designed for busy families, the digital calendar keeps you organised and in step with your family. Assign different colours and tasks to each family member to make family scheduling easier and more intuitive.
  • Easy Setup and Auto-Sync: Plug in, connect to WLAN and auto-syn your electric calendar in minutes. Digital wall calendar compatible with Google calendar, iCloud calendar, Outlook calendar, Cozi calendar and Yahoo calendar. Add events directly on the device or through the ecalendar app. Electronic calendar stays current whether you're at work or traveling—no manual updates needed.
  • All-In-One Home Assistant: Smart calendar builds habits and encourage independence with personalised chores. Display daily meal plan to reduce the daily ‘What's for dinner?’ stress. To-do lists keep track of everything you want. Turning chores into valuable achievements with stars and rewards, making life easier and more enjoyable.
  • Manage Anytime Anywhere: BSIMB electronic calendar for family stay connected with the powerful ecalendar app. Access and manage your digital wall calendar anytime, anywhere with free features like stars & rewards, photo screensaver, chore charts, meals plans, to-do lists etc. Electronic planner paid features like Magic Import tailor advanced tools for users with special needs.
  • Stay in Touch with Loved Ones: Share photos or videos from your phone to electronic wall calendar with app, instantly update your life moment, and keep in touch with your family, especially those who are far away; you can also surprise your smart calendar digital wall by sending him a wish card; it's also great for keeping tech-illiterate elders in touch with the youngsters.

Template module behavior and useful options

The template module safely manages a destination file and can automatically decrypt Ansible Vault content used by the task. The rendered file is still text, so protect sensitive destinations with appropriate ownership and permissions in addition to encrypting source variables.

The most important parameters are:

  • src: the template source name, resolved on the control node.
  • dest: the path of the rendered file on the managed host.
  • mode: the destination permission mode, written as a quoted string such as '0644' to avoid YAML interpretation surprises.

Make sure the destination’s parent directory exists or create it in a preceding task. If a service needs to reload after a changed file, attach a handler to the template task rather than restarting it on every run.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Template module versus template lookup

Choose between the module and the lookup based on what you need to produce:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Decision point ansible.builtin.template module ansible.builtin.template lookup
Output purpose Renders text and writes a file to a managed host Retrieves rendered content as a value for another task or expression
Data shape Designed for text-file generation; native Jinja2 types are not used Supports native-type behavior when templated content must remain a data structure
Typical location A task that manages dest A variable assignment, argument, or other expression using lookup or query
Example ansible.builtin.template: src: app.conf.j2 dest: /etc/myapp/app.conf lookup('ansible.builtin.template', 'fragment.j2')

Use the module when the end result is a deployed text file. Use the lookup when a later task needs the rendered content itself, especially when native Jinja2 data types matter. The lookup supports lookup and query forms; verify the expected scalar or list shape before passing the result to another module.

Windows and newline behavior

For Windows targets, use ansible.windows.win_template rather than the POSIX-oriented template module. The Windows module defaults to CRLF newline sequences, which matches the normal Windows text convention. If a program requires a different newline style, set and test the appropriate option for that module and application.

Do not assume that a file rendered for Linux can be copied unchanged to Windows. Newline conventions, destination paths, permissions, and service reload mechanisms differ even when the Jinja2 expressions are identical.

Whitespace, delimiters, and files that contain Jinja-like text

Ansible has loaded templates with trim_blocks=True since Ansible 0.9. This removes the first newline after a block statement and can affect blank lines around {% if %} and {% for %}. Inspect the rendered diff when blank lines or indentation are significant.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

If the target file itself contains text that looks like Jinja2 syntax, put a special header at the top of the template to change delimiters or whitespace settings. For example:

#jinja2: variable_start_string: '[[', variable_end_string: ']]', trim_blocks: False
message = [[ message_text ]]

The header lets you preserve literal {{ and }} sequences required by another application while using alternate delimiters for the values Ansible must substitute. Keep the header as the first line and document the choice for future maintainers.

Validate a template before changing production files

  1. Check encoding: confirm that the template and included data are UTF-8.
  2. Check syntax: run ansible-playbook --syntax-check against the playbook.
  3. Check variable availability: verify names, host scope, group membership, and fact gathering.
  4. Render in check mode: use ansible-playbook --check --diff and read the rendered diff for every affected host.
  5. Test representative hosts: include hosts from each group or platform branch used by your conditionals.
  6. Apply and verify: run the play, confirm the destination content and permissions, and let the service validate or reload the configuration.

Check mode is not a replacement for the target application’s own configuration validator. If the service provides a syntax-test command, run it in a separate validation task before notifying a reload handler.

Troubleshooting common failures

Undefined variable

An error naming a variable means the value was not in the rendering context for that host. Check spelling and scope, then confirm that the inventory group, included variable file, registered result, or -e argument is actually used by the play. If a value is optional, guard the complete block with an {% if %} test and choose an explicit default appropriate for the target application.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Template not found

Verify the path and spelling under the playbook’s or role’s templates/ directory. The src value is resolved on the control node, so creating a file only on the managed host does not fix this error.

Unexpected blank lines or indentation

Inspect block placement, the module’s trim_blocks=True behavior, and whether a loop emits a newline before or after each item. Use whitespace controls deliberately and preview with --diff instead of guessing from the source.

Wrong value type in a later task

The template module writes text and does not preserve native Jinja2 types. If a subsequent task needs a list, dictionary, Boolean, or number rather than serialized text, retrieve the rendered content with the template lookup and use its native-type behavior, or keep the data structure as a normal variable instead of serializing it into a file first.

Facts are missing

Fact expressions fail when fact gathering is disabled, a fact is unavailable on a platform, or the key differs between hosts. Gather the required facts, select a stable fact, or pass the needed value explicitly as inventory data.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Rendered file works on one platform but not another

Check newline style, path syntax, permissions, and module choice. Windows targets generally require ansible.windows.win_template and its CRLF default; POSIX targets use the regular template module and POSIX file semantics.

Plan for ansible-core upgrades

Current ansible-core development documentation warns that version 2.19 introduced significant templating changes. Treat an ansible-core upgrade as a template compatibility change, not merely a controller package update.

  • Record the ansible-core version used to render the current files.
  • Run syntax checks, check mode, and diffs against representative inventories on the new version.
  • Pay particular attention to whitespace, undefined values, native-type assumptions, and templates that rely on older delimiter behavior.
  • Validate the resulting configuration with the target service before a broad rollout.

Keep the controller version, collections, and test inventory consistent in continuous integration so a templating change is detected before it reaches production.

Maintainable template patterns

  • Keep business decisions in clearly named variables and use short, readable Jinja2 blocks in the file.
  • Use filters such as to_yaml and to_json at the boundary where data enters a format, rather than manually assembling escaped text.
  • Prefer role templates for reusable components and a playbook-level directory for one-off deployments.
  • Use handlers for service reloads triggered by a changed template.
  • Review rendered diffs for secrets and set restrictive destination permissions where needed.
  • Document unusual delimiter headers and assumptions about facts, groups, and newline behavior.
  • Keep task orchestration, retries, and per-item module calls in YAML; keep text generation logic in Jinja2.

With these boundaries, a template remains easy to test: variables describe the desired state, Jinja2 describes how that state becomes text, and the template task owns delivery of the rendered file.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Outdated Drivers Are Slowing You DownFree scan - exact matches

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.