Secure Your Website: Simple HTTPS with Nginx


Is your website using HTTPS? If a website is not using HTTPS, then Google Chrome will mark the website as “Not Secure”.

With free options such as Let’s Encrypt – there is no reason for a website or any website to be running on plain HTTP.

Even if your organization is running a backend web service that doesn’t support HTTPS, there are still options to use HTTPS, such as using Let’s Encrypt and Nginx. Transport Layer Security (TLS) is very important (even if you are behind a firewall and have IP whitelisting) to protect your website from malicious code injections.

How to Set Up a Nginx Proxy with TLS

Let’s start by reviewing how to set up a Nginx proxy with TLS and proxy an endpoint that only supports plain HTTP.

In this example, we are using Amazon EC2 for the hosting of both the Nginx proxy and the HTTP service. In addition, we are using Ubuntu as the OS. First, we set up a EC2 instance and logged in using SSH. Our example web service runs on port 8080 and when the web service is accessed, the service will return {“success”,true}.

Installing Nginx and Certbot

  • Step 1:

    Run “sudo apt update” to ensure the latest packages are known.

  • Step 2:

    Install Nginx. This step is very straight forward and starts with the command: “sudo apt install nginx”

  • Step 3:

    Once the installation is complete and the default configuration is set up, the next step is to install Certbot. Certbot is the piece of software that will automatically install and manage Let’s Encrypt certificates. In this case, we will want to install it with the Nginx plugin.

  • Step 4:

    To install Certbot, we need to add the repository using: “sudo add-apt-repository ppa:certbot/certbot” (Note: the repository location is valid as of October 2019)

  • Step 5:

    Run “sudo apt update” again and then: “sudo apt install python-certbot-nginx”

Installing the Certificate

Now we need to set up the initial certificate for the site. In this example we have the domain “example.domain”, which should already be configured in DNS to reference the public IP of the our EC2 instance.

This can be done by running: “sudo certbot –nginx -d example.domain”

Then there will be a prompt to fill out some information. Lastly, there will prompt to redirect from http to https. Be sure to select option 2 or yes.

After this is done, reboot Nginx. Use “sudo service nginx restart” or “sudo service nginx reload”.

(Note: The restart command actually restarts nginx and reload just reloads the config.)

This installation of the certificate requires validation which requires writing files to prove ownership of the domain. This will not work in the future when we run a redirect from “/” to the backend proxy, so we will need to provide a fix. This will be mentioned as we configure the redirects on Nginx.

Configuring the Redirect from Nginx

Our backend service is running on localhost on port 8080 via HTTP 1.1.

To set up the redirect, use your text editor of choice and open with sudo, example:

“sudo vi /etc/nginx/default”

In the editor look for the blob of text that contains:

location / {
try_files $uri $uri/ =404;

Comment out the line that contains “try_files $uri $uri/ =404; using “#”

Now add in the following lines in the same location you commented out the try_files:

proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $http_host;
proxy_cache_bypass $http_upgrade;

It should look something like this:

location / {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $http_host;
proxy_cache_bypass $http_upgrade;

Under the “location /” block, we need to add one more block as well:

location /.well-known {
alias /var/www/html/.well-known;

This one is to allow certbot to renew the certificate in the future.

Once these are added, reboot Nginx using either “sudo service nginx restart” or “sudo service nginx reload”.

Certificate Renewal

Now it’s time to test a certificate renewal, but we will be doing a dry run, so we don’t run against any rate limits, and make sure everything works.

To renew, type “sudo certbot –dry-run renew”. If this succeeds, then we can go ahead and add this command to a cron job to automatically renew it as needed.

To open cron, type:

“sudo crontab -e”
then type in:
“2 3 13 1-12 * certbot renew”

This will run at 3:02 on the 13th of every month. Make sure to vary the time a bit from this example, and don’t use minute “0” as to not overload Let’s Encrypt servers, as requested by them.

Running websites with HTTPS in this era is important, because it ensures that no one is injecting malicious content (malware or advertisements from an ISP) in your website. Running websites with HTTPs also ensures that any content including passwords are not being sent over the web in clear text. (Read more about a common phishing tactic used to steal user credentials here).