All Articles

Add Https to website using Let's Encrypt to Nginx configured as a reverse proxy on Ubuntu

To enable HTTPS on your website, you need to get a certificate (a type of file) from a Certificate Authority (CA). Let’s Encrypt is a CA. In order to get a certificate for your website’s domain from Let’s Encrypt, you have to demonstrate control over the domain. With Let’s Encrypt, you do this using software that uses the ACME protocol, which typically runs on your web host.

Let’s Encrypt uses the ACME protocol to verify that you control a given domain name and to issue you a certificate. To get a Let’s Encrypt certificate, you’ll need to choose a piece of ACME client software to use.

We use Certbot as ACME client. It can simply get a cert for you or also help you install, depending on what you prefer. It’s easy to use, works on many operating systems and has great documentation.

The first thing to before adding SSL in your website using Let’s Encrypt make sure that you have an ubuntu server running and have ssh access to it. Also, make sure that you have a domain that’s pointed to the server.

 Install Lets Encrypt

To install Let’s Encrypt on ubuntu first add the repository.

For Ubuntu 16.04

sudo apt-get install software-properties-common python-software-properties
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update

For Ubuntu 18.04

sudo apt-get install software-properties-common
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update

Then install LetsEncrypt which contains that contains cerbot and other libraries needed.

sudo apt-get install letsencryp

Verify ACME challenge using Nginx

To verify that we have control over a domain first we need to pass the ACME challenge. For that we will configure Nginx to catch all request to /\.well-known/acme-challenge/ and host it in /var/www/letsencrypt .

Change you’re vhost so it looks like this. You can use default one located in /etc/nginx/sites-available/default

server {
        listen 80 default_server;
        listen [::]:80 default_server;

        location ~ /\.well-known/acme-challenge/ {
                allow all;
                root /var/www/letsencrypt;
                try_files $uri =404;
                break;
        }

Let’s create folder /var/www/letsencrypt to host the challenge.

mkdir /var/www/letsencrypt

Let’s check out Nginx setting are valid by running

sudo nginx -t

If you get message like this you’re ready to go.

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Now let’s reboot our nginx sever to apply the changes

sudo service nginx reload

Generating Let’s Encrypt SSL

After setting up Let’s Encrypt now we will generate the SSL certificates. I’ll use ssl.example.com as an example domain name, use your own domain.

Now use this command to generate the SSL replace the following fields with your own fields.

  • mail@example.com with your own email address

  • ssl.example.com with your own domain

sudo letsencrypt certonly -a webroot --webroot-path=/var/www/letsencrypt -m mail@example.com --agree-tos -d ssl.example.com

You should see the congratulations message after this step.

Adding SSL to Nginx

Now let’s configure our virtual host file with new SSL certificates. I’ll use default config at /etc/nginx/sites-available/default but you can use your own, just replace ssl.example.com with your own domain name.

server {
    server_name ssl.example.com;
    listen 443 ssl;
    ssl on;
    ssl_certificate     /etc/letsencrypt/live/ssl.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/ssl.example.com/privkey.pem;

    location ~ /.well-known {
            root /var/www/letsencrypt;
            allow all;
    }

}

Reverse proxy on Nginx

If you’ve got your web server running on localhost on your sever you can use Nginx to proxy all the request to the web server. For example I have a node server running at localhost:8000 and you can use this config to pass all request to local web server. Just replace the port inside location / with your server’s port number.

server {
    server_name ssl.example.com;
    listen 443 ssl;
    ssl on;
    ssl_certificate     /etc/letsencrypt/live/ssl.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/ssl.example.com/privkey.pem;

    location ~ /.well-known {
            root /var/www/letsencrypt;
            allow all;
    }

    location / {
            proxy_pass http://127.0.0.1:8000;
            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;
    }

Force all requests to https

If you want all the HTTP request to be forced into HTTPS request you can add this block in your Nginx config file.

server {
  listen 80 default_server;
  listen [::]:80 default_server;
  server_name ssl.example.com;
  return 301 https://$host$request_uri;
}

Automate renewal of SSL certificates

The SSL certificates issued by Let’s encrypt is only for 90 days. You can use following commands to automate the renewal of the certificates.

Create a script to run every day that checks and renews the certificate if they expire.

sudo touch /etc/cron.daily/letsencrypt

And set it’s permission.

sudo chmod +x /etc/cron.daily/letsencrypt

Now add the following content to the /etc/cron.daily/letsencrypt file.

 Ubuntu 16.04 

#!/bin/bash
/usr/bin/letsencrypt renew && /etc/init.d/nginx reload

Ubuntu 18.04 

#!/bin/bash
/usr/bin/letsencrypt renew --renew-hook "/etc/init.d/nginx reload"

Conclusion

Adding SSL certificates makes your website more secure and make the site look more secure to search engines and even the user. Let’s Encrypt enables us to freely do it. So I think to do it essential of any web applications or websites.

Published 26 Oct 2018

Learning to love JS
Dipesh Wagle on Twitter