Installing letsencrypt.org SSL Certificates on NGINX in 5 minutes or less
In 2014 Google announced they would be using HTTPS as a ranking signal. It’s been two years and now this rule is fully implemented and paving the road to a safer internet.
When originally announced, the enforcement of HTTPS was met with an immediate outcry due to what was considered a pay-wall for smaller websites. This could be mainly attributed to the fact that back then, usually, SSL certificates were either expensive or hard to implement (depending on the issuer).
Thus, the Let’s Encrypt project was born. As stated on the website, Let’s Encrypt is free, automated, and open. Today I’m going to show you how to implement a Let’s Encrypt certificate in NGINX in 5 minutes or less. (This guide assumes that you have already purchased a domain, set up the necessary DNS configuration to have said domain to point to your NGINX host, and have root access through ssh to your NGINX host.)
The steps we are going to follow are:
- Setup NGINX with dummy config
- Download Certbot
- Run
certbot-auto
- Setup NGINX with SSL config
Let’s Encrypt uses an automated script called certbot which certifies ownership of a website. Certbot can certify ownership of a host/domain through several means. In this guide, we are going to have certbot
generate a file under a sub-folder which should be accessible through your domain. Certbot
will then look for the file at the expected randomly generated address and verify the contents of the file.
Let’s assume you have the domain yoursite.io
and you wish to sprinkle some free encrypting sugar on top of it.
1. Setup NGINX with dummy config
You may want to backup your site’s current configuration for this step.
For simplicity’s sake, we’re going to have NGINX temporarily serve all files under the root of your site. First, go and replace your sites config with the following:
server {
listen 80;
listen [::]:80;
root /path/to/yoursite;
index index.html;
server_name yoursite.io;
location / {
try_files $uri $uri/ =404;
}
}
Pro tip: For added security, you should temporarily change the root
path on the config to a temp folder rather than the site’s actual directory, so you don’t share the entirety of your site’s source code and assets with the whole world.
Restart NGINX:
$ sudo service nginx restart
Place a dummy file on your root folder and make sure it’s accessible through your browser (i.e. http://yoursite.io/dummy.txt).
If all is good and accesible we can move on forward to step 2!
2. Download Certbot
The most stable way of running certbot is to download its source from github and firing-up the included certbot-auto
script.
In order to download the code you’ll need git
. To make sure you have git
installed run:
$ git --version
You should see something like:
$ git --version
git version 2.8.1
With git
in place go ahead and run the following to clone the certbot
repository from github:
$ git clone
https://github.com/certbot/certbot.git
This should have created the certbot
directory and placed the repository’s contents inside.
3. Run certbot-auto
Change the directory to the newly downloaded certbot
folder:
$ cd certbot
As previously mentioned, certbot has many ways of certifying ownership of a website, and in this guide we’ll cover only the following:
$ ./certbot-auto certonly --webroot -w /path/to/yoursite -d
yoursite.io
In a few words, the previous command tells certbot you only want to generate a certificate for your site, that your site’s path is /path/to/yoursite
and that the domain you are certifying is yoursite.io
.
In running the command, certbot will auto-magically detect your OS and set-up the sauces necessary to run. This might take a while.
Once run, you’ll get a long success message, but the line we’re interested in is:
Congratulations! Your certificate and chain have been saved at /etc/letsencrypt/live/
yoursite.io/fullchain.pem
.
More specifically the path to your certificate and key; which in this case would be: /etc/letsencrypt/live/
yoursite.io/
4. Setup NGINX with SSL config
Now that we have generated the certificate and know where it is stored, all that’s left to do is to restore your configuration and add the SSL specifics to it.
For an added aid I will share with you three common configurations for using with a static file server: a port proxy server (rails, angular, etc), and a PHP server.
Static file server example:
server {
listen 443;
listen [::]:443;
root /path/to/yoursite;
index index.html;
server_name yoursite.io;
location / {
try_files $uri $uri/ =404;
}
ssl on;
ssl_session_cache shared:SSL:50m;
ssl_certificate /etc/letsencrypt/live/yoursite.io/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yoursite.io/privkey.pem;
ssl_client_certificate /etc/letsencrypt/live/yoursite.io/fullchain.pem;
ssl_session_timeout 5m;
}
server {
# Redirect www to non-www
listen 443;
listen [::]:443;
server_name www.yoursite.io;
return https://yoursite.io$request_uri;
}
server {
# Redirect all calls to HTTP (port 80) to HTTPS
listen 80;
listen [::]:80;
server_name www.yoursite.io yoursite.io;
return https://yoursite.io$request_uri;
}
Port proxy server (rails, angular, etc) example:
server {
listen 443;
listen [::]:443;
root /path/to/yoursite;
index index.html;
server_name yoursite.io;
location / {
# Example for proxying requests to a web-app/service/api running on port 3000
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
}
ssl on;
ssl_session_cache shared:SSL:50m;
ssl_certificate /etc/letsencrypt/live/yoursite.io/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yoursite.io/privkey.pem;
ssl_client_certificate /etc/letsencrypt/live/yoursite.io/fullchain.pem;
ssl_session_timeout 5m;
}
server {
# Redirect www to non-www
listen 443;
listen [::]:443;
server_name www.yoursite.io;
return https://yoursite.io$request_uri;
}
server {
# Redirect all calls to HTTP (port 80) to HTTPS
listen 80;
listen [::]:80;
server_name www.yoursite.io yoursite.io;
return https://yoursite.io$request_uri;
}
PHP server example:
server {
listen 443;
listen [::]:443;
root /path/to/yoursite;
index index.html;
server_name yoursite.io;
location / {
# unless the request is for a valid file, send to bootstrap
if (!-e $request_filename) {
rewrite ^(.+)$ /index.php?q=$1 last;
}
}
location ~ \.php$ {
try_files $uri = 404;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
ssl on;
ssl_session_cache shared:SSL:50m;
ssl_certificate /etc/letsencrypt/live/yoursite.io/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yoursite.io/privkey.pem;
ssl_client_certificate /etc/letsencrypt/live/yoursite.io/fullchain.pem;
ssl_session_timeout 5m;
}
server {
# Redirect www to non-www
listen 443;
listen [::]:443;
server_name www.yoursite.io;
return https://yoursite.io$request_uri;
}
server {
# Redirect all calls to HTTP (port 80) to HTTPS
listen 80;
listen [::]:80;
server_name www.yoursite.io yoursite.io;
return https://yoursite.io$request_uri;
}
Restart NGINX:
$ sudo service nginx restart
And you’re all set with a spanking new, 100% free SSL certificate!
—
Gorilla Logic is always on the lookout for exceptional talent, be sure to check out our Careers Section.
Happy Coding!