Nginx Ansible Galaxy Role


Nginx
For more information on Nginx, visit nginx.com


Description:


This is an Ansible role that will provision a fresh Nginx web server installation on a variety of platforms and provide a few tools to get users started quickly and easily spinning up new sites within the web server. The role utilizes a few variables that will allow the role to install with set customizations such as the http/https ports that Nginx will listen on, the directory location that SSL certificates will be stored, and an automatic basic Nginx configuration generator, that will create a new site directory, config file for the new site, as well as auto generate a self signed certificate that Nginx can use to serve the new site once there has been content placed into the newly created web directory.



Ansible Galaxy
Github


Pre-Requisites:


1.    OS:


   ROLE COMPATIBILITY:
_________________________________

  CentOS 6 and 7
  RHEL 6 and 7
  Amazon Linux 2016.09
  Debian 8 Jessie
  Ubuntu 14.04 Trusty and up


2.    Install dependencies:

  RedHat based distros (RHEL, CentOS, AL):

sudo yum -y install epel-release
sudo yum clean all
sudo yum -y install ansible



  Debian based distros (Debian, Ubuntu):

sudo apt-get update
sudo apt-get install -y curl vim python python-dev python-openssl libffi-dev libssl-dev gcc
curl "https://bootstrap.pypa.io/get-pip.py" -o "/tmp/get-pip.py"
python /tmp/get-pip.py
pip install pip ansible --upgrade
rm -fr /tmp/get-pip.py


3.    Create directory structure:

Create the directory structure that you are going to use. In this tutorial we are going to set up ansible roles in /etc/ansible/roles


mkdir -p /etc/ansible/roles || exit 0


4.    Set ansible host:

Set Ansible localhost entry so that ansible knows it will run against localhost and can talk to itself on localhost without attempting to open a TCP socket connection.


echo localhost ansible_connection=local > /etc/ansible/hosts


Ansible Role Variables:


The clusterfrak.nginx role uses a few environment variables to automatically configure Nginx. The role is set with default values for each of the available variables. Ansible will attempt to gather shell environment variable values and use those values to over-ride the default values that are set. If no shell environment variable is available or set, then ansible will configure itself to use the default values. In order to customize the installation of Nginx, simply export the ansible corresponding shell variable to set the value to something other than default prior to installing the role.


Ansible Variables:

  • http_port: 80
  • https_port: 443
  • status_port: 8080
  • site_name: "nginx.local"
  • nginx_ssl_dir: "/etc/nginx/ssl"


Mapped Shell Environment Variables:

  • HTTP_PORT - Port nginx will listen on for http connections [default:80]
  • HTTPS_PORT - Port nginx will listen on for https connections [default:443]
  • STATUS_PORT - Port nginx will use to serve web server stats [default:8080]
  • SITE_NAME - Site that nginx will set up a default server instance for [default:"nginx.local"]
  • SSL_DIR - Location that nginx will store any generated certificates [default:"/etc/nginx/ssl"]


Setting Shell Environment Variables:

To set a variable value simply export the variable prior to running the role install playbook.


export SITE_NAME="mydomain.com"


Installing the Ansible Role:


1.    Download the role from Ansible Galaxy:

Now that we have the server set up to run ansible playbooks and roles, we need to download the newest version of the role from the ansible galaxy. Running the ansible-galaxy install clusterfrak.nginx action will automatically download the role into /etc/ansible/roles/clusterfrak.nginx


cd /etc/ansible/roles
ansible-galaxy install clusterfrak.nginx


2.    Create a playbook to install the role:

Running ansible-galaxy install command will simply go to the galaxy and download the newest version of the role. Once downloaded we need to create a simple playbook that will execute the role installation.


cd /etc/ansible/
cat > nginx-role.yml << EndOfMessage
---
- hosts: all
  become: true
  roles:
    - clusterfrak.nginx
EndOfMessage


3.    Run the playbook to install the role:

Now that we have a playbook that references the role that we downloaded from ansible galaxy, simply run the role. The role will go through the entire process of installing and configuring nginx.


cd /etc/ansible/
ansible-playbook nginx-role.yml


Nginx Role Support Playbooks:


1.    /etc/ansible/roles/clusterfrak.nginx/files/nginx-reconfig.yml:

The nginx-reconfig.yml file is a playbook that will reconfigure a nginx install that has occurred using this role, with the default values set. If the role was installed with the default values, and you would like to reconfigure the server to instead use a custom site, then this playbook will do exactly that.

Installing this role with the default values will do the following:

  • Create a /var/www/html/nginx.local directory
  • Create a /etc/nginx/conf.d/nginx.local.conf nginx config file
  • All log paths, log locations, etc will reference nginx.local in the nginx config

In order to either create a self signed certificate for nginx.local or reconfigure the server to use a different domain besides nginx.local, then use the following to execute this playbook.


cd /etc/ansible/roles/clusterfrak.nginx/files
ansible-playbook nginx-reconfig.yml


   EXAMPLE:
For this example we will assume we have already ran the following "export SITE_NAME=mydomain.com" on your nginx host


This playbook will perform the following tasks:

  • If SITE_NAME has not been set, or is still set to nginx.local, then the reconfig playbook will simply generate a self signed certificate for the nginx.local domain and restart the nginx process, skipping all other major steps in the playbook.
  • If a certificate already exists for nginx.local, it will detect the existing cert and skip the cert generation step as well.
  • If SITE_NAME has been exported to a value other than nginx.local, then the playbook will use the value of SITE_NAME
  • The /var/www/html/nginx.local directory will be renamed to /var/www/html/mydomain.com
  • The /etc/nginx/conf.d/nginx.local.conf will be moved to /etc/nginx/conf.d/mydomain.com.conf
  • All paths, log names and references of nginx.local with be replaced with mydomain.com mydomain.com.conf file
  • A new self signed certificate key pair will be generated for mydomain.com and placed in /etc/nginx/ssl


nginx-reconfig.yml

---
 - hosts: all
   become: true
   vars:
      site_name: "{{ lookup('env','SITE_NAME') | default('nginx.local',true) }}"
      nginx_ssl_dir: "{{ lookup('env','SSL_DIR') | default('/etc/nginx/ssl',true) }}"

   tasks:
    # Set stats to check for the existance of the default web dir and conf file
    - name: stat web directory
      stat: path=/var/www/html/nginx.local
      register: webdir_stat

    - name: stat nginx configuration
      stat: path=/etc/nginx/conf.d/nginx.local.conf
      register: siteconfig_stat

    - name: stat nginx certificate
      stat: path={{nginx_ssl_dir}}/{{site_name}}.crt
      register: sitecert_stat

    # Rename the web directory if the default exists
    - name: reconfiguring web directory
      command: mv /var/www/html/nginx.local /var/www/html/{{site_name}}
      when: webdir_stat.stat.exists and site_name != "nginx.local"

    # Reconfigure the site config file if the default already exists
    - name: reconfiguring site
      replace: dest=/etc/nginx/conf.d/nginx.local.conf regexp='nginx.local' replace='{{site_name}}' owner=nginx group=nginx mode=644
      when: siteconfig_stat.stat.exists and site_name != "nginx.local"
      notify: restart nginx

    # Rename the nginx config file if the default already exists
    - name: reconfiguring nginx
      command: mv /etc/nginx/conf.d/nginx.local.conf /etc/nginx/conf.d/{{site_name}}.conf
      when: siteconfig_stat.stat.exists and site_name != "nginx.local"
      notify: restart nginx

    # Generate a self signed certificate for the web service
    - name: ensuring openssl is present
      package: name={{item}} state=installed
      with_items:
        - openssl

    - name: creating nginx ssl directory
      file: path={{nginx_ssl_dir}} state=directory owner=nginx group=nginx mode=0775 recurse=yes

    - name: generate self signed certificate
      command: openssl req -new -nodes -x509 -subj "/C=US/ST=US/L=US/O=\'{{site_name}}\'/OU=Self Signed/CN=\'{{site_name}}\'" -days 3650 -keyout {{nginx_ssl_dir}}/{{site_name}}.key -out {{nginx_ssl_dir}}/{{site_name}}.crt -extensions v3_ca creates={{nginx_ssl_dir}}/{{site_name}}.crt
      when: sitecert_stat.stat.exists == False
      notify: restart nginx

    # Patch the nginx config file to enable SSL
    - name: enabling ssl
      replace: 
        dest: /etc/nginx/conf.d/{{site_name}}.conf
        regexp: '{{ item.regexp }}'
        replace: '{{ item.replace }}'
        owner: nginx
        group: nginx
        mode: 644
      with_items:
        - { regexp: '#listen', replace: 'listen' }
        - { regexp: '#ssl_certificate_key', replace: 'ssl_certificate_key' }
        - { regexp: '#ssl_certificate', replace: 'ssl_certificate' }
        - { regexp: '#ssl', replace: 'ssl' }
      notify: restart nginx

   handlers:
    - name: restart nginx
      service: name=nginx state=restarted


2.    /etc/ansible/roles/clusterfrak.nginx/files/nginx-newsite.yml:


   PRE-REQUISITE STEP:
Prior to running the following nginx-newsite.yml playbook, remember to re-export SITE_NAME to the new site that you wish to configure!


   EXAMPLE:
For this example we will assume we have already ran the following `export SITE_NAME="mycoolsite2.com"` on your nginx host


In the event that you have installed the nginx role, configured for a site, and decided, that you want to create a new site on the same nginx server, a playbook to create a template for a new site has also been automatically included in the role. Again going to /etc/ansible/roles/clusterfrak.nginx/files/ and running the ansible-playbook nginx-newsite.yml playbook will perform the following tasks:


  • Create the directory /var/www/html/mycoolsite2.com
  • Create a new nginx config in /etc/nginx/conf.d/mycoolsite2.com.conf
  • Configure the config file with all paths, log locations, and references in /etc/nginx/conf.d/mycoolsite2.com.conf to mycoolsite2.com
  • Create a new self signed certificate pair in /etc/nginx/ssl/mycoolsite2.com.key and /etc/nginx/ssl/mycoolsite2.com.crt


nginx-newsite.yml


---
 - hosts: all
   become: true
   vars:
      http_port: "{{ lookup('env','HTTP_PORT') | default('80',true) }}"
      https_port: "{{ lookup('env','HTTPS_PORT') | default('443',true) }}"
      site_name: "{{ lookup('env','SITE_NAME') | default('nginx.local',true) }}"
      nginx_ssl_dir: "{{ lookup('env','SSL_DIR') | default('/etc/nginx/ssl',true) }}"

   tasks:
    # Set up new site
    - name: configuring nginx site directory
      file: path=/var/www/html/{{site_name}} state=directory owner=nginx group=nginx mode=0775 recurse=yes

    - name: configure nginx site config file
      template: src=../templates/nginx_site.conf.j2 dest=/etc/nginx/conf.d/{{site_name}}.conf owner=nginx group=nginx mode=0644
      notify: restart nginx

    # Generate a self signed certificate for the web service
    - name: ensuring openssl is present
      package: name={{item}} state=installed
      with_items:
        - openssl

    - name: creating nginx ssl directory
      file: path={{nginx_ssl_dir}} state=directory owner=nginx group=nginx mode=0775 recurse=yes

    - name: generate self signed certificate
      command: openssl req -new -nodes -x509 -subj "/C=US/ST=US/L=US/O=\'{{site_name}}\'/OU=Self Signed/CN=\'{{site_name}}\'" -days 3650 -keyout {{nginx_ssl_dir}}/{{site_name}}.key -out {{nginx_ssl_dir}}/{{site_name}}.crt -extensions v3_ca creates={{nginx_ssl_dir}}/{{site_name}}.crt
      notify: restart nginx

    # Patch the nginx config file to enable SSL
    - name: enabling ssl
      replace: 
        dest: /etc/nginx/conf.d/{{site_name}}.conf
        regexp: '{{ item.regexp }}'
        replace: '{{ item.replace }}'
        owner: nginx
        group: nginx
        mode: 644
      with_items:
        - { regexp: '#listen', replace: 'listen' }
        - { regexp: '#ssl_certificate_key', replace: 'ssl_certificate_key' }
        - { regexp: '#ssl_certificate', replace: 'ssl_certificate' }
        - { regexp: '#ssl', replace: 'ssl' }
      notify: restart nginx

   handlers:
    - name: restart nginx
      service: name=nginx state=restarted


Launch on Digital Ocean:


  CentOS 6 Userdata:


To customize the install, simply copy one of the user data scripts below and change one line from: export SITE_NAME=mydomain.com to export SITE_NAME=yourdomain.com


#!/bin/bash

# Install Epel, as it holds the lastest Ansible RPM, then update
yum install epel-release -y
rpm --import http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6
yum update -y

# Install PIP
curl "https://bootstrap.pypa.io/get-pip.py" -o "/tmp/get-pip.py"
python /tmp/get-pip.py
pip install pip --upgrade
rm -fr /tmp/get-pip.py

# Install Ansible
yum install git ansible -y
mkdir -p /etc/ansible/roles || exit 0
echo `hostname` ansible_connection=local > /etc/ansible/hosts

# Download the nginx role, create a playbook to install the role, then run the playbook
ansible-galaxy install clusterfrak.nginx
cd /etc/ansible
cat > nginx-role.yml << EndOfMessage
---
- hosts: all
  become: true
  roles:
    - clusterfrak.nginx
EndOfMessage
export SITE_NAME=mydomain.com
ansible-playbook nginx-role.yml

# Enable SSL by doing an auto reconfigure
cd /etc/ansible/roles/clusterfrak.nginx/files
ansible-playbook nginx-reconfig.yml


  CentOS 7 Userdata:


#!/bin/bash

# Install Epel, as it holds the lastest Ansible RPM, then update
yum install epel-release -y
rpm --import http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-7
yum update -y

# Install PIP
curl "https://bootstrap.pypa.io/get-pip.py" -o "/tmp/get-pip.py"
python /tmp/get-pip.py
pip install pip --upgrade
rm -fr /tmp/get-pip.py

# Install Ansible
yum install git ansible -y
mkdir -p /etc/ansible/roles || exit 0
echo `hostname` ansible_connection=local > /etc/ansible/hosts

# Download the nginx role, create a playbook to install the role, then run the playbook
ansible-galaxy install clusterfrak.nginx
cd /etc/ansible
cat > nginx-role.yml << EndOfMessage
---
- hosts: all
  become: true
  roles:
    - clusterfrak.nginx
EndOfMessage
export SITE_NAME=mydomain.com
ansible-playbook nginx-role.yml

# Enable SSL by doing an auto reconfigure
cd /etc/ansible/roles/clusterfrak.nginx/files
ansible-playbook nginx-reconfig.yml


  Debian &   Ubuntu Userdata:


#!/bin/bash

# Update and install git
sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get install -y git

# If using Ubuntu, then install some required python packages (These should be installed in debian by default)
sudo apt-get install -y python-dev python-openssl libffi-dev libssl-dev gcc

# Install Ansible using PIP
sudo easy_install pip
sudo pip install pip --upgrade
sudo pip install ansible
sudo mkdir -p /etc/ansible/roles || exit 0
sudo echo `hostname` ansible_connection=local > /etc/ansible/hosts

# Download the nginx role, create a playbook to install the role, then run the playbook
ansible-galaxy install clusterfrak.nginx
cd /etc/ansible
cat > nginx-role.yml << EndOfMessage
---
- hosts: all
  become: true
  roles:
    - nginx
EndOfMessage
sudo ansible-playbook nginx-role.yml

# Enable SSL by doing an auto reconfigure
cd /etc/ansible/roles/clusterfrak.nginx/files
ansible-playbook nginx-reconfig.yml


License


Use this playbook/role to your hearts content!

BSD


Post Requisites:


None


References: