Aller au contenu
Infrastructure as Code medium

Module ansible.builtin.template : validate, backup, lstrip_blocks

11 min de lecture

Logo Ansible

Le module ansible.builtin.template est l’outil principal pour générer un fichier de configuration depuis un template Jinja2. Il prend un fichier .j2 côté control node, l’évalue avec les variables Ansible, et copie le résultat sur le managed node — avec les options classiques (mode, owner, group) plus des options spécifiques précieuses : validate: (rejette une config invalide avant écriture), backup: (préserve l’ancien fichier), lstrip_blocks: + trim_blocks: (whitespace control).

C’est l’alternative idiomatique à lineinfile: quand vous gérez plus de 2-3 lignes de config (voir lineinfile vs template).

  • Les paramètres essentiels : src, dest, mode, owner, group
  • validate: — rejeter un fichier généré invalide avant écriture
  • backup: true — conserver l’ancienne version
  • lstrip_blocks: + trim_blocks: — whitespace control automatique
  • force: false — ne pas écraser un fichier existant
  • Comment notifier un handler quand le template change
- name: Poser un fichier de config depuis un template
ansible.builtin.template:
src: templates/nginx.conf.j2
dest: /etc/nginx/nginx.conf
mode: "0644"
owner: root
group: root

src: est cherché dans cet ordre (depuis le playbook ou le rôle) :

  1. templates/nginx.conf.j2 (relatif au playbook ou au rôle)
  2. nginx.conf.j2 (relatif au playbook)

Le module évalue le template côté control node, puis copie le résultat. Idempotent : si le contenu généré est identique au fichier distant existant, changed=false.

- name: Mettre à jour sshd_config (avec validation)
ansible.builtin.template:
src: sshd_config.j2
dest: /etc/ssh/sshd_config
owner: root
group: root
mode: "0600"
validate: '/usr/sbin/sshd -t -f %s'
notify: Restart sshd

validate: '<commande> %s' lance la commande sur le fichier temporaire généré (%s est remplacé par le path temporaire). Si la commande échoue (exit ≠ 0), Ansible n’écrit pas le fichier final → vous ne vous bloquez pas hors du serveur si la config sshd est cassée.

Quelques validateurs utiles :

ServiceValidate
sshd/usr/sbin/sshd -t -f %s
nginx/usr/sbin/nginx -t -c %s
Apache/usr/sbin/httpd -t -f %s
Sudo/usr/sbin/visudo -cf %s
named (BIND)/usr/sbin/named-checkconf %s

Toujours poser un validate: sur les services critiques (sshd, nginx, sudoers) — c’est le filet de sécurité qui empêche le verrou complet.

- name: Update httpd.conf
ansible.builtin.template:
src: httpd.conf.j2
dest: /etc/httpd/conf/httpd.conf
backup: true

Si le fichier existe et change, Ansible crée d’abord /etc/httpd/conf/httpd.conf.<timestamp>~ avant d’écrire le nouveau contenu. Permet de revenir à l’ancienne version en cas de problème.

Le chemin du backup est retourné dans result.backup_file (avec register:) :

- name: Update et capturer le backup
ansible.builtin.template:
src: httpd.conf.j2
dest: /etc/httpd/conf/httpd.conf
backup: true
register: tpl_result
- name: Afficher le backup créé
ansible.builtin.debug:
msg: "Backup : {{ tpl_result.backup_file | default('aucun changement') }}"
- name: Template avec whitespace control auto
ansible.builtin.template:
src: motd.j2
dest: /etc/motd
lstrip_blocks: true # supprime les espaces avant les {% %}
trim_blocks: true # supprime le \n après les {% %}

Avec ces deux options activées, vous écrivez votre .j2 sans {%- / -%} partout — Jinja2 nettoie automatiquement les sauts de ligne. C’est la combinaison recommandée pour tout nouveau template.

Cf. Jinja2 — syntaxe de base pour le détail.

- name: Poser le fichier seulement si absent
ansible.builtin.template:
src: motd.j2
dest: /etc/motd
force: false

Avec force: false, le fichier n’est posé qu’une seule fois — au premier run. Les exécutions suivantes ne touchent pas au fichier, même s’il a été modifié à la main. Cas typique : laisser l’admin local faire des modifications post-déploiement.

Pattern restart-on-config-change (cf. Handlers) :

tasks:
- name: Update nginx.conf
ansible.builtin.template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
validate: '/usr/sbin/nginx -t -c %s'
backup: true
notify: Reload nginx
handlers:
- name: Reload nginx
ansible.builtin.systemd:
name: nginx
state: reloaded

Le notify: ne déclenche le handler que si le template a changé (idempotence du module). Au second run, changed=false → handler non déclenché.

Cas pratique — banner avec validate (lab ecrire-code/module-template)

Section intitulée « Cas pratique — banner avec validate (lab ecrire-code/module-template) »

Voici l’exemple validé sur le lab 29-ecrire-code-module-template :

- name: Challenge module template
hosts: db1.lab
become: true
vars:
motd_text: "Bienvenue !"
metadata:
generated: "2026-04-25"
owner: "ops-team"
tasks:
- name: Poser le banner via template
ansible.builtin.template:
src: templates/banner.txt.j2
dest: /etc/banner.txt
owner: root
group: root
mode: "0644"
backup: true
lstrip_blocks: true
trim_blocks: true

Avec templates/banner.txt.j2 :

====================
{{ motd_text }}
====================
{% for k, v in metadata.items() %}
{{ k | capitalize }}: {{ v }}
{% endfor %}

Sortie sur db1.lab dans /etc/banner.txt :

====================
Bienvenue !
====================
Generated: 2026-04-25
Owner: ops-team

Le lstrip_blocks: true + trim_blocks: true produit un fichier propre sans lignes vides indésirables.

SymptômeCauseFix
Could not find or access 'templates/foo.j2'Mauvais chemin de src:Vérifier la convention : templates/ à côté du playbook ou dans le rôle
validate: plante alors que la config semble bonneLa commande de validation a besoin de paths relatifsTester la commande à la main avec un fichier temporaire
backup: true ne crée pas de backupLe fichier n’a pas changé (idempotence)Comportement attendu : pas de backup si pas de changement
Whitespace pollué malgré lstrip_blocks: trueManque trim_blocks: trueToujours activer les deux ensemble
Permissions du fichier reset à chaque runFaux : si mode: est posé et conforme, changed=falseVérifier le mode: dans le module
  • ansible.builtin.template = src (.j2 côté control) + dest (managed node) + options.
  • validate: est le filet de sécurité — toujours l’utiliser sur sshd, nginx, sudoers.
  • backup: true préserve l’ancien fichier en <dest>.<timestamp>~.
  • lstrip_blocks: true + trim_blocks: true = whitespace control auto (combinaison recommandée).
  • notify: déclenche un handler uniquement si le template a changé — pattern restart-on-config-change.
  • force: false pose le fichier une seule fois (laisse les modifications locales intactes).

Cette page a un lab d’accompagnement : labs/ecrire-code/module-template/ dans stephrobert/ansible-training. Le challenge fait poser un /etc/banner.txt généré depuis un template Jinja2 avec backup: true, lstrip_blocks: true, trim_blocks: true.

Fenêtre de terminal
cd ~/Projets/ansible-training/labs/ecrire-code/module-template/
cat README.md
pytest -v challenge/tests/

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn