Configuration

Comment out the whole server section in /etc/nginx/sites-available/default.

PHP web site

To start with the basics, we will create a PHP site.

_$: service php5-fpm status
 * php5-fpm is running

Check where is listening by default fastCGI

/etc/php5/fpm/pool.d/www.conf:
------------------------------
...
user = www-data
group = www-data
...
listen = /var/run/php5-fpm.sock
...
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
_$: service php5-fpm restart

Create the web site:

/etc/nginx/sites-available/nginx-php:
-------------------------------------
server {
        listen 80;
        root   /var/www;

        location / {
                index index.php;
        }

        location ~ \.(css|js)$ {
                access_log  off;
        }

        location ~ \.php$ {
                include /etc/nginx/fastcgi_params;
                fastcgi_index index.php;
                fastcgi_pass  unix:/var/run/php5-fpm.sock;
                fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
        }
}
_$: ln -s /etc/nginx/sites-available/nginx-php /etc/nginx/sites-enabled/
_$: mv /etc/nginx/sites-available/default /etc/nginx/sites-available/default.bak
_$: service nginx restart

Be warned: the next file will expose your system, so don’t do it in a host facing the hordes of untrustworthy people on the internet.

/var/www/index.php:
-------------------
<?php phpinfo(); ?>

Python web site

For the next web site we will use HTTPS, so we need to configure it beforehand.

SSL

_$: mkdir /etc/nginx/ssl
_$: cd /etc/nginx/ssl
_$: openssl genrsa -des3 -out server.key 2048       (pass: ...)
_$: openssl req -new -key server.key -out server.csr
Enter pass phrase for server.key:                   (pass: ...)
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:SP
State or Province Name (full name) [Some-State]:Aragon
Locality Name (eg, city) []:ZGZ
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
_$: cp server.key server.key.org
_$: openssl rsa -in server.key.org -out server.key      (pass: ...)
_$: openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

Check the certificate

_$: openssl x509 -in server.crt -text -noout

Nginx with uWSGI

/etc/nginx/sites-available/webapp:
----------------------------------
upstream webapp_app_server {
        server unix:///var/run/uwsgi/uwsgi.sock;
}

server {
        server_name webapp.example.com;
        listen 80;

        # SSL
        listen 443 ssl;
        ssl_certificate     /etc/nginx/ssl/server.crt;
        ssl_certificate_key /etc/nginx/ssl/server.key;

        ssl_ciphers                 RC4:HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers   on;

        ...
}
_$: nginx -t && service nginx reload
/etc/nginx/uwsgi_params:
------------------------
uwsgi_param        QUERY_STRING             $query_string;
uwsgi_param        REQUEST_METHOD           $request_method;
uwsgi_param        CONTENT_TYPE             $content_type;
uwsgi_param        CONTENT_LENGTH           $content_length;

uwsgi_param        REQUEST_URI              $request_uri;
uwsgi_param        PATH_INFO                $document_uri;
uwsgi_param        DOCUMENT_ROOT            $document_root;
uwsgi_param        SERVER_PROTOCOL          $server_protocol;

uwsgi_param        UWSGI_SCHEME             $scheme;        <== http + https

uwsgi_param        REMOTE_ADDR              $remote_addr;
uwsgi_param        REMOTE_PORT              $remote_port;
uwsgi_param        SERVER_PORT              $server_port;
uwsgi_param        SERVER_NAME              $server_name;

Default web site

If we want all the requests that don’t match with either (PHP or Python) web site, we can create another one to catch those requests. Another option is to make one of the others the default. In any case, we will add the default_server flag to the listen option.

/etc/nginx/sites-available/zz:
------------------------------
server {
        server_name  _;
        listen       80 default_server;
        root         /var/www/zz;

        location / {
                index  index.html;
        }
}

This is an example of a highly responsive and lean web site. Take note of it!

/var/www/zz/index.html:
-----------------------
<!DOCTYPE html>
<meta charset="UTF-8"/>
<title> </title>
_$: ln -s /etc/nginx/sites-available/zz /etc/nginx/sites-enabled/
_$: service nginx restart

HTTP 2

Nginx version has to be >= 1.9.5

_$: nginx -v
nginx version: nginx/1.10.0 (Ubuntu)

OpenSSL version has to be >= 1.0.2

_$: openssl version
OpenSSL 1.0.2g  1 Mar 2016

Let’s create a DHE key of 2048 bits:

_$: openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048
/etc/nginx/sites-available/webapp:
----------------------------------
upstream webapp_app_server {
        server unix:///var/run/uwsgi/uwsgi.sock;
}

server {
        server_name webapp.example.com;
        listen 80;

        # SSL
        listen 443 ssl;
        ssl_certificate     /etc/nginx/ssl/server.crt;
        ssl_certificate_key /etc/nginx/ssl/server.key;

        # Intermmediate ciphers: Firefox 1, Chrome 1, IE 7, Opera 5, Safari 1, Windows XP IE8, Android 2.3, Java 7
        ssl_ciphers ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS;

        # Modern ciphers: Firefox 27, Chrome 30, IE 11 on Windows 7, Edge, Opera 17, Safari 9, Android 5.0, and Java 8
        ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256;

        ssl_prefer_server_ciphers   on;
        ssl_dhparam                 /etc/nginx/ssl/dhparam.pem;
    ...
}
_$: nginx -t && systemctl restart nginx