KodeKloud Engineer Day 92: Managing Jinja2 Templates Using Ansible.
Hey Everyone! I have taken up the kodekloud engineer daily challenge [100 days of Devops] and through this series, we shall slowly but…
KodeKloud Engineer Day 92: Managing Jinja2 Templates Using Ansible.
Hey Everyone! I have taken up the kodekloud engineer daily challenge [100 days of Devops] and through this series, we shall slowly but steadily start solving the daily challenges.
Here’s the link to get started with the challenge: https://engineer.kodekloud.com/practice
Day #92 Task: Managing Jinja2 Templates Using Ansible.
One of the Nautilus DevOps team members is working on to develop a role for
httpdinstallation and configuration. Work is almost completed, however there is a requirement to add a jinja2 template forindex.htmlfile. Additionally, the relevant task needs to be added inside the role. The inventory file~/ansible/inventoryis already present onjump hostthat can be used. Complete the task as per details mentioned below:
a. Update
~/ansible/playbook.ymlplaybook to run thehttpdrole onApp Server 2.
b. Create a jinja2 template
index.html.j2under/home/thor/ansible/role/httpd/templates/directory and add a lineThis file was created using Ansible on <respective server>(for exampleThis file was created using Ansible on stapp01in case ofApp Server 1). Also please make sure not to hard code the server name inside the template. Instead, useinventory_hostnamevariable to fetch the correct value.
c. Add a task inside
/home/thor/ansible/role/httpd/tasks/main.ymlto copy this template onApp Server 2under/var/www/html/index.html. Also make sure that/var/www/html/index.htmlfile's permissions are0744.
d. The user/group owner of
/var/www/html/index.htmlfile must be respective sudo user of the server (for exampletonyin case ofstapp01).
Note:Validation will try to run the playbook using commandansible-playbook -i inventory playbook.ymlso please make sure the playbook works this way without passing any extra arguments.

Day #92 Task: Managing Jinja2 Templates Using Ansible.
Let’s understand a few things, before working on this task.
What is Jinja2?
Jinja2 is a tool that allows you to create dynamic files using variables, conditions, and loops instead of hardcoding everything. Without Jinja, you’ll have to write multiple config/template files for multiple setups. With Jinja, one template file works for all servers dynamically. You can think of it as a document template with blanks to fill automatically, (which will be done so, by Ansible, in our case).
Now, there’s another difference to be spotted with this challenge. In all our previous challenges, we were directly adding the tasks in the playbook.yml file and it executes, when we trigger it. In this challenge, we are making use of the Ansible role structure, where the playbook only calls the role, and the actual tasks, templates, files, and configurations are organized inside separate role directories like tasks/, templates/, files/, etc.
This makes automation more modular, reusable, and easier to manage in real production environments. Now let’s move on to solving the task.
Step-1: Verify the existing inventory file.
Let’s just check the content of the existing inventory file.
thor@jump-host ~/ansible$ cat inventory
stapp01 ansible_host=stapp01 ansible_ssh_pass=Ir0nM@n ansible_user=tony
stapp02 ansible_host=stapp02 ansible_ssh_pass=Am3ric@ ansible_user=steve
stapp03 ansible_host=stapp03 ansible_ssh_pass=BigGr33n ansible_user=banner
This means that the playbook that we’ll create will run on all the three app-servers.
Step-2: Edit the playbook, jinja file and the roles file with the defined requirements.
Let’s checkout the existing playbook file and the task file.
# Let's check out the existing playbook file.
thor@jump-host ~$ cat ~/ansible/playbook.yml
# Content of the playbook.yml file.
---
- hosts:
become: yes
become_user: root
roles:
- role/httpd
# Let's check out the httpd task file and see what kind of tasks will be executed.
# We need to make a note as to what to add in this file.
thor@jump-host ~/ansible$ cat role/httpd/tasks/main.yml
---
# tasks file for role/test
- name: install the latest version of HTTPD
yum:
name: httpd
state: latest
- name: Start service httpd
service:
name: httpd
state: started
From this, we can observe that there are certain things that needs to be added/modified in all these files. Let’s go through them step-by-step.
In the playbook.yml, we need to add the host as stapp02 as it’s mentioned in the problem statement. For the roles, it’ll automatically pick up, what ever task is defined in *~/role/httpd*path. So, let’s modify the playbook.yml to run in App server 02.
# Let's edit the playbook.yml file.
thor@jump-host ~$ vi ~/ansible/playbook.yml
# Content of the playbook.yml file.
---
- hosts: stapp02
become: yes
become_user: root
roles:
- role/httpd
Now, let’s create the jinja file *index.html.j2in path:`/home/thor/ansible/role/httpd/templates/`*.
# Let's create the jinja file index.html.j2in path:/home/thor/ansible/role/httpd/templates/.
thor@jump-host ~/ansible$ vi role/httpd/templates/index.html.j2
# Content of the jinja file:-
This file was created using Ansible on {{ inventory_hostname }}
# This file will pick up, whichever host the playbook is running on.
Let’s move on to the tasks file now. It needs to pick up the template from the jinja file that we created and also need to change the ownership and permission of the file.
# Modify the tasks file.
thor@jump-host ~/ansible$ cat role/httpd/tasks/main.yml
# Content of the task file.
---
# tasks file for role/test
- name: install the latest version of HTTPD
yum:
name: httpd
state: latest
- name: Start service httpd
service:
name: httpd
state: started
# Added this to pick up the jinja file and modify the ownership and permission.
- name: Deploy index.html template
template:
# Take a Jinja2 template file, render its variables, and copy the final generated file to the remote server (App Server 02, in this case).
src: index.html.j2
dest: /var/www/html/index.html
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
mode: '0744'
Step-3: Validate the execution of the playbook against the inventory file.
Check in the app server 02, before executing the playbook file, if any such file exists.
# Check if there exists any file in the /var/www/html path in App Server 02.
thor@jump-host ~$ cat ansible/inventory
stapp01 ansible_host=stapp01 ansible_ssh_pass=Ir0nM@n ansible_user=tony
stapp02 ansible_host=stapp02 ansible_ssh_pass=Am3ric@ ansible_user=steve
stapp03 ansible_host=stapp03 ansible_ssh_pass=BigGr33n ansible_user=banner
thor@jump-host ~$ ssh steve@stapp02
The authenticity of host 'stapp02 (10.244.234.245)' can't be established.
ED25519 key fingerprint is SHA256:07ELy86qBUSR3TQmn60CbIJgywNSoCzFuX6eKP9R+rg.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'stapp02' (ED25519) to the list of known hosts.
steve@stapp02's password:
[steve@stapp02 ~]$ sudo systemctl status httpd
Unit httpd.service could not be found.
[steve@stapp02 ~]$ ls /var/www/html
ls: cannot access '/var/www/html': No such file or directory
[steve@stapp02 ~]$ cat /var/www/html/index.html
cat: /var/www/html/index.html: No such file or directory
# Run the playbook and verify if the playbook is executed successfully.
thor@jump-host ~/ansible$ ansible-playbook -i inventory playbook.yml
PLAY [stapp02] **************************************************************************
TASK [Gathering Facts] ******************************************************************
ok: [stapp02]
TASK [role/httpd : install the latest version of HTTPD] *********************************
changed: [stapp02]
TASK [role/httpd : Start service httpd] *************************************************
changed: [stapp02]
TASK [role/httpd : Deploy index.html template] ******************************************
changed: [stapp02]
PLAY RECAP ******************************************************************************
stapp02 : ok=4 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
# Check if the file index.html is created in the /var/www/html path in App Server 02. Also verify the ownership and the permission of the file.
[steve@stapp02 ~]$ sudo systemctl status httpd
● httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; preset: d>
Active: active (running) since Mon 2026-05-25 10:47:43 UTC; 12s ago
Docs: man:httpd.service(8)
Main PID: 27606 (httpd)
Status: "Total requests: 0; Idle/Busy workers 100/0;Requests/sec: 0; Bytes>
Tasks: 177 (limit: 404712)
Memory: 14.9M
CPU: 72ms
CGroup: /system.slice/httpd.service
├─27606 /usr/sbin/httpd -DFOREGROUND
├─27788 /usr/sbin/httpd -DFOREGROUND
├─27791 /usr/sbin/httpd -DFOREGROUND
├─27794 /usr/sbin/httpd -DFOREGROUND
└─27797 /usr/sbin/httpd -DFOREGROUND
May 25 10:47:43 stapp02 systemd[1]: Starting The Apache HTTP Server...
May 25 10:47:43 stapp02 httpd[27606]: AH00558: httpd: Could not reliably determ>
May 25 10:47:43 stapp02 httpd[27606]: Server configured, listening on: port 80
May 25 10:47:43 stapp02 systemd[1]: Started The Apache HTTP Server.
[steve@stapp02 ~]$ cat /var/www/html/index.html
This file was created using Ansible on stapp02
[steve@stapp02 ~]$ ls /var/www/html
index.html
[steve@stapp02 ~]$ ls -la /var/www/html/index.html
-rwxr--r-- 1 steve steve 47 May 25 10:48 /var/www/html/index.html
That’s it for Day #92. Let’s hop on to the next challenge! See you there! Toodaloo!
메타데이터
- post_id
- a7c8e24ab8b4
- slug
- kodekloud-engineer-day-92-managing-jinja2-templates-using-ansible-a7c8e24ab8b4
- url
- https://medium.com/@janemils/kodekloud-engineer-day-92-managing-jinja2-templates-using-ansible-a7c8e24ab8b4
- canonical_url
- https://medium.com/@janemils/kodekloud-engineer-day-92-managing-jinja2-templates-using-ansible-a7c8e24ab8b4
- author_url
- https://medium.com/@janemils
- status
- ok
- fetched_at
- 2026-06-21 19:25:17