How to install Nginx server with Ansible playbook

How to install Nginx server with Ansible playbook

What is Nginx?

Nginx is a popular tool used in configuring and hosting websites, it has other important features too such as load balancing, etc. Although this is not the only tool used for this particular function, there is also apache which is also very popular as well. To know more about Nginx and its functions/properties click here.

What is Ansible?

Ansible has become very popular because of its value proposition which it brings to the industry of Cloud computing, Networking, DevOps, and others, in terms of configuration management. the list of things you can do with ansible ranges from simple command-line tasks to complex configurations that can be deployed to a host of servers, Kubernetes pods, Docker containers, etc using various Modules. More comprehensive documentation about Ansible for better understanding can be found here.

Objective

Now we have an Idea of what Ansible and Nginx are, let's gets started. For this exercise we will be installing Nginx on an EC2 instance(target machine) from another EC2 instance(control node) which is our ansible host.

What we need to get this done.

  • An AWS account
  • A linux terminal (preferably git bash if you are on windows)

    Note

  • I will be using the default VPC, if you have a custom VPC you will have to adjust your settings accordingly.

  • My code for this exercise can be found on Github
  • You can connect with me on LinkedIn

Setting up the Environment

Create security groups

Create a security group called AnsibleSG with the following inbound rules:

  • Type: SSH
  • Port range: 22
  • Source: My IP

This will enable you to ssh into the Ansible host. Create another Security Group "ServerSG" with the following inbound rules:

  • Type: HTTP
  • Port range: 80
  • Source: My IP
  • Type: SSH
  • Port range: 22
  • Source: My IP
  • Type: SSH
  • Port range: 22
  • Source: Control node IP

Create EC2 instaces

Create an EC2 instance(control node where Ansible will be installed) with the following properties

  • AMI: Ubuntu Server 20.04 LTS (HVM), SSD Volume Type
  • Instance Type: t2.micro
  • VPC: Default
  • Tags: Key = name, Value = Ansible control node
  • Security Group: AnsibleSG
  • Keypair: Create new or existing

Next, we will create another instance that will serve as the target node/server to install Nginx. The instance will have the following properties:

  • AMI: Ubuntu Server 20.04 LTS (HVM), SSD Volume Type
  • Instance Type: t2.micro
  • VPC: Default
  • Tags: Key = name, Value = Nginx
  • Security Group: AnsibleSG
  • Keypair: Use same key above

When you are done with the above steps you will be having an environment as shown in the screenshot below.

New instance pic.PNG

Install Ansible and Setup SSH

Ansible is going to dwell or exist inside our control node(EC2) instance that we have provisioned above. In other to install ansible, we will need to SSH into the control node and carry out the installation procedure. Note! am running the ssh command from a Linux terminal, if you are using windows you can download putty or use gitbash. instructions for installation of putty can be found here. To SSH into the control node, make sure you are in the same directory where you have the private key you have from AWS, then run the following command:

ssh -i "<your key name.pem>" ubuntu@<control node instance IP>

When inside the control node, you can install Ansible by running the following commands:

  sudo apt-get update
  sudo apt-get install software-properties-common
  sudo apt-add-repository --yes --update ppa:ansible/ansible
  sudo apt-get install ansible

After Ansible has been successfully installed, you need to setup ssh connection between your control node(Ansible host) and your target Instance. This will enable Ansible to comunicate freely with the target instance. To do this you need to generate a key pair that will be used to authenticate the control node whenever a connection is initiated. While still logged in the control node, run the following commands;

ssh-keygen #this will generate the keys
cat ~/.ssh/id_rsa.pub #this will print the contents of the public key for you to copy and paste on a clip #board

Now exit the control node and SSH into the target instance and run the following code

cat >> ~/.ssh/authorized_keys

paste in the contents of the public key you copied ealier pres "ctrl +d" to save and exit. Exit from the target instance and ssh back into your control node to test the connection. Run the following code;

ssh ubuntu@target-instance-IP

There will be a fingerprint prompt, type yes. you will be logged into your target instance. Exit to return back to your control node. Now that SSH connection has been set up lets move on.

Creating the Ansible playbook

An Ansible playbook is a file that contains the task or procedures that you want to execute on your target machine(s) properly documented in YAML syntax. When creating a playbook there are different ways that it can be structured, you can follow a simple format where you have a YAML manifest file that contains the description of the desired state of your system, or you can follow a structure that enables you to establish different roles that contain a collection of tasks you want to deploy. You can find more information on playbooks here. An inventory file is what contains a list of the addresses of the machines/servers you want to configure and apply changes to.

First, we will access our files by cloning the github repo:

git clone https://github.com/Joshua-Igoni/ansible-dev.git

Now that we have our files lets examine the structure to understand how Ansible will go about the installation and configuration of nginx. To examine the structure use the command tree if the terminal flags 'command not found' you will have to install it using the command ;

sudo apt-get install tree

Type in the command tree and you should be able to see something that looks like what i have below

our tree.PNG

From the picture above, there is a top-level directory ansible dev that contains inventory and main.yaml files, the inventory file contains the list of target IPs that we intend to configure, in this case is just a single IP which will be your target instance IP.

inventory file N2.PNG

contents of main.yaml shown below

# Install Nginx
---
- hosts: target
  become: True
  become_user: root
  roles:
    - nginx

The main.yaml file contains the information that would be used by Ansible to connect to the target machines in the inventory file, and also tell Ansible to connect to the machine as the root user so as to have administrative privileges to perform installation procedures. The file tells ansible to look for a directory(folder) called "Nginx" that exists inside a "roles" directory to find what it needs to execute the installation. Roles are there to separate different collections of tasks that have been group together to achieve a particular desired state. In this case, the "desired state" of the system that we are after is the installation of Nginx. The "Nginx" role that contains tasks which is a folder that holds a main.yaml file that is a list of procedures that will be executed sequentially to achieve the state, vars which is also a folder that contains a main.yaml file that lists all the variables that will be needed for successful completion, templates which is also a folder that holds configuration files for the server to be installed successfully.

Let's take a closer look at each of these files, starting with the task folder which contains a "main.yaml" file, the contents are shown below. Each task has a name that serves as a form of documentation so that if someone else uses this playbook it would be easy to understand and follow up on the processes. Each task also has a module from which it draws references for execution, for this process of installation we used the apt, template and systemd modules. For more comprehensive overview of modules click here

    # Install Nginx

- name: "apt-get update"
  apt:
    update_cache: yes
    cache_valid_time: 3600
- name: Install Nginx
  apt:
    name: nginx
    state: latest
- name: generate Nginx site config
  template:
     src: site.conf.j2
     dest: /etc/nginx/sites-available/site.conf
     owner: root
     group: root
     mode: 0755
- name: Generate index.html
  template:
     src: index.html.j2
     dest: /var/www/html/index.html
     owner: root
     group: root
     mode: 0744
- name: Enable Nginx service
  systemd:
    name: nginx
    daemon_reload: yes
    enabled: yes
    state: started

The next is the Templates directory which holds the configuration of the site and the index file. The contents of the site.conf.j2 and index.html.j2 are shown below respectively. The files contain certain variables which will be defined in a separate file in a separate folder.

contents of site.conf.j2 shown below

server {
        listen   80;
        server_name  {{ SERVER_NAME }};
        root   {{ FILE_PATH }};
        location / {
                index  index.php index.html index.htm;
                autoindex off;    #enable listing of directory index
        }
}

contents of index.html.j2 shown below

<!doctype html>
   <html>
     <head>
         <title>Welcome {{ STUDENT_NAME }} to Ansible</title>
     </head>
     <body>
       <h2> {{ STUDENT_NAME }} </h2>
       <p><strong>Configure your world your way &#153;</strong></p>
     </body>
   </html>

The final folder is vars folder which holds the main.yaml file that has all our variables defined. The contents are shown below

SERVER_NAME: "<server ip>"
FILE_PATH: "/var/www/html"
STUDENT_NAME: "<Student name>"

Now we have everything setup lets go back to the top level folder and run our playbook, run the playbook with the following command:

ansible-playbook -i inventory main.yaml

If everything is setup correctly, you wont be having any errors, the output should look like the following

it worked.PNG

when you access the IP:80 of your machine, you should be having a customized static web page as shown below

remote nginx.PNG

Awesome right? Now I would encourage to take a deep dive into Ansible documention because its a really great place to learn about the tool and how it applies to your particular domain of tech. Thank you for reading. Feel free to like and share.