Sitemap
Babatunde

Babatunde

Aspiring Professional System Administrator RHCSA Linux | Windows Server | Automation | MS SQL Building real-world skills with discipline & consistency

Ansible Automation of Apache Web Server Deployment and Firewall Configuration on RHEL 10

9 min readJun 8, 2026

--

OBJECTIVE

The objective of this practical is to use Ansible to automate the installation and configuration of an Apache web server on remote RHEL 10 systems. The practical also demonstrates how to configure firewall settings and deploy a custom web page automatically using a single Ansible playbook.

INTRODUCTION

Ansible is an open-source automation tool used for configuration management, application deployment, and task automation. It allows system administrators to manage multiple servers from a single control node without manually logging into each server.

Ansible uses SSH to communicate with managed nodes and does not require any agent software to be installed on the remote systems. Automation tasks are written in YAML files known as playbooks.

The major advantage of Ansible is its ability to automate repetitive administrative tasks, reduce human errors, and maintain consistent configurations across multiple servers.

In this practical, Ansible will be used to:

  • Install Apache web server
  • Configure the firewall
  • Open HTTP access
  • Deploy a custom webpage

During this practical, the following activities were carried out:

  1. Installed Ansible on the RHEL 10 Control Node.
  2. Generated SSH keys for secure authentication.
  3. Configured passwordless SSH access to managed nodes.
  4. Created an Ansible inventory file.
  5. Tested communication between the control node and managed nodes.
  6. Created an Ansible playbook.
  7. Installed Apache Web Server automatically.
  8. Configured and enabled firewalld.
  9. Opened HTTP traffic through the firewall.
  10. Deployed a custom web page.
  11. Verified successful deployment of Apache services.

All tasks will be performed automatically on remote servers.

LAB SETUP:

  • Control Node: RHEL 10 system where Ansible is installed
  • Managed Node: Remote RHEL server managed by Ansible
  • Communication Method: SSH
  • Software Installed: Ansible

Managed Node 1:

  • IP Address: 192.168.65.134

Managed Node 2:

  • IP Address: 192.168.65.135

Web Service:

  • Apache HTTP Server (httpd)

Firewall Service:

  • firewalld

STEP 1 — INSTALL ANSIBLE

Before Ansible can be used, it must first be installed on the control node. RHEL uses the DNF package manager to install software packages.

Command:

sudo dnf install -y ansible-core
Press enter or click to view image in full size

Command Explanation:

  • sudo runs the command with administrative privileges.
  • dnf is the package manager used in RHEL systems.
  • install tells the system to install a package.
  • -y automatically accepts installation prompts.
  • ansible-core is the main Ansible package being installed.

VERIFY ANSIBLE INSTALLATION

After installation, the Ansible version is checked to confirm successful installation.

Command:

ansible --version
Press enter or click to view image in full size

Command Explanation:

  • ansible runs the Ansible program.
  • -version displays the installed version and configuration details.

STEP 2 — GENERATE SSH KEY

SSH keys are generated to enable secure passwordless authentication between the control node and managed nodes.

Command:

ssh-keygen
Press enter or click to view image in full size

Command Explanation:

  • ssh-keygen generates SSH public and private authentication keys.

STEP 3 — COPY SSH KEY TO MANAGED NODE

The SSH public key is copied to the remote server to allow automatic SSH login without entering passwords also run it on the control node server as well so the control node and the ssh server are sharing the same key.

Command:

ssh-copy-id srhel@192.168.65.135
ssh-copy-id rhel-lab@192.168.65.134
Press enter or click to view image in full size
Press enter or click to view image in full size

Command Explanation:

  • ssh-copy-id copies the SSH public key to the remote server.
  • rhel-lab and srhel are remote usernames =
  • @ separates the username from the IP address.
  • 192.168.65.134 and 192.168.65.135 are the IP address of the managed nodes.

STEP 4 — TEST SSH CONNECTION

The SSH connection is tested to verify that passwordless login works successfully.

Command:

ssh rhel-lab@192.168.65.134
ssh srhel@192.168.65.135
Press enter or click to view image in full size

Verification Explanation:

  • ssh establishes a secure remote connection.

If login occurs without repeatedly requesting passwords, passwordless authentication is working correctly.

STEP 5 — CREATE INVENTORY FILE

The inventory file stores the list of managed nodes that Ansible will manage.

The inventory file is created on the control node.

Command:

sudo vim inventory

Command Explanation:

  • vim opens the Vim text editor.
  • inventory is the name of the inventory file being created.

INVENTORY FILE CONTENT:

[webservers]
192.168.65.134 ansible_user=rhel-lab
192.168.65.135 ansible_user=srhel

Inventory Explanation:

  • [webservers] creates a group called webservers.
  • 192.168.65.134 is the first managed server.
  • ansible_user=rhel-lab tells Ansible to connect to that server using the rhel-lab account.
  • 192.168.65.135is the second managed server.
  • ansible_user=srhel tells Ansible to connect to that server using the srhel account.

Why We Added ansible_user:

The two managed nodes use different usernames:

  • Server 1 → rhel-lab
  • Server 2 → srhel

By specifying ansible_user, Ansible automatically uses the correct username for each server during SSH connections, ensuring successful communication with both managed nodes.

STEP 6 — CONFIGURE PASSWORDLESS SUDO

The playbook uses become: yes to perform administrative tasks such as installing packages, managing services, and modifying system files.

To allow Ansible execute these tasks automatically on the managed nodes without requesting a password, passwordless sudo must be configured.

Command:

sudo visudo

Command Explanation:

  • sudo - executes the command with administrative privileges.
  • visudo - safely edits the sudoers configuration file.

i - to insert into the visudo file

Add the Following Entry:

rhel-lab ALL=(ALL) NOPASSWD: ALL
Press enter or click to view image in full size

Explanation:

  • rhel-lab identifies the user.
  • ALL=(ALL) allows the user to run commands as any user.
  • NOPASSWD disables sudo password prompts.
  • ALL grants access to all commands.

To save and exit use the esc key then type :wq then press enter

Passwordless configuration on the managed node

On the control node SSH into the managed node to insert the passwordless configuration

To SSH:

ssh srhel@192.168.65.135— Connects to the second managed node.

Command to open the configuration file: sudo visudo

Command Explanation: Opens the sudoers file safely for editing.

  • Scroll to the bottom of the file using your arrow keys.
  • Locate the User Rules section. You are looking for lines that start with the %wheel group or standard user aliases.
  • Press Enter to add the Following Entry:
srhel ALL=(ALL) NOPASSWD: ALL

Explanation:

  • Grants passwordless sudo access to the srhel user.

Verification Command: sudo -l

Get Babatunde’s stories in your inbox

Join Medium for free to get updates from this writer.

Command Explanation: Displays the sudo privileges assigned to the current user.

Verification Explanation:

The output should show that the user can execute commands without being prompted for a password.

STEP 7 — INSTALL REQUIRED ANSIBLE COLLECTION

The playbook uses the ansible.posix.firewalld module to manage firewall rules.

Before creating the playbook, the required Ansible collection should be installed on the control node.

Command:

ansible-galaxy collection install ansible.posix

Press enter or click to view image in full size

Command Explanation:

  • ansible-galaxy manages Ansible roles and collections.
  • collection specifies collection management.
  • install downloads and installs a collection.
  • ansible.posix contains the firewalld module used in this practical.

Verification Command:

ansible-galaxy collection list

Command Explanation:

  • Displays all installed Ansible collections.

Verification Explanation:

The output should contain:

ansible.posix

confirming successful installation.

STEP 8 — TEST ANSIBLE CONNECTIVITY

Before automation begins, connectivity between the control node and managed nodes must be verified.

Command:

ansible -i inventory webservers -m ping

Command Explanation:

  • ansible runs an Ansible command.
  • -i inventory specifies the inventory file to use.
  • webservers targets the webservers group.
  • -m ping uses the ping module to test connectivity.

EXPECTED OUTPUT:

SUCCESS => pong

This output confirms successful communication between the control node and managed nodes.

STEP 9 — CREATE PLAYBOOK FILE

A playbook file is created to store all automation tasks in YAML format.

The playbook is containing the automation tasks that Ansible will execute on the managed nodes.

Command:

vim web_setup.yml

Command Explanation:

  • vim opens the Vim text editor.
  • web_setup.yml is the playbook file being created.

PLAYBOOK SCRIPT

- name: Deploy Apache Web Server with Firewall Configuration
hosts: webservers
become: yes
tasks:

- name: Install Apache web server
dnf:
name: httpd
state: present

- name: Start and enable Apache
service:
name: httpd
state: started
enabled: yes

- name: Install firewalld
dnf:
name: firewalld
state: present

- name: Start firewalld
service:
name: firewalld
state: started
enabled: yes

- name: Allow HTTP service through firewall
ansible.posix.firewalld:
service: http
permanent: yes
state: enabled
immediate: yes

- name: Create custom index page
copy:
dest: /var/www/html/index.html
content:|
<html>
<head><title>My Ansible Web Server</title></head>
<body>
<h1>Apache deployed using Ansible on RHEL 10 </h1>
</body>
</html>

PLAYBOOK TASK EXPLANATION:

Apache Installation Task:

dnf:
name: httpd
state: present

Explanation:

  • dnf is the Ansible module used to install software packages.
  • name: httpd specifies the Apache package name.
  • state: present ensures the package is installed.

Start Apache Service:

service:
name: httpd
state: started
enabled: yes

Explanation:

  • service manages Linux services.
  • name: httpd specifies the Apache service.
  • state: started ensures the service is currently running.
  • enabled: yes ensures the service starts automatically after reboot.

Install Firewall Service:

dnf:
name: firewalld
state: present

Explanation:

  • dnf installs software packages.
  • name: firewalld specifies the firewall package name.
  • state: present ensures the package is installed.

Start Firewall Service:

service:
name: firewalld
state: started
enabled: yes

Explanation:

  • service controls Linux services.
  • name: firewalld specifies the firewall service.
  • state: started ensures the firewall service is running.
  • enabled: yes starts the firewall automatically after reboot.

Open HTTP Port in Firewall:

firewalld:
service: http
permanent: yes
state: enabled
immediate: yes

Explanation:

  • firewalld is the Ansible module used for firewall configuration.
  • service: http allows HTTP traffic through port 80.
  • permanent: yes keeps the firewall rule after reboot.
  • state: enabled activates the firewall rule.
  • immediate: yes applies the firewall rule instantly.

Create Custom Webpage:

copy:
dest: /var/www/html/index.html

Explanation:

  • copy transfers files or content to remote systems.
  • dest specifies the destination location of the webpage file.

STEP 10 — RUN PLAYBOOK

The playbook is executed so all configurations can be applied automatically on the managed nodes.

Command:

ansible-playbook -i inventory web_setup.yml

Command Explanation:

  • ansible-playbook runs Ansible playbook files.
  • i inventory specifies the inventory file.
  • web_setup.yml is the playbook file being executed.

STEP 11 — VERIFY APACHE SERVICE

The Apache service status is checked to verify successful deployment.

Command:

systemctl status httpd
Press enter or click to view image in full size

Command Explanation:

  • systemctl manages Linux services.
  • status checks the current service state.
  • httpd is the Apache web server service.

STEP 12 — VERIFY THE WEB PAGE

The custom web page deployed by Ansible should be tested.

Commands to run on each nodes:

curl <http://192.168.65.134>
curl <http://192.168.65.135>

Command Explanation:

  • curl – Retrieves data from a web server.
  • http://192.168.65.134 ****– The target web server.

Verification:

Expected output:

<h1>Apache deployed using Ansible on RHEL 10</h1>

Verification Explanation:

Confirms that the web page was successfully deployed.

VERIFY THROUGH WEB BROWSER

URL:

<http://192.168.65.135>
<http://192.168.65.134>
Press enter or click to view image in full size
Press enter or click to view image in full size

Verification Explanation:

Opening the server IP address in a browser confirms that the Apache web server is working successfully.

CONCLUSION

In this practical, Ansible was successfully installed and configured on a RHEL 10 control node. SSH key-based authentication was configured to allow secure communication between the control node and managed nodes.

An inventory file was created to define the managed servers, and an Ansible playbook was developed to automate Apache installation, firewall configuration, and webpage deployment.

The automation process reduced manual configuration effort and demonstrated how Ansible simplifies system administration through Infrastructure as Code (IaC).

FINAL OUTCOME:

✔ Ansible installed successfully

✔ SSH key authentication configured

✔ Inventory file created successfully

✔ Apache web server installed automatically

✔ Firewall configured automatically

✔ HTTP access enabled

✔ Custom webpage deployed successfully

✔ Full automation achieved using Ansible

--

--

Babatunde
Babatunde

Written by Babatunde

Aspiring Professional System Administrator RHCSA Linux | Windows Server | Automation | MS SQL Building real-world skills with discipline & consistency