Chapter 6: Deploying Files to Managed Hosts
Exercise: Deploying custom files with Jinja2 templates
You will write a small template for the message of the day and a playbook that deploys it, so that each machine greets its users with its own name, its distribution and the address of its owner.
The project ~/file-template has an ansible.cfg and this inventory:
[webservers]
servera.lab.example.com
[workstations]
workstation.lab.example.comDeploying custom files with Jinja2 templates
- Build a template file.
- Use the template file in a playbook.
Prerequisites: Complete control-node setup and the preceding lessons in this chapter. Run commands as student on workstation unless a step names another machine.
From the project directory, run the relevant home-lab check. For an exercise with several checkpoints, grade each state before changing or removing it:
lab grade file-templateThe grader reads project files and host state. A passing report covers the listed checks; also perform the task’s independent connection, repeat-run, and reboot checks where requested.
Add a host-specific owner email in host variables and verify only that host’s rendered message changes.
Record the published result first. The grader checks the original requirements, so a changed name or value may intentionally fail those checks.
Publish a host-specific login message with motd.yml and motd.j2.
- Every inventory host's
/etc/motdmust identify its FQDN, distribution and version, and thesystem_owneremail value. - The file must belong to root:root with mode
0644. - One reusable template must produce different facts for different hosts. Verify the rendered file and the message at login; a second run must make no change.
This play also manages workstation.lab.example.com itself, so it changes /etc/motd on workstation. rht-vmctl reset servers does not reset workstation; empty the file afterwards with sudo truncate -s 0 /etc/motd if you want it gone.
Review the inventory
[student@workstation ~]$ cd ~/file-template
[student@workstation file-template]$ cat inventory
[webservers]
servera.lab.example.com
[workstations]
workstation.lab.example.comWrite the template
Create motd.j2 in the project directory. It should use:
ansible_facts['fqdn']for the host's full name;ansible_facts['distribution']andansible_facts['distribution_version']for the Linux distribution;system_owner, the owner's email address, which the play will define.
This is the system {{ ansible_facts['fqdn'] }}.
This is a {{ ansible_facts['distribution'] }} version {{ ansible_facts['distribution_version'] }} system.
Only use this system with permission.
Please report issues to: {{ system_owner }}.Write the playbook
Create motd.yml. The play runs on all hosts as devops with privilege escalation, defines system_owner, and deploys motd.j2 to /etc/motd, owned by root:root with mode 0644.
---
- name: Configure SOE
hosts: all
remote_user: devops
become: true
vars:
- system_owner: clyde@example.com
tasks:
- name: Configure /etc/motd
ansible.builtin.template:
src: motd.j2
dest: /etc/motd
owner: root
group: root
mode: 0644Check the syntax
[student@workstation file-template]$ ansible-navigator run \
> -m stdout motd.yml --syntax-check
playbook: /home/student/file-template/motd.ymlRun the playbook
[student@workstation file-template]$ ansible-navigator run -m stdout motd.yml
PLAY [Configure SOE] ***********************************************************
TASK [Gathering Facts] *********************************************************
ok: [servera.lab.example.com]
ok: [workstation.lab.example.com]
TASK [Configure /etc/motd] *****************************************************
changed: [servera.lab.example.com]
changed: [workstation.lab.example.com]
PLAY RECAP *********************************************************************
servera.lab.example.com : ok=2 changed=1 unreachable=0 failed=0 ...
workstation.lab.example.com : ok=2 changed=1 unreachable=0 failed=0 ...Log in and read the message
Log in to servera as devops. The message of the day is printed at login, with servera's own values.
[student@workstation file-template]$ ssh devops@servera.lab.example.com
This is the system servera.lab.example.com.
This is a RedHat version 9.0 system.
Only use this system with permission.
Please report issues to: clyde@example.com.
...output omitted...
[devops@servera ~]$ exit[student@workstation file-template]$ ssh devops@servera.lab.example.com
This is the system servera.lab.example.com.
This is a Rocky version 9.8 system.
Only use this system with permission.
Please report issues to: clyde@example.com.
...output omitted...
[devops@servera ~]$ exitThe template is identical; the facts differ because the lab runs Rocky Linux.
Run it again
Run the playbook a second time. Both hosts report ok, changed=0: the rendered text matches the file that is already there.
Finish
Check your work with lab grade file-template, then put the exercise away with lab finish file-template.
Try it again, differently
Add a line to motd.j2 that prints the host's memory in GiB, rounded to one decimal place, from ansible_facts['memtotal_mb']. Then add a line that appears only on hosts in the webservers group. The template playground in the previous section is a quick place to work out the syntax first.