DevOps Se­ries An­si­ble De­ploy­ment of Nginx with SSL

This is the 12th ar­ti­cle in the DevOps se­ries. It is a tu­to­rial on in­stalling Nginx with SSL. Nginx is a high per­for­mance Web server and can be used as a load bal­ancer.

OpenSource For You - - Contents - By: Shak­thi Kan­nan The au­thor is a free soft­ware en­thu­si­ast and blogs at shak­thi­maan.com.

Nginx is a Web server writ­ten in C by Igor Sysoev. It can be used as a load bal­ancer, re­verse proxy and HTTP cache server. Nginx was de­signed to han­dle over 10,000 client con­nec­tions and has sup­port for TLS (trans­port layer se­cu­rity) and SSL (se­cure sock­ets layer). It re­quires a very low mem­ory foot­print and is IPv6-com­pat­i­ble. Nginx can also be used as a mail server proxy. It was first re­leased in 2004 un­der a BSD-like li­cence.

The OpenSSL project pro­vides a free and open source soft­ware se­cu­rity li­brary that im­ple­ments the SSL and TLS pro­to­cols. This li­brary is used by ap­pli­ca­tions to se­cure com­mu­ni­ca­tion be­tween machines in a com­puter net­work. The li­brary is writ­ten in C and Assem­bly, and uses a dual­li­cence — Apache Li­cense 1.0 and a four-clause BSD li­cence. The li­brary im­ple­ments sup­port for a num­ber of ci­phers and cryp­to­graphic func­tions. It was first re­leased in 1998 and is widely used in In­ter­net Web servers.

An Ubuntu 16.04.1 LTS guest vir­tual ma­chine (VM) in­stance us­ing KVM/QEMU is cho­sen to in­stall Nginx.

$ cat /etc/lsb-re­lease

DISTRIB_ID=Ubuntu

DISTRIB_RELEASE=16.04 DISTRIB_CODENAME=xe­nial DISTRIB_DESCRIPTION=”Ubuntu 16.04.1 LTS”

The de­fault in­stal­la­tion on the guest VM does not come with Python2, and hence you need to in­stall this on the guest ma­chine, man­u­ally, as shown be­low:

$ sudo apt-get up­date

$ sudo apt-get in­stall python-min­i­mal

The host sys­tem is a Parabola GNU/Linux-li­bre x86_64 sys­tem, and An­si­ble is in­stalled on the host sys­tem us­ing the dis­tri­bu­tion pack­age man­ager. The ver­sion of An­si­ble used is 2.4.2.0 as in­di­cated be­low:

$ an­si­ble --ver­sion an­si­ble 2.4.2.0 con­fig file = /etc/an­si­ble/an­si­ble.cfg con­fig­ured mod­ule search path = [u’/home/shak­thi/.an­si­ble/ plug­ins/mod­ules’, u’/usr/share/an­si­ble/plug­ins/mod­ules’]

an­si­ble python mod­ule lo­ca­tion = /usr/lib/python2.7/sitepack­ages/an­si­ble executable lo­ca­tion = /bin/an­si­ble python ver­sion = 2.7.14 (de­fault, Sep 20 2017, 01:25:59) [GCC 7.2.0]

You should add an en­try to the /etc/hosts file for the guest Ubuntu VM, as fol­lows:

192.168.122.244 ubuntu

On the host sys­tem, let’s cre­ate a project direc­tory struc­ture to store the An­si­ble play­books, in­ven­tory and con­fig­u­ra­tion files, as fol­lows:

an­si­ble/in­ven­tory/kvm/ /play­books/con­fig­u­ra­tion/ /play­books/ad­min/

/files/

An ‘in­ven­tory’ file is cre­ated in­side the in­ven­tory/kvm folder that con­tains the fol­low­ing:

ubuntu an­si­ble_host=192.168.122.244 an­si­ble_­con­nec­tion=ssh an­si­ble_user=ubuntu an­si­ble_­pass­word=pass­word

You should now be able to is­sue com­mands to the guest OS, us­ing An­si­ble. For ex­am­ple:

$ an­si­ble -i in­ven­tory/kvm/in­ven­tory ubuntu -m ping ubuntu | SUC­CESS => {

“changed”: false,

“ping”: “pong”

In­stalling Nginx

The Nginx soft­ware pack­age in Ubuntu can be in­stalled on the guest ma­chine. The APT pack­age repos­i­tory is first up­dated be­fore in­stalling the Nginx Web server. The Un­com­pli­cated Fire­wall (UFW) is then used to en­able both HTTP and

HTTPS ac­cess on the guest OS. The Web server is then started, and the play­book waits for the server to lis­ten on port 80. The An­si­ble play­book is pro­vided be­low for ref­er­ence:

--name: In­stall nginx hosts: ubuntu be­come: yes be­come_method: sudo gath­er_­facts: true tags: [nginx]

tasks:

- name: Up­date the soft­ware pack­age repos­i­tory apt: up­date_­cache: yes

- name: In­stall nginx pack­age: name: “{{ item }}” state: lat­est with­_items:

- nginx

- name: Al­low Nginx Full ufw: rule: al­low name: Nginx Full state: en­abled

- name: Al­low Nginx Full ufw: rule: al­low name: OpenSSH state: en­abled

- name: Start nginx ser­vice: name: nginx state: started

- wait­_­for: port: 80

The above play­book can be in­voked as fol­lows:

$ an­si­ble-play­book -i in­ven­tory/kvm/in­ven­tory play­books/ con­fig­u­ra­tion/nginx-ssl.yml --tags nginx -K

The -K op­tion prompts for the sudo pass­word of the Ubuntu user. You can ap­pend mul­ti­ple -v to the end of the play­book in­vo­ca­tion to get a more ver­bose out­put.

If you open a browser on the host sys­tem with the URL http://192.168.122.244, you should see the de­fault Nginx home page as shown in Fig­ure 1.

Gen­er­at­ing SSL cer­tifi­cates

The re­quired SSL cer­tifi­cates need to be cre­ated us­ing An­si­ble. The OpenSSL and Python-openssl pack­ages are in­stalled af­ter up­dat­ing the APT soft­ware repos­i­tory in Ubuntu. An OpenSSL pri­vate key is gen­er­ated in the /etc/ssl/pri­vate/an­si­ble.com.pem file. The /etc/ssl/csr direc­tory is cre­ated be­fore gen­er­at­ing the OpenSSL cer­tifi­cate sign­ing re­quest (CSR) with the re­quired cer­tifi­cate pa­ram­e­ters in the /etc/ssl/csr/www.an­si­ble.com. csr file. The ac­tual self-signed cer­tifi­cate is then gen­er­ated as shown in the fol­low­ing play­book:

- name: Cre­ate SSL cer­tifi­cates hosts: ubuntu be­come: yes be­come_method: sudo gath­er_­facts: true tags: [ssl]

tasks:

- name: Up­date the soft­ware pack­age repos­i­tory apt: up­date_­cache: yes

- name: In­stall openssl pack­age:

name: “{{ item }}” state: lat­est with­_items:

- openssl - python-openssl

- name: Gen­er­ate an OpenSSL pri­vate key openss­l_pri­vatekey: path: /etc/ssl/pri­vate/an­si­ble.com.pem

- name: Cre­ate direc­tory file: path: /etc/ssl/csr state: direc­tory mode: 0755

- name: Gen­er­ate an OpenSSL Cer­tifi­cate Sign­ing Re­quest openss­l_csr: path: /etc/ssl/csr/www.an­si­ble.com.csr pri­vatekey_­path: /etc/ssl/pri­vate/an­si­ble.com.pem coun­try_­name: IN or­ga­ni­za­tion_­name: An­si­ble email_ad­dress: au­thor@shak­thi­maan.com com­mon_­name: www.an­si­ble.com

- name: Gen­er­ate a self signed cer­tifi­cate openss­l_cer­tifi­cate: path: /etc/ssl/certs/nginx-self­signed.crt pri­vatekey_­path: /etc/ssl/pri­vate/an­si­ble.com.pem csr_­path: /etc/ssl/csr/www.an­si­ble.com.csr provider: self­signed

The above play­book can be run as fol­lows:

$ an­si­ble-play­book -i in­ven­tory/kvm/in­ven­tory play­books/ con­fig­u­ra­tion/nginx-ssl.yml --tags ssl -K

Con­fig­ur­ing Nginx for SSL

The fi­nal step is to con­fig­ure Nginx to use SSL. A self-signed. conf file is cre­ated in the /etc/nginx/snip­pets folder that con­tains the fol­low­ing:

ss­l_cer­tifi­cate /etc/ssl/certs/nginx-self­signed.crt; ss­l_cer­tifi­cate_key /etc/ssl/pri­vate/an­si­ble.com.pem;

The SSL pa­ram­e­ter con­fig­u­ra­tions are stored in the /etc/ nginx/snip­pets/ssl-params.conf file as shown be­low:

# from https://ci­pherli.st/

# and https://raymii.org/s/tu­to­ri­als/Strong_SSL_Se­cu­ri­ty_On_ nginx.html

ss­l_pro­to­cols TLSv1 TLSv1.1 TLSv1.2; ss­l_prefer­_server_­ci­phers on; ss­l_­ci­phers “EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+E DH”; ss­l_ecd­h_curve secp384r1; ss­l_ses­sion_­cache shared:SSL:10m; ss­l_ses­sion_tick­ets off; ss­l_sta­pling on; ss­l_sta­pling_ver­ify on; re­solver 8.8.8.8 8.8.4.4 valid=300s; re­solver_­time­out 5s;

# Dis­able preload­ing HSTS for now. You can use the com­mented out header line that in­cludes

# the “preload” di­rec­tive if you un­der­stand the im­pli­ca­tions. #ad­d_­header Strict-Trans­port-Se­cu­rity “max-age=63072000; in­cludeSub­do­mains; preload”; ad­d_­header Strict-Trans­port-Se­cu­rity “max-age=63072000; in­cludeSub­do­mains”; ad­d_­header X-Frame-Op­tions DENY; ad­d_­header X-Con­tent-Type-Op­tions nos­niff;

The Nginx Web server con­fig­u­ra­tion for this host (google. com, for ex­am­ple) is then cre­ated in the /etc/nginx/site­sen­abled folder with the fol­low­ing con­tents:

server { lis­ten 80;

root /var/www/html; in­dex in­dex.nginx-de­bian.html;

server_­name google.com www.google.com; }

server { lis­ten 443 ssl http2 de­fault­_server; in­clude snip­pets/self-signed.conf; in­clude snip­pets/ssl-params.conf; }

The An­si­ble play­book for con­fig­ur­ing Nginx with SSL is as fol­lows:

- name: Setup nginx with SSL hosts: ubuntu be­come: yes be­come_method: sudo gath­er_­facts: true tags: [https]

tasks:

- copy: src: ../../files/self-signed.conf dest: /etc/nginx/snip­pets/self-signed.conf owner: root group: root mode: 0644

- copy: src: ../../files/ssl-params.conf dest: /etc/nginx/snip­pets/ssl-params.conf owner: root group: root mode: 0644

- copy: src: ../../files/google.com dest: /etc/nginx/sites-en­abled/google.com owner: root group: root mode: 0644

- name: Restart nginx ser­vice: name: nginx state: restarted

- wait­_­for: port: 443

The above play­book can be ex­e­cuted as fol­lows:

$ an­si­ble-play­book -i in­ven­tory/kvm/in­ven­tory play­books/ con­fig­u­ra­tion/nginx-ssl.yml --tags https -K

You can now open https://192.168.122.244 in a browser on the host sys­tem, and view the self-signed cer­tifi­cate as shown in Fig­ure 2.

Af­ter ac­cept­ing the cer­tifi­cate, you will be able to see the de­fault Nginx home page as shown in Fig­ure 3.

You can also use the curl com­mand to view the home page from the com­mand line, as fol­lows:

$ curl https://192.168.122.244 -k

<!DOCTYPE html>

<html>

<head>

<ti­tle>Wel­come to nginx!</ti­tle>

<style> body { width: 35em; mar­gin: 0 auto; font-fam­ily: Ta­homa, Ver­dana, Arial, sans-serif;

}

</style>

</head>

<body>

<h1>Wel­come to nginx!</h1>

<p>If you see this page, the nginx web server is suc­cess­fully in­stalled and work­ing. Fur­ther con­fig­u­ra­tion is re­quired.</p> <p>For on­line doc­u­men­ta­tion and sup­port please re­fer to <a href=”http://nginx.org/”>nginx.org</a>.<br/> Com­mer­cial sup­port is avail­able at

<a href=”http://nginx.com/”>nginx.com</a>.</p>

<p><em>Thank you for us­ing nginx.</em></p> </body>

</html>

Val­i­da­tion

You can run a num­ber of val­i­da­tion checks on the SSL cer­tifi­cate, pe­ri­od­i­cally, to as­cer­tain that it still holds good and meets your re­quire­ments. A few ex­am­ples of san­ity checks that you can per­form on the cer­tifi­cate are shown be­low for ref­er­ence:

- name: Val­i­date SSL cer­tifi­cate hosts: ubuntu be­come: yes be­come_method: sudo gath­er_­facts: true tags: [val­i­date]

tasks:

- name: Cer­tifi­cate matches with the pri­vate key openss­l_cer­tifi­cate: path: /etc/ssl/certs/nginx-self­signed.crt pri­vatekey_­path: /etc/ssl/pri­vate/an­si­ble.com.pem provider: as­ser­tonly

- name: Cer­tifi­cate can be used for dig­i­tal sig­na­tures openss­l_cer­tifi­cate: path: /etc/ssl/certs/nginx-self­signed.crt provider: as­ser­tonly key_usage:

- dig­i­talSig­na­ture key_usage_strict: true

- name: Cer­tifi­cate uses a re­cent sig­na­ture al­go­rithm (no SHA1, MD5 or DSA) openss­l_cer­tifi­cate: path: /etc/ssl/certs/nginx-self­signed.crt provider: as­ser­tonly sig­na­ture_al­go­rithms:

- sha224WithRSAEn­cryp­tion

- sha256WithRSAEn­cryp­tion

- sha384WithRSAEn­cryp­tion

- sha512WithRSAEn­cryp­tion - sha224WithECDSAEn­cryp­tion - sha256WithECDSAEn­cryp­tion - sha384WithECDSAEn­cryp­tion - sha512WithECDSAEn­cryp­tion

- name: Cer­tifi­cate matches the do­main openss­l_cer­tifi­cate: path: /etc/ssl/certs/nginx-self­signed.crt provider: as­ser­tonly sub­jec­t_alt_­name:

- DNS:www.an­si­ble.com

- name: Cer­tifi­cate is valid for another month (30 days) from now openss­l_cer­tifi­cate: path: /etc/ssl/certs/nginx-self­signed.crt provider: as­ser­tonly valid_in: 2592000

You can in­voke the above val­i­da­tion checks in the play­book us­ing the fol­low­ing com­mand:

$ an­si­ble-play­book -i in­ven­tory/kvm/in­ven­tory play­books/ con­fig­u­ra­tion/nginx-ssl.yml --tags val­i­date -K

Unin­stalling

An unin­stall play­book is pro­vided in the play­books/ad­min/ unin­stall-nginx.yml file to stop the Nginx Web server, dis­able ac­cess to the port in the fire­wall, and to re­move the soft­ware from the guest VM:

--name: Unin­stall Nginx hosts: ubuntu be­come: yes be­come_method: sudo gath­er_­facts: true tags: [server]

tasks:

- name: Stop the web server ser­vice: name: nginx state: stopped

- name: Dis­able Nginx Full ufw: rule: deny name: Nginx Full state: en­abled

- name: Unin­stall apache2 pack­age: name: “{{ item }}” state: ab­sent with­_items:

- nginx

The above play­book can be run as fol­lows:

$ an­si­ble-play­book -i in­ven­tory/kvm/in­ven­tory play­books/ ad­min/unin­stall-nginx.yml -K

You can ver­ify the fire­wall sta­tus us­ing the ufw com­mand, as shown be­low:

$ sudo ufw sta­tus Sta­tus: ac­tive To Ac­tion From

-Nginx -----Nginx ---Nginx Full DENY Any­where OpenSSH AL­LOW Any­where

Nginx Full (v6) DENY Any­where (v6) OpenSSH (v6) AL­LOW Any­where (v6) Please re­fer to the Nginx doc­u­men­ta­tion web­site (https://nginx.org/en/docs/) for more in­for­ma­tion.

Fig­ure 1: Nginx home page

Fig­ure 2: SSL cer­tifi­cate

Fig­ure 3: Nginx HTTPS home page

Newspapers in English

Newspapers from India

© PressReader. All rights reserved.