How to use HTTPS for my personal website. Nginx server and Ubuntun 16.04.
My environment
- Web server: Nginx
- Operating System: Ubuntu 16.04
The steps are mainly following this Digital Ocean Tutorial:
How To Secure Nginx with Let’s Encrypt on Ubuntu 16.04, but with some modifications for subdomain settings.
Step 1: Install Let’s Encrypt Client
Run the following command on your Ubuntu server:
1 | sudo apt-get update |
Step 2: Obtain an SSL Certificate
Change the Nginx conf files to enable access to /.well-known
folder:
1 | sudo nano /etc/nginx/sites-available/peiyingchi.com |
Add the following line inside the server
block:
1 | location ~ /.well-known { |
If you want to add the SSL cert to multiple domains or other subdomains, please do the same for all the nginx conf files.
After changing the nginx conf files for the domains you want to setup HTTPS in, run the following:
1 | sudo letsencrypt certonly -a webroot --webroot-path=/var/www/peiyingchi.com/html -d peiyingchi.com -d www.peiyingchi.com |
To setup for subdomains together:
1 | sudo letsencrypt certonly --webroot -w /var/www/peiyingchi.com/html/ -d www.peiyingchi.com -d peiyingchi.com -w /var/www/blog.peiyingchi.com/html -d blog.peiyingchi.com |
You will be prompted to enter your contact email and agree some terms and conditions.
My cert files are at :
1 | $ yingchi@yingchi-site:~$ sudo ls -l /etc/letsencrypt/live/peiyingchi.com |
After obtaining the cert, you will have the following PEM-encoded files:
cert.pem
: Your domain’s certificatechain.pem
: The Let’s Encrypt chain certificatefullchain.pem
:cert.pem
andchain.pem
combinedprivkey.pem
: Your certificate’s private key
To further increase security, you should also generate a strong Diffie-Hellman group. To generate a 2048-bit group, use this command:
1 | sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048 |
Step 3: Configure TLS/SSL on Web Server (Nginx)
Now that you have an SSL certificate, you need to configure your Nginx web server to use it.
We will make a few adjustments to our configuration:
- We will create a configuration snippet containing our SSL key and certificate file locations.
- We will create a configuration snippet containing strong SSL settings that can be used with any certificates in the future.
- We will adjust the Nginx server blocks to handle SSL requests and use the two snippets above.
First, let’s create a new Nginx configuration snippet in the /etc/nginx/snippets
directory.
To properly distinguish the purpose of this file, we will name it ssl-
followed by our domain name, followed by .conf
on the end:
1 | sudo nano /etc/nginx/snippets/ssl-peiyingchi.com.conf |
1 | ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; |
Next, we will create another snippet that will define some SSL settings. This will set Nginx up with a strong SSL cipher suite and enable some advanced features that will help keep our server secure.
The parameters we will set can be reused in future Nginx configurations, so we will give the file a generic name:
1 | sudo nano /etc/nginx/snippets/ssl-params.conf |
1 | # from https://cipherli.st/ |
If you are interested, you can take take a moment to read up on HTTP Strict Transport Security, or HSTS, and specifically about the “preload” functionality. Preloading HSTS provides increased security, but can have far reaching consequences if accidentally enabled or enabled incorrectly. In this guide, we will not preload the settings, but you can modify that if you are sure you understand the implications
Now that we have our snippets, we can adjust our Nginx configuration to enable SSL.
Before we go any further, let’s back up our current server block file:
1 | sudo cp /etc/nginx/sites-available/peiyingchi.com /etc/nginx/sites-available/peiyingchi.com.bak |
Now, open the server block file to make adjustments.
Blow are the 2 conf files for my top-level domain and my subdomain:
1 | sudo nano /etc/nginx/sites-available/peiyingchi.com |
1 | server { |
1 | server { |
Step 4: Adjust the Firewall
If you have the ufw
firewall enabled, as recommended by the prerequisite guides, you’ll need to adjust the settings to allow for SSL traffic.
You can see the current setting by typing:
1 | sudo ufw status |
To additionally let in HTTPS traffic, we can allow the “Nginx Full” profile and then delete the redundant “Nginx HTTP” profile allowance:
1 | sudo ufw allow 'Nginx Full' |
Step 5: Enabling the Changes in Nginx
First, we should check to make sure that there are no syntax errors in our files. We can do this by typing:
1 | sudo nginx -t |
If your output matches the above, your configuration file has no syntax errors. We can safely restart Nginx to implement our changes:
1 | sudo systemctl restart nginx |
You can use the Qualys SSL Labs Report to see how your server configuration scores:
Enter the following to your web browser:
https://www.ssllabs.com/ssltest/analyze.html?d=example.com
Step 6: Set Up Auto Renewal
From Let’s Encrypt’s official documentation, you can run the following to test the renew function:
1 | sudo letsencrypt renew --dry-run --agree-tos |
Do not worry for the ‘Registering without email!’ warning. It does not hurt anything.
If that appears to be working correctly, you can arrange for automatic renewal by adding a cron or systemd job which runs letsencrypt renew
Since the renewal first checks for the expiration date and only executes the renewal if the certificate is less than 30 days away from expiration, it is safe to create a cron job that runs every week or even every day, for instance.
Let’s edit the crontab to create a new job that will run the renewal command every week. To edit the crontab for the root user, run:
1 | sudo crontab -e |
Add the following lines:
1 | 30 2 * * 1 /usr/bin/letsencrypt renew >> /var/log/le-renew.log |
This will create a new cron job that will execute the letsencrypt-auto renew command every Monday at 2:30 am, and reload Nginx at 2:35am (so the renewed certificate will be used). The output produced by the command will be piped to a log file located at /var/log/le-renewal.log
.