Commands Only - Raspberry Pi Nginx HTTPS & SPDY Secure Web Server

Commands Only - For Professionals Only


Why and how you'd get the very latest Nginx installed on Raspbian (or Debian) & how to serve your site securely over HTTPS/SPDY


The default Nginx installed via apt-get is very old


Existing Nginx users

sudo cp -r /etc/nginx ~/Desktop/apt-get-nginx

Those of you who aren't yet running Nginx on your Pi

sudo apt-get install nginx

Everyone

sudo apt-get remove nginx

cd ~
wget https://gist.githubusercontent.com/MaXwellFalstein/eecfe12be81ef4698610/raw/c66aca57dc56a9241801f99f8175a477aba4c05c/build_nginx.sh
(You don't have to type all that, just copy and paste it into your Terminal)

Go to the following URLs and just check what the latest versions are:

	https://www.openssl.org/source/
	http://www.pcre.org/
	http://nginx.org/en/download.html

sudo chmod +x build_nginx.sh

sudo ./build_nginx.sh
This will take quite a long time on the Pi – as in 20min or more.

If you did not have nginx installed previously, you're now set to go, you just need to start nginx (see the next section). You can set up a website in the normal way – if you don't know 'the normal way', try following my Setting up a (reasonably) secure home web server with Raspberry Pi tutorial, but skip the setting up the Pi and installation of nginx parts.

If you had nginx installed previously everything should just work for you now. However it might not. If not it's likely that the new version of nginx might be reading your existing config files expecting some form of new option, or be seeing an option in your configuration files that's no longer valid. You could tinker about and google until you know what's different, or you could 'revert' your /etc/nginx directory to the default contents nginx last compiled with, and then manually re-configure those while referencing your old files.

sudo mv /etc/nginx /etc/nginx-broken
sudo mv /etc/nginx-default /etc/nginx

Refer to the files in your nginx-broken directory and amend the ones in /etc/nginx.

sudo service nginx start

If you want to go down the selft-signed certificate route, follow this tutorial on how to create a self-signed certificate.

Once you have completed signing up for an SSL Certificate you should be in possession of three files:

	yourdomain.key
	yourdomain.pem
	ca-bundle.pem


sudo mkdir /etc/nginx/my_ssl_certs

You need to get all of those files onto your pi and in that folder. If you've registered for the SSL Cert directly on your Pi you can just download them in the normal way. If you've been registering via a different machine and are using the Pi through Terminal only, you're going to need to download the files onto the machine you've been using for registering and then use scp to move them from that machine onto your pi, e.g., On the machine you've downloaded the files onto…

scp yourdomain.key yourdomain.pem ca-bundle.pem pi@IPOFYOURPI:~/

Now, ssh onto your Pi and move those files into the directory we want. We didn't copy them directly there as the pi user shouldn't have permission to write files into /etc/nginx.

On your Pi:

sudo mv ~/yourdomain.key ~/yourdomain.pem ~/ca-bundle.pem /etc/nginx/my_ssl_certs

Last thing, we need to create one more file for use when Perfect Forward Secrecy algorithms are used (which we absolutely want).

Again, on the pi, and inside the /etc/nginx/my_ssl_certs directory;
Warning: this command will take a long time to complete!

sudo openssl dhparam -rand - 4096 >> dhparam.pem

When you run this, the program means what it says; it's going to take a long time, almost 24hrs for a 4096bit value. If you want, change that to 2048 instead and it'll lop the time off considerably (but be less secure). Now might be a good time to read a few chapters of a decent book (I can recommend anything by Brandon Sanderson, if you're interested). Or you could go learn why big prime numbers make things secure (that's what this is doing; making a huge prime number).

With all files now on your pi and in the /etc/nginx/my_ssl_certs directory you can use them to secure your site!

In the nginx file that defines your site (/etc/nginx/sites-available/yoursite) you'll need to set the following (adjusting to your needs, this is a basic set-up which forbids HTTP and enforces HTTPS, using SPDY if SPDY is available on the browser that's trying to connect):

  server {
  # REDIRECT HTTP TO HTTPS
      server_name yourdomain.com;
      add_header  Strict-Transport-Security max-age=15768000;
      return 301  https://yourdomain.com$request_uri;
  }

  server {
      # SET THE SITE UP FOR SSL
      listen 443 ssl spdy;
      # Get SSL setup
      ssl                 on;
      ssl_certificate     /etc/nginx/my_ssl_certs/yourdomain.pem;
      ssl_certificate_key /etc/nginx/my_ssl_certs/yourdomain.key;
      ssl_dhparam         /etc/nginx/my_ssl_certs/dhparam.pem;
      ssl_session_timeout 5m;
      ssl_protocols       SSLv3 TLSv1 TLSv1.1 TLSv1.2;
      ssl_ciphers         'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:AES128:AES256:RC4-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK';
      ssl_prefer_server_ciphers on;
      ssl_session_cache         shared:SSL:50m;
      # Enable HSTS
      add_header Strict-Transport-Security max-age=15768000;
      # OCSP Stapling
      ssl_stapling            on;
      ssl_stapling_verify     on;
      ssl_trusted_certificate /etc/nginx/my_ssl_certs/ca-bundle.pem;
      resolver                8.8.8.8;
      # NOW CONFIGURE YOUR SITE BELOW, e.g,
      server_name yourdomain.com;
      root        /path/to/your/website/files;
      index       index.html index.htm;
      access_log /path/to/your/website/logs/access.log;
      error_log  /path/to/your/website/logs/error.log;
      error_page 404 /404.html;
      location / {
          try_files $uri $uri/;
      }

Be sure to replace the list of ssl_ciphers from this example with whatever the latest recommended cipher-suite from Mozilla is – choosing good ciphers in a good order is complex; you can render your server far less secure by doing this bit wrong – so just grab what the experts have compiled and use that.

Restart nginx as follows:

sudo service nginx restart

Your site should now be serving over HTTPS. To test it, run your domain through https://www.ssllabs.com/ssltest/