Lets Encrypt Linux Security Nginx

Redirecting HTTP to HTTPS

Whether you are using self-signed certs, or certs from well-know CA you need a way to integrate it with your services. One of the most typical use case that of an HTTP server, this could be a web server or a REST API server but it needs to be configured to be secure.

Most web servers like nginx and apache listen on port 80 by default and need quite a bit of configuration before they start using the certificates to encrypt the traffic. Despite having it configured, the web server can still service HTTP traffic no problem. So the visitors to your website will just type http://example.com instead of https://example.com and the entire traffic will remain unencrypted for them. To circumvent this issue we need to configure the HTTP servers such that they themselves redirect all the HTTP to HTTPS.

The setup I have is using an FQDN with a public IP, so I will be issuing an SSL certificate from LetsEncrypt rather than issuing a self-signed one. Depending on the kind of web server you are using, you can do this in multiple ways. But the general flow of it is like this:

  1. Get a signed certificate from a CA. In our case this is going to be LetsEncrypt
  2. Configure the web server to use the encryption key to encrypt the outgoing HTTP traffic on port 443. This is the default HTTPS port.
  3. Redirect all the incoming requests on port 80 (which is unencrypted HTTP) to port 443, thereby enabling encrypted sessions for all incoming connections.

Let’s demonstrate various way to achieve what we want. First is the easiest solution which uses Certbot.

1. Easiest way — Using Certbot plugins for Nginx or Apache

I will be using Nginx as an example for this server. If you are running a different one, like Apache or HAProxy, then just visit the Certbot official page and select your OS and your web server of choice. For Nginx on Ubuntu 18.04, these are the commands you would need.

First, update your repo index.

$ sudo apt-get update
$ sudo apt-get install software-properties-common

You would need to add the required third-party repositories, which Ubuntu may not have enabled by default.

$ sudo add-apt-repository universe
$ sudo add-apt-repository ppa:certbot/certbot
$ sudo apt-get update

And then install the certbot package with Nginx plugins, using the command below.

$ sudo apt-get install certbot python-certbot-nginx

The instruction will be different for different platforms and install plugins for the web server if available. The reason plugins make our lives so much easier is because they can automatically edit the configuration files on the web server to redirect the traffic as well. The downside could be that if you are running a very customized server for pre-existing website, then the plugin may break some stuff in there.

For new websites, or very simple configurations, like a reverse proxy, the plugin works surprisingly well. To obtain the certificates and to redirect the traffic, simply run the below command and follow through the various interactive options  as the package walks you through them.

$ sudo certbot --nginx

Output:

certbot --nginx
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx
Enter email address (used for urgent renewal and security notices) (Enter 'c' t
cancel): YOUREMAILHERE@EXAMPLE.COM
 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server at
https://acme-v02.api.letsencrypt.org/directory
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(A)gree/(C)ancel: A
 
....
No names were found in your configuration files. Please enter in your domain
name(s) (comma and/or space separated)  (Enter 'c' to cancel): SUBDOMAIN.DOMAINNAME.TLD
....
 
Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server'
s configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2
Redirecting all traffic on port 80 to ssl in /etc/nginx/sites-enabled/default
 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations! You have successfully enabled https://SUBDOMAIN.DOMAINNAME.TLD
 
You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=SUBDOMAIN.DOMAINNAME.TLD
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

IMPORTANT NOTES:
– Congratulations! Your certificate and chain have been saved at:

/etc/letsencrypt/live/SUBDOMAIN.DOMAINNAME.TLD/fullchain.pem

Your key file has been saved at:

/etc/letsencrypt/live/SUBDOMAIN.DOMAINNAME.TLD/privkey.pem

As shown in the above example you only have to provide a valid email address and your domain name to get the certificate. This certificate is sotred in /etc/letsencrypt/live/SUBDOMAIN.DOMAINNAME.TLD. The last directory will be named after your FQDN.

The most important aspect is selecting the Redirect option and it will do the job of redirecting all the HTTP traffic to HTTPS. If you are curious as to what these changes are, you can inspect the config files in /etc/nginx/ to get the gist of it.

2. Editing the Config files

If you want to manually configure your server to use the certificates. To get the certificates using certbot, run:

$ sudo certbot certonly

As before, the certificates are saved in the directory /etc/letsencrypt/live/yourdomainname.com/

Now we can configure Nginx to use the files in this directory. First things first, I will get rid of the Debian specific directory layout. The default page’s site config file is /etc/nginx/sites-available/default subdirectory with a symlink to /etc/nginx/site-enabled.

I will just delete the symlink and move the config file to /etc/nginx/conf.d with a .conf extension just to keep things more generalized and applicable to other distros as well.

$ sudo rm /etc/sites-enabled/default
$ sudo mv /etc/nginx/sites-available/default /etc/nginx/conf.d/default.conf
$ sudo service nginx restart

I will be modifying this default config file to demonstrate how the TLS is enabled.

The following are the contents inside your default config file, without the commented out sections. The highlighted sections are the one that you ought to add to your server configuration in order to enable TLS and the last block in this config file detects if the scheme is using TLS or not. If TLS is not being used, then it simply returns a 301 redirect code to the client and changes the URL to use https instead. This way, you won’t miss out on users

server {
listen 80 default_server;
listen [::]:80 default_server;
listen 443 ssl;
ssl_certificate  /etc/letsencrypt/live/SUBDOMAIN.DOMAIN.TLS/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/SUBDOMAIN.DOMAIN.TLD/privkey.pem;
ssl_session_cache shared:le_nginx_SSL:1m;
ssl_session_timeout 1440m; ssl_protocols TLSv1 TLSv1.1  TLSv1.2;
ssl_prefer_server_ciphers on;
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"
;

root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
try_files $uri $uri/ =404;
}
if ($scheme != "https") {
return 301 https://$host$request_uri;
}
 
}

There are a few extra parameters added to this config file. Including parameters declaring the timeout, the TLS version you ought to use and what encryption ciphers the server will be using. This was borrowed from Certbot’s recommended (but optional) configurations for Nginx.

Now, check if the configuration file is valid and restart the server.

$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
$ sudo service nginx restart

Conclusion

You can apply the same approach for more complicated web apps and services that need HTTPS. Letsencrypt let’s you issue certificates for multiple domain names at once, and you can host multiple websites behind your nginx web server quite easily. If you followed the above example, try reaching out to your website using http (http://SUBDOMAIN.DOMAIN.TLD) and you will be redirected to HTTPS automatically.

For other web servers, like Apache, use the appropriate certbot plugin or refer their official documentation.

About the author

Ranvir Singh

Ranvir Singh

I am a tech and science writer with quite a diverse range of interests. A strong believer of the Unix philosophy. Few of the things I am passionate about include system administration, computer hardware and physics.