Configuring an optimized web server with Ansible

Configuring an optimized web server with Ansible

Hello There!

After reading this blog you will be able to configure an optimized apache web server with Ansible.

You might be wondering what exactly do I mean by optimized

Restarting the Apache server every time we run the playbook takes away the idempotence nature of Ansible and also consumes more resources. So we will see how to solve this challenge.

I assume you are already familiar with Ansible and setting up an Apache webserver. The entire code in this blog is tested on RHEL 8.

Approach

To solve this challenge we can use handlers in Ansible where we specify that if there are any changes in the configuration files then we restart the apache server which brings back the Idempotence nature.

First, we'll write down the steps:

  • Install Apache webserver

  • Transfer the configuration file

  • Transfer webpages

  • Make a rule in the firewall to allow the incoming traffic to the webserver port

  • Restart web server upon a change in the configuration file

Implementing the approach

  • Install Apache webserver: (Assuming you have already configured yum)
- name: "Install Apache webserver"
  package:
    name: "httpd"
    state: "present"
  • Transfer the configuration file:
- name: "Transfer conf files"
  template:
    src: "{{ path_to_conf }}"
    dest: "/etc/httpd/conf.d/custom.conf"
  notify: "Restart httpd service"

Where path_to_conf is variable which will store the path to the custom httpd configuration file. This will also trigger the handler "Restart httpd service" (which will restart the httpd service) when there is a change in the configuration file.

The configuration file (which is a jinja template) which I have used in this tutorial is as follows:

Listen {{ port_no }}

<VirtualHost {{ ansible_facts['default_ipv4']['address'] }}:{{ port_no }}>
    DocumentRoot {{ document_root }}
</VirtualHost>

Where port_no and document_root are the variables which hold the port number on which the web server is launched and the name of the document root directory (document root is the directory where all the webpages are read from) respectively.

ansible_facts['default_ipv4']['address'] retieves the IP address of the Managed Nodes from Facts.

  • Transfer webpages:
- name: "Create a directory for document root"
  file:
    path: "{{ document_root }}"
    state: "directory"

- name: "Transfer webpages"
  copy:
    src: "{{ item }}"
    dest: "{{ document_root }}"
  with_fileglob: "/var/www/html/*"
  • Make a rule in the firewall to allow the incoming traffic to the webserver port
- name: "Make a firewall rule"
  firewalld:
    port: "{{ port_no }}/tcp"
    permanent: "yes"
    state: "enabled"
    immediate: true
  • Restart web server upon a change in the configuration file
handlers:

  - name: "Restart httpd service"
    service:
      name: "httpd"
      state: "restarted"
      enabled: "yes"

Finally compiling all these we get the playbook as:

- hosts: webservers

  vars:
    - port_no : 8081
    - document_root: "/var/www/webserver"
    - path_to_conf: "./httpd_conf.j2"

  tasks:

    - name: "Install Apache webserver"
      package:
        name: "httpd"
        state: "present"

    - name: "Transfer conf files"
      template:
        src: "{{ path_to_conf }}"
        dest: "/etc/httpd/conf.d/custom.conf"
      notify: "Restart httpd service"

    - name: "Create a directory for document root"
      file:
        path: "{{ document_root }}"
        state: "directory"

    - name: "Transfer webpages"
      copy:
        src: "{{ item }}"
        dest: "{{ document_root }}"
      with_fileglob: "/var/www/html/*"

    - name: "Make a firewall rule"
      firewalld:
        port: "{{ port_no }}/tcp"
        permanent: "yes"
        state: "enabled"
        immediate: true

  handlers:

    - name: "Restart httpd service"
      service:
        name: "httpd"
        state: "restarted"
        enabled: "yes"

Where you can put all the hosts which you want as webservers under the webservers group in the hosts file.

Thank You!