Installing NGINX and NGINX Plus With Ansible

Official NGINX Ansible Roles have now been released and this solution is no longer supported. Please refer to the announcement blog post for more details.

Coming from a production operations background, I have learned to love all things related to automation. Why do something by hand if a computer can do it for you? But creating and implementing automation can be a difficult task given an ever‑changing infrastructure and the various technologies surrounding your environments. This is why I love Ansible. Ansible is an open source tool for IT configuration management, deployment, and orchestration that is extremely easy to use.

One of my favorite features of Ansible is that it is completely clientless. To manage a system, a connection is made over SSH, using either Paramiko (a Python library) or native OpenSSH. Another attractive feature of Ansible is its extensive selection of modules. These modules can be used to perform some of the common tasks of a system administrator. In particular, they make Ansible a powerful tool for installing and configuring any application across multiple servers, environments, and operating systems, all from one central location.

In this tutorial, I will walk you through the steps for using Ansible to install and deploy the open source NGINX software and NGINX Plus, our commercial product. I’m showing deployment onto a CentOS server, but I have included details about deploying on Ubuntu servers in Creating an Ansible Playbook for Installing NGINX and NGINX Plus on Ubuntu below.

Editor – For information about using other DevOps automation tools with NGINX and NGINX Plus, check out these related blogs:

Installing Ansible

For this tutorial I will be using Ansible version 1.9.2 and performing the deployment from a server running CentOS 7.1.

$ ansible --version
ansible 1.9.2

$ cat /etc/redhat-release
CentOS Linux release 7.1.1503 (Core)

If you don’t already have Ansible, you can get instructions for installing it at the Ansible site.

If you are using CentOS, installing Ansible is easy as typing the following command. If you want to compile from source or for other distributions, see the instructions at the Ansible link provided just above.

$ sudo yum install -y epel-release && sudo yum install -y ansible

Depending on your environment, some of the commands in this tutorial might require sudo privileges. The path to the files, usernames, and destination servers are all values that will be specific to your environment.

Creating an Ansible Playbook for Installing NGINX (CentOS)

First we create a working directory for our NGINX deployment, along with subdirectories and deployment configuration files. I usually recommend creating the directory in your home directory and show that in all examples in this tutorial.

$ cd $HOME
$ mkdir -p ansible-nginx/tasks/
$ touch ansible-nginx/deploy.yml
$ touch ansible-nginx/tasks/install_nginx.yml

The directory structure now looks like this. You can check by using the tree command.

$ tree $HOME/ansible-nginx/
/home/kjones/ansible-nginx/
├── deploy.yml
└── tasks
└── install_nginx.yml

1 directory, 2 files

If you do not have tree installed, you can do so using the following command.

$ sudo yum install -y tree

Creating the Main Deployment File

Next we open deploy.yml in a text editor. I prefer vim for editing configuration files on the command line, and will use it throughout the tutorial.

$ vim $HOME/ansible-nginx/deploy.yml

The deploy.yml file is our main Ansible deployment file, which we’ll reference when we run the ansible‑playbook command in Running Ansible to Deploy NGINX. Within this file we specify the inventory for Ansible to use along with any other configuration files to include at runtime.

In my example I use the include module to specify a configuration file that has the steps for installing NGINX. While it is possible to create a playbook in one very large file, I recommend that you separate the steps into smaller included files to keep things organized. Sample use cases for an include are copying static content, copying configuration files, or assigning variables for a more advanced deployment with configuration logic.

Type the following lines into the file. I include the filename at the top in a comment for reference.

# ./ansible-nginx/deploy.yml

- hosts: nginx
tasks:
- include: 'tasks/install_nginx.yml'

The hosts statement tells Ansible to deploy to all servers in the nginx group, which is defined in /etc/ansible/hosts. We’ll edit this file in Creating the List of NGINX Servers below.

The include statement tells Ansible to read in and execute the contents of the install_nginx.yml file from the tasks directory during deployment. The file includes the steps for downloading, installing, and starting NGINX. We’ll create this file in the next section.

Creating the Deployment File for NGINX

Now let’s save our work to deploy.yml and open up install_nginx.yml in the editor.

$ vim $HOME/ansible-nginx/tasks/install_nginx.yml

The file is going to contain the instructions – written in YAML format – for Ansible to follow when installing and configuring our NGINX deployment. Each section (step in the process) starts with a name statement (preceded by hyphen) that describes the step. The string following name: is written to stdout during the Ansible deployment and can be changed as you wish. The next line of a section in the YAML file is the module that will be used during that deployment step. In the configuration below, both the yum and service modules are used. The yum module is used to install packages on CentOS. The service module is used to manage UNIX services. The final line or lines in a section specify any parameters for the module (in the example, these lines start with name and state).

Type the following lines into the file. As with deploy.yml, the first line in our file is a comment that names the file for reference. The first section tells Ansible to install the .rpm file for CentOS 7 from the NGINX repository. This directs the package manager to install the most recent stable version of NGINX directly from NGINX. Modify the pathname as necessary for your CentOS version. A list of available packages can be found on the open source NGINX website. The next two sections tell Ansible to install the latest NGINX version using the yum module and then start NGINX using the service module.

Note: In the first section, the pathname to the CentOS package might appear on two lines; that is only for space reasons. Type the entire path on a single line.

# ./ansible-nginx/tasks/install_nginx.yml
 
- name: NGINX | Installing NGINX repo rpm
yum:
name: http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
 
- name: NGINX | Installing NGINX
yum:
name: nginx
state: latest
 
- name: NGINX | Starting NGINX
service:
name: nginx
state: started

Creating the List of NGINX Servers

Now that we have our Ansible deployment configuration files all set up, we need to tell Ansible exactly which servers to deploy to. We specify this in the Ansible hosts file I mentioned earlier. Let’s make a backup of the existing file and create a new one just for our deployment.

$ sudo mv /etc/ansible/hosts /etc/ansible/hosts.backup
$ sudo vim /etc/ansible/hosts

Type (or edit) the following lines in the file to create a group called nginx and list the servers to install NGINX on. You can designate servers by hostname, IP address, or in an array such as server[1-3].domain.com. Here I designate one server by its IP address.

# /etc/ansible/hosts
 
[nginx]
172.16.239.140

Setting Up Security

We are almost all set, but before deployment we need to ensure that Ansible has authorization to access our destination server over SSH.

The preferred and most secure method is to add the Ansible deployment server’s RSA SSH key to the destination server’s authorized_keys file, which gives Ansible unrestricted SSH permissions on the destination server. To learn more about this configuration, see Securing OpenSSH on wiki.centos.org. This way you can automate your deployments without user interaction.

Alternatively, you can request the password interactively during deployment. I strongly recommend that you use this method during testing only, because it is insecure and there is no way to track changes to a destination host’s fingerprint. If you want to do this, change the value of StrictHostKeyChecking from the default yes to no in the /etc/ssh/ssh_config file on each of your destination hosts. Then add the --ask-pass flag on the ansible-playbook command to have Ansible prompt for the SSH password.

Here I illustrate how to edit the ssh_config file to disable strict host key checking on the destination server. We manually SSH into the server to which we’ll deploy NGINX and change the value of StrictHostKeyChecking to no.

$ ssh kjones@172.16.239.140
kjones@172.16.239.140's password:***********
 
[kjones@nginx ]$ sudo vim /etc/ssh/ssh_config

After you make the change, save ssh_config, and connect to your Ansible server via SSH. The setting should look as below before you save your work.

# /etc/ssh/ssh_config
 
StrictHostKeyChecking no

Running Ansible to Deploy NGINX

If you have followed the steps in this tutorial, you can run the following command to have Ansible deploy NGINX. (Again, if you have set up RSA SSH key authentication, then the --ask-pass flag is not needed.) Run the command on the Ansible server with the configuration files we created above.

$ sudo ansible-playbook --ask-pass $HOME/ansible-nginx/deploy.yml

Ansible prompts for the SSH password and produces output like the following. A recap that reports failed=0 like this one indicates that deployment succeeded.

$ sudo ansible-playbook --ask-pass $HOME/ansible-nginx/deploy.yml
SSH password:
 
PLAY [all] ********************************************************************
 
GATHERING FACTS ***************************************************************
ok: [172.16.239.140]
 
TASK: [NGINX | Installing NGINX repo rpm] *************************************
changed: [172.16.239.140]
 
TASK: [NGINX | Installing NGINX] **********************************************
changed: [172.16.239.140]
 
TASK: [NGINX | Starting NGINX] ************************************************
changed: [172.16.239.140]
 
PLAY RECAP ********************************************************************
172.16.239.140             : ok=4    changed=3    unreachable=0    failed=0

If you didn’t get a successful play recap, you can try running the ansible-playbook command again with the -vvvv flag (verbose with connection debugging) to troubleshoot the deployment process.

When deployment succeeds (as it did for us on the first try), you can verify that NGINX is running on the remote server by running the following basic cURL command. Here it returns 200 OK. Success! We have successfully installed NGINX using Ansible.

$ curl -Is 172.16.239.140 | grep HTTP
HTTP/1.1 200 OK

Creating an Ansible Playbook for Installing NGINX Plus (CentOS)

Now that I’ve shown you how to install the open source version of NGINX, I’ll walk you through the steps for installing NGINX Plus. This requires some additional changes to the deployment configuration and showcases some of Ansible’s other features.

Copying the NGINX Plus Certificate and Key to the Ansible Server

To install and configure NGINX Plus with Ansible, we first need to copy the key and certificate for our NGINX Plus subscription from the NGINX Plus Customer Portal to the standard location on the Ansible deployment server.

Access to the NGINX Plus Customer Portal is available for customers who have purchased NGINX Plus or are evaluating it. If you are interested in evaluating NGINX Plus, you can request a 30‑day free trial here. You will receive a link to your trial certificate and key shortly after you sign up.

On a Mac or Linux host, use the scp utility as I show here. On a Microsoft Windows host, you can use WinSCP. For this tutorial, I downloaded the files to my Mac laptop, then used scp to copy them to the Ansible server. These commands place both the key and certificate in my home directory.

$ cd /path/to/nginx-repo-files/
$ scp nginx-repo.* user@destination-server:.

Next we SSH to the Ansible server, make sure the SSL directory for NGINX Plus exists, and move the files there.

$ ssh user@destination-server
$ sudo mkdir -p /etc/ssl/nginx/
$ sudo mv nginx-repo.* /etc/ssl/nginx/

Verify that your /etc/ssl/nginx directory contains both the certificate (.crt) and key (.key) files. You can check by using the tree command.

$ tree /etc/ssl/nginx
/etc/ssl/nginx
├── nginx-repo.crt
└── nginx-repo.key
 
0 directories, 2 files

If you do not have tree installed, you can do so using the following command.

$ sudo yum install -y tree

Creating the Ansible Directory Structure

The remaining steps are very similar to the ones for open source NGINX that we performed in Creating an Ansible Playbook for Installing NGINX (CentOS). First we set up a working directory for our NGINX Plus deployment. Again I prefer creating it as a subdirectory of my home directory.

$ cd $HOME
$ mkdir -p ansible-nginx-plus/tasks/
$ touch ansible-nginx-plus/deploy.yml
$ touch ansible-nginx-plus/tasks/install_nginx_plus.yml

The directory structure now looks like this.

$ tree $HOME/ansible-nginx-plus/
/home/kjones/ansible-nginx-plus/
├── deploy.yml
└── tasks
└── install_nginx_plus.yml
 
1 directory, 2 files

Creating the Main Deployment File

Next we use vim to create the deploy.yml file as for open source NGINX.

$ vim ansible-nginx-plus/deploy.yml

The only difference from the open source NGINX deployment is that we change the name of the included file to install_nginx_plus.yml. As a reminder, the file tells Ansible to deploy NGINX Plus on all servers in the nginx group (which is defined in /etc/ansible/hosts), and to read in and execute the contents of the install_nginx_plus.yml file from the tasks directory during deployment.

# ./ansible-nginx-plus/deploy.yml
 
- hosts: nginx
tasks:
- include: 'tasks/install_nginx_plus.yml'

If you have not done so already, you also need to create the hosts file as detailed in Creating the List of NGINX Servers above.

Creating the Deployment File for NGINX Plus

Open install_nginx_plus.yml in a text editor. The file is going to contain the instructions for Ansible to follow when installing and configuring your NGINX Plus deployment. The commands and modules are specific to CentOS and some are unique to NGINX Plus.

$ vim ansible-nginx-plus/tasks/install_nginx_plus.yml

The first section uses the file module, telling Ansible to create the SSL directory for NGINX Plus as specified by the path and state arguments, set the ownership to root, and change the mode to 0755.

# ./ansible-nginx-plus/tasks/install_nginx_plus.yml
 
- name: NGINX Plus | Creating NGINX Plus SSL/TLS cert repo directory
file: path=/etc/ssl/nginx state=directory group=root mode=0755

The next two sections use the copy module to copy the NGINX Plus certificate and key from the Ansible deployment server to the NGINX Plus server during the deployment, setting ownership to root and the mode to 0644.

- name: NGINX Plus | Copying NGINX Plus repository certificate
copy: src=/etc/ssl/nginx/nginx-repo.crt dest=/etc/ssl/nginx/nginx-repo.crt owner=root group=root mode=0644
 
- name: NGINX Plus | Copying NGINX Plus repository key
copy: src=/etc/ssl/nginx/nginx-repo.key dest=/etc/ssl/nginx/nginx-repo.key owner=root group=root mode=0644

Next we tell Ansible to install the CA certificates package using the package manager.

- name: NGINX Plus | Installing CA certificates package
yum:
name: ca-certificates
state: latest

Then we tell Ansible to use the get_url module to download the NGINX Plus repo file and copy it to the /etc/yum.repos.d directory on the NGINX Plus server.

- name: NGINX Plus | Downloading yum NGINX Plus repository
get_url: url=https://cs.nginx.com/static/files/nginx-plus-7.repo dest=/etc/yum.repos.d/nginx-plus-7.repo mode=0700

The final two name sections tell Ansible to install and start NGINX Plus using the yum and service modules.

- name: NGINX Plus | Installing NGINX Plus
yum:
name: nginx-plus
state: latest
 
- name: NGINX Plus | Starting NGINX Plus
service:
name: nginx
state: started

Running Ansible to Deploy NGINX Plus

After saving the install_nginx_plus.yml file, we run the ansible-playbook command to deploy NGINX Plus. Again here we include the --ask-pass flag to have Ansible prompt for the SSH password and pass it to each NGINX Plus server, and specify the path to the main Ansible deploy.yml file.

$ sudo ansible-playbook --ask-pass $HOME/ansible-nginx-plus/deploy.yml
 
PLAY [nginx] ******************************************************************
 
GATHERING FACTS ***************************************************************
ok: [172.16.239.140]
 
TASK: [NGINX Plus | Creating NGINX Plus SSL/TLS cert repo directory] **************
changed: [172.16.239.140]
 
TASK: [NGINX Plus | Copying NGINX Plus repository certificate] ****************
changed: [172.16.239.140]
 
TASK: [NGINX Plus | Copying NGINX Plus repository key] ************************
changed: [172.16.239.140]
 
TASK: [NGINX Plus | Installing CA certificates package] ********************
changed: [172.16.239.140]
 
TASK: [NGINX Plus | Downloading yum NGINX Plus repository] ********************
changed: [172.16.239.140]
 
TASK: [NGINX Plus | Installing NGINX Plus] ************************************
changed: [172.16.239.140]
 
TASK: [NGINX Plus | Starting NGINX Plus] **************************************
changed: [172.16.239.140]
 
PLAY RECAP ********************************************************************
172.16.239.140             : ok=8    changed=7    unreachable=0    failed=0

The playbook recap was successful. Now we can run a quick curl command to verify that NGINX Plus is running. Great, we get 200 OK! Success! We have successfully installed NGINX Plus with Ansible.

$ curl -Is http://172.16.239.140 | grep HTTP
HTTP/1.1 200 OK

Creating an Ansible Playbook for Installing NGINX and NGINX Plus on Ubuntu

The process for deploying NGINX and NGINX Plus on Ubuntu servers is pretty similar to the process on CentOS, so instead of providing step‑by‑step instructions I’ll show the complete deployment files and and point out the slight differences from CentOS.

First create the Ansible directory structure and the main Ansible deployment file, as for CentOS. Also create the /etc/ansible/hosts file as described in Creating the List of NGINX Servers. For NGINX Plus, you need to copy over the key and certificate as described in Copying the NGINX Plus Certificate and Key to the Ansible Server.

Here’s the install_nginx.yml deployment file for open source NGINX. In the first section, we use the apt_key module to import the NGINX signing key. The next two sections use the lineinfile module to add the package URLs for Ubuntu 14.04 to the sources.list file. Lastly we use the apt module to update the cache and install NGINX (apt replaces the yum module we used for deploying to CentOS).

# ./ansible-nginx/tasks/install_nginx.yml
 
- name: NGINX | Adding NGINX signing key
apt_key: url=http://nginx.org/keys/nginx_signing.key state=present
 
- name: NGINX | Adding sources.list deb url for NGINX
lineinfile: dest=/etc/apt/sources.list line="deb http://nginx.org/packages/mainline/ubuntu/ trusty nginx"
 
- name: NGINX Plus | Adding sources.list deb-src url for NGINX
lineinfile: dest=/etc/apt/sources.list line="deb-src http://nginx.org/packages/mainline/ubuntu/ trusty nginx"
 
- name: NGINX | Updating apt cache
apt:
update_cache: yes
 
- name: NGINX | Installing NGINX
apt:
pkg: nginx
state: latest
 
- name: NGINX | Starting NGINX
service:
name: nginx
state: started

Here’s the install_nginx.yml deployment file for NGINX Plus. The first four sections set up the NGINX Plus key and certificate. Then we use the apt_key module to import the signing key as for open source NGINX, and the get_url module to download the apt configuration file for NGINX Plus. The shell module evokes a printf command that writes its output to the nginx-plus.list file in the sources.list.d directory. The final name modules are the same as for open source NGINX.

Note that on Ubuntu 16.04 (Xenial), apt-get drops privileges so we need to adjust the permissions of the files it needs to access.

# ./ansible-nginx-plus/tasks/install_nginx_plus.yml
 
- name: NGINX Plus | Creating NGINX Plus SSL/TLS cert repo directory
file: path=/etc/ssl/nginx state=directory group=root mode=0755
 
- name: NGINX Plus | Copying NGINX Plus repository certificate
copy: src=/etc/ssl/nginx/nginx-repo.crt dest=/etc/ssl/nginx/nginx-repo.crt owner=root group=root mode=0644
 
- name: NGINX Plus | Copying NGINX Plus repository key
copy: src=/etc/ssl/nginx/nginx-repo.key dest=/etc/ssl/nginx/nginx-repo.key owner=root group=root mode=0644
 
- name: NGINX Plus | Installing CA certificates package
yum:
name: ca-certificates
state: latest
 
- name: NGINX Plus | Adding NGINX Plus signing key
apt_key: url=http://nginx.org/keys/nginx_signing.key state=present
 
- name: NGINX Plus | Downloading Apt-Get NGINX Plus repository
get_url: url=https://cs.nginx.com/static/files/90nginx dest=/etc/apt/apt.conf.d/90nginx mode=0644
 
- name: NGINX Plus | Adding sources.list url for NGINX Plus
shell: printf "deb https://plus-pkgs.nginx.com/ubuntu `lsb_release -cs` nginx-plus\n" >/etc/apt/sources.list.d/nginx-plus.list
 
- name: NGINX Plus | Running apt-get update
apt:
update_cache: yes
 
- name: NGINX Plus | Installing NGINX Plus via apt-get
apt:
pkg: nginx-plus
state: latest
 
- name: NGINX Plus | Start NGINX Plus
service:
name: nginx
state: started

We’re now ready to run the ansible-playbook command:

$ sudo ansible-playbook --ask-pass $HOME/ansible-nginx-plus/deploy.yml

You should get a successful play recap. If you did not get a success, you can use the verbose flag to help troubleshoot your deployment as described in Running Ansible to Deploy NGINX.

Summary

What I demonstrated in this tutorial is just the beginning of what Ansible can do to help automate your NGINX or NGINX Plus deployment. There are many useful modules ranging from user account management to custom configuration templates. If you are interested in learning more about these, please visit the extensive Ansible documentation site.

To learn more, watch the video recording of my talk on deploying NGINX Plus with Ansible from nginx.conf 2015.

Editor – Check out these related blogs about other DevOps automation tools for NGINX and NGINX Plus:

To try out Ansible with NGINX Plus in your environment, start your free 30-day trial of NGINX Plus today or contact us for a live demo.

Cover image
Free O'Reilly Ebook
Your guide to everything NGINX