Table of Contents
- Before starting
- Installing LetsEncrypt and SSL 2.1. Using Mac OS X 2.2. Using Linux
- Adding SSL to nginx
- Using HTTP2 with SSL in nginx
- Adding security
Before starting
Before we start you should take a read of my previous articles on setting up the basic PHP7, nginx and MySQL on Debian 8 and getting it configured.
You can catch up by going here: Part 1 of Installing PHP7 with nginx and MySQL for installing and Part 2 of Installing PHP7 with nginx and MySQL for configuring.
Installing LetsEncrypt and SSL
So when it comes to security on the web, most will talk about having an SSL and using OpenSSL. These things will make your site more attractive to Search Engines and also give your users abit of comfort that middleman attacks aren't going to be much of an issue.
LetsEncrypt is an open-source FREE SSL TLS certificate generator. It will generate you a certificate for you to use in nginx.
I had to do this on my Mac to be able to generate a certificate for my server as I was unable to build due to memory issues. I will show you both in this article.
Using Mac OS X
First off lets go through how I set this up on Mac. If you are new to OS X then I would suggest looking up how to use Brew and getting Homebrew setup. Click here to find some results for installing homebrew.
With Brew and xcode installed you will need the letsencrypt repo so install Git and clone the repo so fire up terminal and lets begin with:
cd ~
git clone https://github.com/letsencrypt/letsencrypt
Next you need to install Python, I used 2.7.10 for my version and once you have python you need Pip:
sudo easy_install pip
Once you have Pip installed you can install VirtualEnv and its wrapper:
sudo pip install virtualenv virtualenvwrapper
Now you have those installed you can run the build letsencrypt:
cd letsencrypt
./letsencrypt-auto certonly -a manual --rsa-key-size 4096 -d mysite.com -d www.mysite.com
After a while you will get a lovely set of screens that you will need to validate your website. Its fairly easy to do, follow the steps it gives you and upload the file it asks for and you are complete.
You'll find your files available in /etc/letsencrypt, now you can place them on the server in the next part.
Using Linux
So first we need to get git installed to our Debian machine using:
sudo apt-get install git
With git installed we can now clone the repo:
cd ~
git clone https://github.com/letsencrypt/letsencrypt
Once it has cloned the repo you can use the command letsencrypt-auto
like so:
cd letsencrypt
./letsencrypt-auto certonly -a manual --rsa-key-size 4096 -d mysite.com
Now letsencrypt installs the required packages and once it has completed you will be presented with some screens to fill some details out. Follow the steps and add the relevant file to your server using:
sudo nano /var/www/mysite.com/public_html/.wellknown/acme-challenge/mYranDomStriNgFILeNamEIamAsKeDToUpLOaD
Then paste/type in the challenge you are given. Save this file and then check it exists on your server before continuing the final step. Once completed your cert and files are going to be in /etc/letsencrypt
Adding SSL to nginx
Now you should have the following files:
- cert.pem
- chain.pem
- fullchain.pem
- privkey.pem
If you cannot find these files they are locked inside /etc/letsencrypt/live/mysite.com
. So now we need to edit our nginx configuration to have the following:
listen 443 ssl;
ssl_certificate /path/to/my/ssl/fullchain.pem;
ssl_certificate_key /path/to/my/ssl/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
Redirect the old port 80 to 443 in this case I altered my server block from the last parts and added this above what I had edited:
server {
server_name mysite.com www.mysite.com;
listen 80;
return 301 https://$host$request_uri;
}
This forces any non-HTTPS user to HTTPS.
Furthermore for my example I stored my SSLs in the folder /etc/nginx/ssl/mysite.com/
its secure and away from the webroot and also is in the same area as nginx so easy to find for if I need to change anything.
The above nginx config will get you basic ssl ready so now you need to restart nginx using:
sudo service nginx restart
Accessing your site should now redirect you to https with a vaild certificate.
There you go, basic ssl.
Using http2 with ssl in nginx
Now that SSL is configured and running we should bring our standards up a little and improve the performance.
Lets check that we have http_v2 module installed by running:
sudo nginx -V
Look for --with-http_v2_module
and it should be installed if you followed the previous parts of this guide.
If not you will need to add it but rebuilding nginx. This is fairly easy to do by downloading the source for nginx. First get the libraries required for building sources:
sudo apt-get install build-essential zlib1g-dev libpcre3 libpcre3-dev libbz2-dev libssl-dev tar unzip
Then grab the source:
cd ~
wget http://nginx.org/download/nginx-1.9.5.tar.gz
tar -xzvf nginx-1.9.5.tar.gz
Now we have the files extracted and in our home directory lets build it with a basic configuration:
cd nginx-1.9.5
./configure \
--prefix=/etc/nginx \
--sbin-path/usr/sbin/nginx \
--modules-path=/usr/lib/nginx/modules \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--pid-path=/var/run/nginx.pid \
--lock-path=/var/run/nginx.lock \
--user=www-data \
--group=www-data \
.....
** Add other modules here ***
.....
--with-http_ssl_module \
--with-http_v2_module
Within the section
.....
** Add other modules here ***
.....
Make sure you add your own modules for example you may want gzip. If you need guidance look at your previous installed modules and install those along with the http ssl module and http v2 module.
Now that http_v2_module is ready all you need to do is change your site server configuration block and replace: listen 443 ssl;
to:
server{
listen 443 http2;
ssl_certificate /path/to/my/ssl/cert.pem;
ssl_certificate_key /path/to/my/ssl/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
...
}
Adding security
There a few things you can do to buff up your security of your server.
First thing you can do is is take a look at configurations for nginx to see best practices and include headers to stop certain actions.
Place the following in your server blocks as required
server_tokens off;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
Server tokens off means that your server will not display its current version of nginx, making it less apparent what server and version you are running.
Next you have frame options which mean that only your site can iframe/frame content from the server this stops something called clickjacking. Change this as appropriate.
Then you have Content Type Options which which is for user supplied content this stops content-type sniffing for some of the browsers.
Finally using the header XSS protection will force the browser to advertise its xss filter if available.
Next you will want to add another layer of security by applying a Diffie-Hellman parameter to your SSL by running the command:
openssl dhparam -out /path/to/my/ssl/dhparam.pem 2048
This will create a dhparam.pem file you can use in your configuration:
ssl_dhparam /path/to/my/ssl/dhparam.pem;
There are a few more options you can add such as:
ssl_trusted_certificate /path/to/my/ssl/fullchain.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
These will force your session to timeout after 1 day and cause the session to resume if before that.
All of the features outline above are completely optional and if you would like to read more check the following pages for more information:
Best nginx configuration for improved security(and performance)
I would also recommend reading more on security with servers and get used to protecting your applications from unwanted use and attacks.