/ NGINX

How To Configure NGINX Using Ansible on Ubuntu

Introduction

When you have more servers and you need to manage their configuration - in this case NGINX one - copy and paste or write the content of the files for each machine is frustrating and not the best way, so in this guide you will learn how to set up Ansible in order to manage NGINX configuration files through Ansible Playbooks.

Ansible is an automation tool that allows you to remotely configure systems, install software, and perform complex tasks across a large fleet of servers without needing to manually log into each. Unlike other alternatives, Ansible is installed on a single host, which can even be your local machine, and uses SSH to communicate with each remote host. This allows it to be incredibly fast at configuring new servers, as there are no prerequisite packages to be installed on each new server. It is incredibly easy to use and understand, since it uses playbooks in yaml format using a simple module based syntax.

When you're finished, you'll be able to write your own Playbook and upload new NGINX configurations with just one command from your terminal.

Prerequisites

Before you begin this guide you'll need the following:

Step 1 — Install Ansible

The first step is to install Ansible. On Mac OS X and Windows you can achieve that with Pip, the Python package manager; on Ubuntu you can install it via apitude.

Mac OS X and Windows

If you don't have Pip installed, you can install it with sudo easy_install pip.
Now install Ansible running sudo pip install ansible from the terminal.

Windows

If you don't have Pip installed, you have to to download the get-pip.py file and run it with python get-pip.py.
Now install Ansible running pip install ansible from the CMD.

Ubuntu

The procedure on Ubuntu is a bit longer. The first thing to do it's to update the apitude repository with sudo apt-get update. After this, install the software-properties-common package with sudo apt-get install software-properties-common and add the Ansible repository running sudo apt-add-repository ppa:ansible/ansible. Update again the repository to fetch Ansible with sudo apt-get update and finally you can install it running sudo apt-get install ansible.

The final commands in the terminal will look like this:

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

If you want a more in-depth guide about Ansible, you can read How to Install and Configure Ansible on Ubuntu 16.04.
In the next step we will see how to configure an inventory file and how to tell Ansible to read hosts from that.

Step 2 — Creating An Inventory File

In the Ansible terminology, an inventory is a file where the target hosts of our actions are specified. Its default path is /etc/ansible/hosts, but in this case we'll create our inventory in the same folder of the other files, so we can create a Git repository to share with other members of our team without the need for them to create or modify their hosts file.

The content is pretty simple, we create a group called "app" with inside two IPs corresponding to two servers.

Note: We specified the ansible_user variable that tells to Ansible with which user log in into the server.

[app]

111.111.111.111 ansible_user=ubuntu
222.222.222.222 ansible_user=ubuntu

Edit, add or delete lines depending on your needs and save the file as hosts.
Now, in order to tell Ansible to use this inventory file, we have two ways:

  1. Specify the -i argument from the terminal when we call an ansible playbook;
  2. Create a file used to set up the current Ansible configuration. We will use this.

Create a file called ansible.cfg with the following content, where we set the default inventory file path:

[defaults]

inventory = ./hosts

Now we can create our template of the NGINX configuration file.

Step 3 — Write The Template File

Our NGINX configuration file will be a template file which will be parsed from Ansible before upload it. It's a common file with the tpl extension and inside you can write your own variables or the Ansible default ones. You can copy your configuration from the server or use the following one:

user www-data;
worker_processes auto;
pid /run/nginx.pid;

events {
  worker_connections 768;
  # multi_accept on;
}

http {
  ##
  # Basic Settings
  ##
  sendfile on;
  tcp_nopush on;
  tcp_nodelay on;
  keepalive_timeout 65;
  types_hash_max_size 2048;
  server_tokens off;
  # server_names_hash_bucket_size 64;
  # server_name_in_redirect off;
  include /etc/nginx/mime.types;
  default_type application/octet-stream;
  ##
  # SSL Settings
  ##
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
  ssl_prefer_server_ciphers on;
  ##
  # Logging Settings
  ##
  access_log /var/log/nginx/access.log timed_combined;
  error_log /var/log/nginx/error.log;
  ##
  # Gzip Settings
  ##
  gzip on;
  gzip_disable "msie6";
  gzip_vary on;
  gzip_proxied any;
  gzip_comp_level 6;
  gzip_buffers 16 8k;
  gzip_http_version 1.1;
  gzip_min_length 256;
  gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
  ##
  # Virtual Host Configs
  ##
  include /etc/nginx/conf.d/*.conf;
  include /etc/nginx/sites-enabled/*;
}

Save this file as nginx.conf.tpl in your folder - where there's the inventory and the Ansible configuration and let's see how to create a Playbook.

Step 4 — Create The Playbook

Now that we created our template, we have to tell Ansible to read it and upload to a specific directory in our servers: this can be achieved with Playbooks, which are files, written in YAML, containing rules and tasks that will be executed.

Our playbook, named nginx.yml, will do these simple actions, called, in the Ansible jargon, tasks:

  1. Upload our nginx configuration file – nginx.conf.tpl – to /etc/nginx/nginx.conf;
  2. Reload nginx.

This can be achieved with the following code, which we'll analyze line by line below:

---
- hosts: app
  become: true
  tasks:
    - name: Setup nginx conf
      template:
        src=nginx.conf.tpl
        dest=/etc/nginx/nginx.conf
      notify: restart nginx
  handlers:
    - name: restart nginx
      service:
        name=nginx
        state=restarted

The first line, ---, it's required to read properly a YAML file.
In the next line, - hosts: app, we create a group of tasks attached to the app group from the inventory, so all our tasks are executed only in that two servers.
become: true is used to run commands with privileges, like if we’re executing them with sudo.
tasks: contains the actions to perform and are common composed by the following variables:

  • name which is the task name that will appear in your terminal when you run the playbook. In this case we called it "Setup nginx conf".
  • template, a module to parse template files. We pass to it two args: src – the file location – and dest – the remote path where it will be uploaded. Learn more about template module.
    And, in this case, we use notify to trigger an event, called handlers in Ansible, which will be used below to restart nginx. When an event is notified, the corresponding handler (restart nginx) is triggered.

Note: If you want to know better the playbook syntax and how to write them, you can read the article Configuration Management 101: Writing Ansible Playbooks.

The configuration is complete: now we can test it.

Step 5 — Run the Playbook

To run a Playbook we have to use the ansible-playbook which accepts as main argument the playbook path:
ansible-playbook nginx.yml

If you want to avoid the ansible.cfg file, you can pass the -i flag with the path of the inventory file:

ansible-playbook -i hosts nginx.yml

The content of your terminal, when Ansible is done, will look like this:

PLAY ***************************************************************************

TASK [setup] *******************************************************************
ok: [111.111.111.111]
ok: [222.222.222.222]

TASK [Setup nginx conf] ********************************************************
changed: [111.111.111.111]
changed: [222.222.222.222]

RUNNING HANDLER [restart nginx] ************************************************
changed: [111.111.111.111]
changed: [222.222.222.222]

PLAY RECAP *********************************************************************
111.111.111.111 : ok=3    changed=2    unreachable=0    failed=0   
222.222.222.222 : ok=3    changed=2    unreachable=0    failed=0 

Conclusion

In this article you learned how to manage NGINX configuration file through Ansible playbooks. Now you can use the same task syntax to create another playbook to configure the virtual host of your site - file under /etc/nginx/sites-available/. Here's some tips about how to realize it:

  • Create a template file called yoursite.conf.tpl;
  • Create a playbook called yoursite.conf.yml
  • Inside the playbook, copy the template into the right path and restart NGINX.
Danilo Polani

Danilo Polani

Software Engineer and dreamer in startups. Go, Python, Laravel, Ionic, AngularJS, VueJS, NodeJS, JavaScript, Elasticsearch, Redis.

Read More