PL - 003 — Ansible Playbook: Automating Apache Web Server Deployment
Manual Steps to Configure the Apache Web Server
The complete manual process is:
Install Apache
sudo dnf -y install httpd
↓
Start and enable Apache
sudo systemctl enable --now httpd
↓
Allow HTTP through firewall
sudo firewall-cmd --permanent --add-service=http
↓
Reload firewall
sudo firewall-cmd --reload
↓
Create index.html
sudo vi /var/www/html/index.html
↓
Set ownership
sudo chown root:root /var/www/html/index.html
↓
Set permissions
sudo chmod 644 /var/www/html/index.html
↓
Test Apache
sudo systemctl is-active httpd
↓
Test website
curl http://localhost
[cnode@control-node ~]$ ls
ansible-lab validate_nodes.sh
[cnode@control-node ~]$ ./validate_nodes.sh
----- dev1 -----
dev1
root
----- dev2 -----
dev2
root
----- testserver -----
testserver
root
----- prodserver -----
prodserver
root
[cnode@control-node ~]$ cd ansible-lab/
[cnode@control-node ansible-lab]$ ls
ansible.cfg inventory
[cnode@control-node ansible-lab]$ cat inventory
[develop]
dev1
dev2
[test]
testserver
[production]
prodserver
[testprod:children]
test
production
[cnode@control-node ansible-lab]$ cat ansible.cfg
[defaults]
inventory = ./inventory
remote_user = cnode
[privilege_escalation]
become = true
become_method = sudo
[cnode@control-node ansible-lab]$
Automation steps to configure web servers on two managed nodes
[cnode@control-node ansible-lab]$ vi webserver.yml
[cnode@control-node ansible-lab]$ ansible-doc copy
[cnode@control-node ansible-lab]$ ls
ansible.cfg inventory webserver.yml
[cnode@control-node ansible-lab]$ mkdir files
[cnode@control-node ansible-lab]$ ls
ansible.cfg files inventory webserver.yml
[cnode@control-node ansible-lab]$ vim files/index.html
[cnode@control-node ansible-lab]$ cat files/index.html
<!DOCTYPE html>
<html>
<head>
<title>Ansible Lab</title>
</head>
<body>
<h1>Hello from Ansible!</h1>
<p>This Apache web server was configured using Ansible.</p>
</body>
</html>
[cnode@control-node ansible-lab]$ vim webserver.yml
[cnode@control-node ansible-lab]$ pwd
/home/cnode/ansible-lab
[cnode@control-node ansible-lab]$ vim webserver.yml
[cnode@control-node ansible-lab]$ cat webserver.yml
- name: Configure Apache web server
hosts: testprod
tasks:
### Install the Apache HTTP server package.
- name: Install Apache web server
ansible.builtin.yum:
name: httpd
state: latest
# Start Apache and configure it to start automatically at boot.
- name: Start and enable Apache service
ansible.builtin.service:
name: httpd
state: started
enabled: yes
# Open HTTP port 80 firewalld and make the change persistent.
- name: Allow HTTP traffic through the firewall
ansible.posix.firewalld:
service: http
state: enabled
permanent: true
immediate: true
# Deploy the website's index page to Apache's document root.
- name: Deploy website index page
ansible.builtin.copy:
src: /home/cnode/ansible-lab/files/index.html
dest: /var/www/html/index.html
owner: root
group: root
mode: '0644'
[cnode@control-node ansible-lab]$ vim webserver.yml
[cnode@control-node ansible-lab]$ cat webserver.yml
---
- name: Configure Apache web server
hosts: testprod
tasks:
# Install the Apache HTTP server package.
- name: Install Apache web server
ansible.builtin.yum:
name: httpd
state: latest
# Start Apache and configure it to start automatically at boot.
- name: Start and enable Apache service
ansible.builtin.service:
name: httpd
state: started
enabled: yes
# Open HTTP port 80 firewalld and make the change persistent.
- name: Allow HTTP traffic through the firewall
ansible.posix.firewalld:
service: http
state: enabled
permanent: true
immediate: true
# Deploy the website's index page to Apache's document root.
- name: Deploy website index page
ansible.builtin.copy:
src: files/index.html
dest: /var/www/html/index.html
owner: root
group: root
mode: '0644'
[cnode@control-node ansible-lab]$
[cnode@control-node ansible-lab]$ ls
ansible.cfg files inventory webserver.yml
[cnode@control-node ansible-lab]$
[cnode@control-node ansible-lab]$ ansible-galaxy collection list
# /home/cnode/.ansible/collections/ansible_collections
Collection Version
---------------------------------------- -------
community.crypto 3.4.0
community.general 13.3.0
community.library_inventory_filtering_v1 1.1.5
# /usr/share/ansible/collections/ansible_collections
Collection Version
---------------------------------------- -------
microsoft.sql 2.6.6
redhat.leapp 1.7.6
redhat.rhel_system_roles 2.4.2
[cnode@control-node ansible-lab]$ ansible-galaxy collection install ansible.posix
Starting galaxy collection install process
[WARNING]: Collection community.general does not support Ansible version 2.16.19
[WARNING]: Collection community.crypto does not support Ansible version 2.16.19
Process install dependency map
Starting collection install process
Downloading https://galaxy.ansible.com/api/v3/plugin/ansible/content/published/collections/artifacts/ansible-posix-2.2.2.tar.gz to /home/cnode/.ansible/tmp/ansible-local-4840p_p0zrme/tmpm4pk34fg/ansible-posix-2.2.2-iqb9w1az
Installing 'ansible.posix:2.2.2' to '/home/cnode/.ansible/collections/ansible_collections/ansible/posix'
ansible.posix:2.2.2 was installed successfully
[cnode@control-node ansible-lab]$ ansible-galaxy collection list | grep ansible.posix
ansible.posix 2.2.2
[cnode@control-node ansible-lab]$ ansible-playbook webserver.yml --syntax-check
playbook: webserver.yml
[cnode@control-node ansible-lab]$ ansible testprod --list-hosts
hosts (2):
testserver
prodserver
[cnode@control-node ansible-lab]$ ansible testprod -m ping
testserver | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}
prodserver | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}
[cnode@control-node ansible-lab]$
[cnode@control-node ansible-lab]$ ansible-playbook webserver.yml --syntax-check
playbook: webserver.yml
[cnode@control-node ansible-lab]$
[cnode@control-node ansible-lab]$ ansible-playbook webserver.yml
PLAY [Configure Apache web server] **************************************************
TASK [Gathering Facts] **************************************************************
ok: [prodserver]
ok: [testserver]
TASK [Install Apache web server] ****************************************************
changed: [testserver]
changed: [prodserver]
TASK [Start and enable Apache service] **********************************************
changed: [testserver]
changed: [prodserver]
TASK [Allow HTTP traffic through the firewall] **************************************
changed: [testserver]
changed: [prodserver]
TASK [Deploy website index page] ****************************************************
changed: [testserver]
changed: [prodserver]
PLAY RECAP **************************************************************************
prodserver : ok=5 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
testserver : ok=5 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[cnode@control-node ansible-lab]$ ansible testprod -m command -a "systemctl is-active httpd"
testserver | CHANGED | rc=0 >>
active
prodserver | CHANGED | rc=0 >>
active
[cnode@control-node ansible-lab]$
[cnode@control-node ansible-lab]$ ansible testprod -m command -a "curl -s http://localhost"
prodserver | CHANGED | rc=0 >>
<!DOCTYPE html>
<html>
<head>
<title>Ansible Lab</title>
</head>
<body>
<h1>Hello from Ansible!</h1>
<p>This Apache web server was configured using Ansible.</p>
</body>
</html>
testserver | CHANGED | rc=0 >>
<!DOCTYPE html>
<html>
<head>
<title>Ansible Lab</title>
</head>
<body>
<h1>Hello from Ansible!</h1>
<p>This Apache web server was configured using Ansible.</p>
</body>
</html>
[cnode@control-node ansible-lab]$
[cnode@control-node ansible-lab]$ curl http://testserver
<!DOCTYPE html>
<html>
<head>
<title>Ansible Lab</title>
</head>
<body>
<h1>Hello from Ansible!</h1>
<p>This Apache web server was configured using Ansible.</p>
</body>
</html>
[cnode@control-node ansible-lab]$ curl http://prodserver
<!DOCTYPE html>
<html>
<head>
<title>Ansible Lab</title>
</head>
<body>
<h1>Hello from Ansible!</h1>
<p>This Apache web server was configured using Ansible.</p>
</body>
</html>
[cnode@control-node ansible-lab]$
[cnode@control-node ansible-lab]$ ansible-playbook webserver.yml --check --diff
...
# DRY RUN
[cnode@control-node ansible-lab]$ ansible-playbook webserver.yml --check
PLAY [Configure Apache web server] *****************************************************************************************************************************************
TASK [Gathering Facts] *****************************************************************************************************************************************************
ok: [testserver]
ok: [prodserver]
TASK [Install Apache web server] *******************************************************************************************************************************************
ok: [prodserver]
ok: [testserver]
TASK [Start and enable Apache service] *************************************************************************************************************************************
ok: [prodserver]
ok: [testserver]
TASK [Allow HTTP traffic through the firewall] *****************************************************************************************************************************
ok: [testserver]
ok: [prodserver]
TASK [Deploy website index page] *******************************************************************************************************************************************
ok: [prodserver]
ok: [testserver]
PLAY RECAP *****************************************************************************************************************************************************************
prodserver : ok=5 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
testserver : ok=5 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[cnode@control-node ansible-lab]$
Undeploy the Apache web server.
[cnode@control-node ansible-lab]$ ls
ansible.cfg files inventory webserver.yml
[cnode@control-node ansible-lab]$ cp webserver.yml undeploy-webserver.yml
[cnode@control-node ansible-lab]$ vim undeploy-webserver.yml
[cnode@control-node ansible-lab]$ ansible-doc firewalld
...
[cnode@control-node ansible-lab]$ vim undeploy-webserver.yml
[cnode@control-node ansible-lab]$ cat undeploy-webserver.yml
---
- name: Undeploy Apache web server
hosts: testprod
tasks:
# Remove the HTTP service from firewalld.
- name: Remove HTTP traffic from the firewall
ansible.posix.firewalld:
service: http
state: disabled
permanent: true
immediate: true
# Stop Apache and prevent it from starting automatically
- name: Stop and disable Apache service
ansible.builtin.service:
name: httpd
state: stopped
enabled: false
# Remove the deployed website.
- name: Remove website index page
ansible.builtin.file:
path: /var/www/html/index.html
state: absent
# Uninstall the Apache HTTP server package.
- name: Remove Apache web server
ansible.builtin.yum:
name: httpd
state: absent
[cnode@control-node ansible-lab]$ ansible-playbook undeploy-webserver.yml --syntax-check
playbook: undeploy-webserver.yml
[cnode@control-node ansible-lab]$ ansible testprod --list-hosts
hosts (2):
testserver
prodserver
[cnode@control-node ansible-lab]$ ansible-playbook --check undeploy-webserver.yml
PLAY [Undeploy Apache web server] ***************************************************
TASK [Gathering Facts] **************************************************************
ok: [prodserver]
ok: [testserver]
TASK [Remove HTTP traffic from the firewall] ****************************************
changed: [prodserver]
changed: [testserver]
TASK [Stop and disable Apache service] **********************************************
changed: [prodserver]
changed: [testserver]
TASK [Remove website index page] ****************************************************
changed: [testserver]
changed: [prodserver]
TASK [Remove Apache web server] *****************************************************
changed: [prodserver]
changed: [testserver]
PLAY RECAP **************************************************************************
prodserver : ok=5 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
testserver : ok=5 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[cnode@control-node ansible-lab]$ ansible-playbook undeploy-webserver.yml
PLAY [Undeploy Apache web server] ***************************************************
TASK [Gathering Facts] **************************************************************
ok: [testserver]
ok: [prodserver]
TASK [Remove HTTP traffic from the firewall] ****************************************
changed: [prodserver]
changed: [testserver]
TASK [Stop and disable Apache service] **********************************************
changed: [prodserver]
changed: [testserver]
TASK [Remove website index page] ****************************************************
changed: [testserver]
changed: [prodserver]
TASK [Remove Apache web server] *****************************************************
changed: [prodserver]
changed: [testserver]
PLAY RECAP **************************************************************************
prodserver : ok=5 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
testserver : ok=5 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[cnode@control-node ansible-lab]$
[cnode@control-node ansible-lab]$ ansible testprod -m command -a "systemctl is-active httpd"
testserver | FAILED | rc=4 >>
inactivenon-zero return code
prodserver | FAILED | rc=4 >>
inactivenon-zero return code
[cnode@control-node ansible-lab]$ ansible testprod -m command -a "rpm -q httpd"
testserver | FAILED | rc=1 >>
package httpd is not installednon-zero return code
prodserver | FAILED | rc=1 >>
package httpd is not installednon-zero return code
[cnode@control-node ansible-lab]$ curl http://testserver
curl: (7) Failed to connect to testserver port 80 after 1 ms: Could not connect to server
[cnode@control-node ansible-lab]$ curl http://prodserver
curl: (7) Failed to connect to prodserver port 80 after 1 ms: Could not connect to server
[cnode@control-node ansible-lab]$