One place for hosting & domains

      How To Deploy a Static HTML Website with Ansible on Ubuntu 20.04 (Nginx)



      Part of the Series:
      How To Write Ansible Playbooks

      Ansible is a modern configuration management tool that doesn’t require the use of an agent software on remote nodes, using only SSH and Python to communicate and execute commands on managed servers. This series will walk you through the main Ansible features that you can use to write playbooks for server automation. At the end, we’ll see a practical example of how to create a playbook to automate setting up a remote Nginx web server and deploy a static HTML website to it.

      If you were following along with all parts of this series, at this point you should be familiar with installing system packages, applying templates, and using handlers in Ansible playbooks. In this part of the series, you’ll use what you’ve seen so far to create a playbook that automates setting up a remote Nginx server to host a static HTML website on Ubuntu 20.04.

      Start by creating a new directory on your Ansible control node where you’ll set up the Ansible files and a demo static HTML website to be deployed to your remote server. This could be in any location of your choice within your home folder. In this example we’ll use ~/ansible-nginx-demo.

      • mkdir ~/ansible-nginx-demo
      • cd ~/ansible-nginx-demo

      Next, copy your existing inventory file into the new directory. In this example, we’ll use the same inventory you set up at the beginning of this series:

      • cp ~/ansible-practice/inventory .

      This will copy a file named inventory from a folder named ansible-practice in your home directory, and save it to the current directory.

      Obtaining the Demo Website

      For this demonstration, we’ll use a static HTML website that is the subject of our How To Code in HTML series. Start by downloading the demo website files by running the following command:

      • curl -L https://github.com/do-community/html_demo_site/archive/refs/heads/main.zip -o html_demo.zip

      You’ll need unzip to unpack the contents of this download. To make sure you have this tool installed, run:

      Then, unpack the demo website files with:

      This will create a new directory called html_demo_site-main on your current working directory. You can check the contents of the directory with an ls -la command:

      • ls -la html_demo_site-main

      Output

      total 28 drwxrwxr-x 3 sammy sammy 4096 sep 18 2020 . drwxrwxr-x 5 sammy sammy 4096 mrt 25 15:03 .. -rw-rw-r-- 1 sammy sammy 1289 sep 18 2020 about.html drwxrwxr-x 2 sammy sammy 4096 sep 18 2020 images -rw-rw-r-- 1 sammy sammy 2455 sep 18 2020 index.html -rw-rw-r-- 1 sammy sammy 1079 sep 18 2020 LICENSE -rw-rw-r-- 1 sammy sammy 675 sep 18 2020 README.md

      Creating a Template for Nginx’s Configuration

      You’ll now set up the Nginx template that is necessary to configure the remote web server. Create a new folder within your ansible-demo directory to hold non-playbook files:

      Then, open a new file called nginx.conf.j2:

      This template file contains an Nginx server block configuration for a static HTML website. It uses three variables: document_root, app_root, and server_name. We’ll define these variables later on when creating the playbook. Copy the following content to your template file:

      ~/ansible-nginx-demo/files/nginx.conf.j2

      server {
        listen 80;
      
        root {{ document_root }}/{{ app_root }};
        index index.html index.htm;
      
        server_name {{ server_name }};
      
        location / {
         default_type "text/html";
         try_files $uri.html $uri $uri/ =404;
        }
      }
      

      Save and close the file when you’re done.

      Creating a New Ansible Playbook

      Next, we’ll create a new Ansible playbook and set up the variables that we’ve used in the previous section of this guide. Open a new file named playbook.yml:

      This playbook starts with the hosts definition set to all and a become directive that tells Ansible to run all tasks as the root user by default (the same as manually running commands with sudo). Within this playbook’s var section, we’ll create three variables: server_name, document_root, and app_root. These variables are used in the Nginx configuration template to set up the domain name or IP address that this web server will respond to, and the full path to where the website files are located on the server. For this demo, we’ll use the ansible_default_ipv4.address fact variable because it contains the remote server’s public IP address, but you can replace this value with your server’s hostname in case it has a domain name properly configured within a DNS service to point to this server:

      ~/ansible-nginx-demo/playbook.yml

      ---
      - hosts: all
        become: yes
        vars:
          server_name: "{{ ansible_default_ipv4.address }}"
          document_root: /var/www/html
          app_root: html_demo_site-main
        tasks:
      

      You can keep this file open for now. The next sections will walk you through all tasks that you’ll need to include in this playbook to make it fully functional.

      Installing Required Packages

      The following task will update the apt cache and then install the nginx package on remote nodes:

      ~/ansible-nginx-demo/playbook.yml

      . . .
          - name: Update apt cache and install Nginx
            apt:
              name: nginx
              state: latest
              update_cache: yes
      

      Uploading Website Files to Remote Nodes

      The next task will use the copy built-in module to upload the website files to the remote document root. We’ll use the document_root variable to set the destination on the server where the application folder should be created.

      ~/ansible-nginx-demo/playbook.yml

      . . .
          - name: Copy website files to the server's document root
            copy:
              src: "{{ app_root }}"
              dest: "{{ document_root }}"
              mode: preserve
      

      Applying and Enabling the Custom Nginx Configuration

      We’ll now apply the Nginx template that will configure the web server to host your static HTML file. After the configuration file is set at /etc/nginx/sites-available, we’ll create a symbolic link to that file inside /etc/nginx-sites-enabled and notify the Nginx service for a posterior restart. The entire process will require two separate tasks:

      ~/ansible-nginx-demo/playbook.yml

      . . .
          - name: Apply Nginx template
            template:
              src: files/nginx.conf.j2
              dest: /etc/nginx/sites-available/default
            notify: Restart Nginx
      
          - name: Enable new site
            file:
              src: /etc/nginx/sites-available/default
              dest: /etc/nginx/sites-enabled/default
              state: link
            notify: Restart Nginx
      

      Allowing Port 80 on UFW

      Next, include the task that enables tcp access on port 80:

      ~/ansible-nginx-demo/playbook.yml

      . . .
          - name: Allow all access to tcp port 80
            ufw:
              rule: allow
              port: '80'
              proto: tcp
      . . .
      

      Creating a Handler for the Nginx Service

      To finish this playbook, the only thing left to do is to set up the Restart Nginx handler:

      ~/ansible-nginx-demo/playbook.yml

      . . .
        handlers:
          - name: Restart Nginx
            service:
              name: nginx
              state: restarted  
      

      Running the Finished Playbook

      Once you’re finished including all the required tasks in your playbook file, it will look like this:

      ~/ansible-nginx-demo/playbook.yml

      ---
      - hosts: all
        become: yes
        vars:
          server_name: "{{ ansible_default_ipv4.address }}"
          document_root: /var/www
          app_root: html_demo_site-main
        tasks:
          - name: Update apt cache and install Nginx
            apt:
              name: nginx
              state: latest
              update_cache: yes
      
          - name: Copy website files to the server's document root
            copy:
              src: "{{ app_root }}"
              dest: "{{ document_root }}"
              mode: preserve
      
          - name: Apply Nginx template
            template:
              src: files/nginx.conf.j2
              dest: /etc/nginx/sites-available/default
            notify: Restart Nginx
      
          - name: Enable new site
            file:
              src: /etc/nginx/sites-available/default
              dest: /etc/nginx/sites-enabled/default
              state: link
            notify: Restart Nginx
      
          - name: Allow all access to tcp port 80
            ufw:
              rule: allow
              port: '80'
              proto: tcp
      
        handlers:
          - name: Restart Nginx
            service:
              name: nginx
              state: restarted
      

      To execute this playbook on the server(s) that you set up in your inventory file, run ansible-playbook with the same connection arguments you’ve used when running a connection test within the introduction of this series. Here, we’ll be using an inventory file named inventory and the sammy user to connect to the remote server. Because the playbook requires sudo to run, we’re also including the -K argument to provide the remote user’s sudo password when prompted by Ansible:

      • ansible-playbook -i inventory playbook.yml -u sammy -K

      You’ll see output like this:

      Output

      BECOME password: PLAY [all] ********************************************************************************************** TASK [Gathering Facts] ********************************************************************************** ok: [203.0.113.10] TASK [Update apt cache and install Nginx] *************************************************************** ok: [203.0.113.10] TASK [Copy website files to the server's document root] ************************************************* changed: [203.0.113.10] TASK [Apply Nginx template] ***************************************************************************** changed: [203.0.113.10] TASK [Enable new site] ********************************************************************************** ok: [203.0.113.10] TASK [Allow all access to tcp port 80] ****************************************************************** ok: [203.0.113.10] RUNNING HANDLER [Restart Nginx] ************************************************************************* changed: [203.0.113.10] PLAY RECAP ********************************************************************************************** 203.0.113.10 : ok=7 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

      Once the playbook is finished, if you go to your browser and access your server’s hostname or IP address you should now see the following page:

      HTML Demo Site Deployed by Ansible

      Congratulations, you have successfully automated the deployment of a static HTML website to a remote Nginx server, using Ansible.

      If you make changes to any of the files in the demo website, you can run the playbook again and the copy task will make sure any file changes are reflected in the remote host. Because Ansible has an idempotent behavior, running the playbook multiple times will not trigger changes that were already made to the system.



      Source link