The default installation of the Nginx Web Server simply uses the port 80 over the HTTP protocol to communicate with the clients. We can install SSL certificates and configure the Nginx server to encrypt the traffic between the server and client and the secure communication will be done using the port 443 over HTTPS protocol. An additional security layer with encrypted communication makes it hard for anyone to misuse the data transferred between the client and the server.
Let’s Encrypt is a free, automated, and open certificate authority (CA), run for the public’s benefit. It is a service provided by the Internet Security Research Group (ISRG).
In this tutorial, we will discuss the steps required to obtain and install the free and trusted SSL certificates provided by Let’s Encrypt. We can secure the Nginx Web Server by configuring the virtual host to redirect all the communication over HTTP to HTTPS. You may keep a part of your application to use HTTP and secure the important URLs by redirecting the HTTP requests to HTTPS based on your website or application requirements.
Prerequisites
You must have the below-listed software installed on your system to continue with this tutorial.
Ubuntu Server - This tutorial is written for Ubuntu 18.04 LTS, though it can be any other Linux system. The steps should be the same on other systems. You can also follow Complete Guide To Install Ubuntu 18.04 LTS (Bionic Beaver) to install the desktop version of Ubuntu.
Nginx Web Server - It assumes that the Nginx is already installed on the system and it's configured properly to access it using the IP address. It can be easily done on your local system in case you have a static IP address. You must be able to view the Welcome Screen by simply navigating to http://xx.xx.xx.xx (xx.xx.xx.xx is your IP address pointing to your server) in case the default virtual host is available. You can also follow How To Install And Configure Nginx on Ubuntu 18.04 LTS to install the Nginx Web Server.
Domain - A valid domain properly configured at your domain registrar pointing to your server. I have used example.com in this tutorial for reference. Make sure to replace it with your own domain.
Firewall - Ports 80 and 443 are open to
Install Certbot - Default
In this section, we will install Certbot using the Ubuntu repositories. The client software Certbot communicates with the certificate authority to fetch the certificates on the system.
You may additionally upgrade your system to the most recent version. Make sure that your system is not breaking due to a dist upgrade.
$ Upgrade System sudo apt-get update sudo apt-get dist-upgrade sudo apt-get autoclean
# Make sure to use purge sudo apt-get autoremove # OR sudo apt-get --purge autoremove
Install the official client Certbot for Nginx using the commands as shown below.
# Install Let's Encrypt sudo apt-get install python-certbot-nginx
# Installation results
...
...
Setting up certbot (0.23.0-1) ...
Setting up python3-certbot-nginx (0.23.0-1) ... Setting up python-certbot-nginx (0.23.0-1) ... Processing triggers for mime-support (3.60ubuntu1) ... Processing triggers for man-db (2.8.3-2ubuntu0.1) ...
We can confirm the installation by checking the Certbot version as shown below.
# Check Certbot version certbot --version
# Output certbot 0.23.0
Since Certbot is actively developed, it gets outdated soon. We can install it from the official repository as explained in the next section.
Install Certbot - Latest
In this section, we will install the most recent version of Certbot using the official repository. You may uninstall the previous installation of Certbot using the commands as shown below.
# Uninstall Certbot sudo apt remove python-certbot-nginx sudo apt remove certbot sudo apt purge certbot sudo apt-get autoclean
# Make sure to use purge sudo apt-get autoremove # OR sudo apt-get --purge autoremove
Now we will add the official repository to the system repositories. It can be done using the commands as shown below.
# Add Certbot repository sudo add-apt-repository ppa:certbot/certbot
# Press Enter to confirm This is the PPA for packages prepared by Debian Let's Encrypt Team and backported for Ubuntu(s). More info: https://launchpad.net/~certbot/+archive/ubuntu/certbot Press [ENTER] to continue or Ctrl-c to cancel adding it. ... ...
Now refresh the packages index using the command as shown below.
# Refresh packages index sudo apt-get update
We can install the Certbot using the same command as we did in the previous section.
# Install Let's Encrypt sudo apt-get install python-certbot-nginx
# Installation results ... ... Setting up python3-certbot (0.31.0-1+ubuntu18.04.1+certbot+1) ... Setting up certbot (0.31.0-1+ubuntu18.04.1+certbot+1) ... Created symlink /etc/systemd/system/timers.target.wants/certbot.timer → /lib/systemd/system/certbot.timer. certbot.service is a disabled or a static unit, not starting it. Setting up python3-certbot-nginx (0.31.0-1+ubuntu18.04.1+certbot+1) ... Setting up python-certbot-nginx (0.31.0-1+ubuntu18.04.1+certbot+1) ... Processing triggers for man-db (2.8.3-2ubuntu0.1) ...
We can confirm the installation by checking the Certbot version as shown below.
# Check Certbot version certbot --version
# Output certbot 0.31.0
This is how we can clean the existing installation of Certbot and install the most recent version of it on the system.
Add Virtual Host (Server Block)
In this section, we will add the virtual host and enable it to access the application using the domain. You may skip this step in case you already have an active website or application accessible from the browser using the domain name.
Add and update the Virtual Host to Nginx Web Server as shown below. I have used the nano editor for demonstration purposes. You can use any editor of your choice. Also, replace example.com with the actual domain. Create the directory /var/www/example.com/html to store the website or application files.
# Create the directories if does not exist sudo mkdir /etc/nginx/sites-available sudo mkdir /etc/nginx/sites-enabled
# Copy the default config sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/example.com # OR sudo cp /etc/nginx/conf.d/default.conf /etc/nginx/sites-available/example.com
Now update the configuration to configure your domain and the system path having site files. The configuration should look like the one as shown below.
# Update configuration /etc/nginx/sites-available/example.com
# Content server { listen 80; server_name example.com www.example.com;
#charset koi8-r; #access_log /var/log/nginx/host.access.log main;
location / { root /var/www/example.com/html; index index.html index.htm; }
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html; }
# proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ \.php$ { # root html; # fastcgi_pass 127.0.0.1:9000; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include fastcgi_params; #}
# deny access to .htaccess files, if Apache's document root # concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#} }
# Save and exit the editor
# Create the site directory and update permissions sudo mkdir /var/www/example.com/html sudo chmod -R 755 /var/www/example.com
Use the below-mentioned commands to enable or disable the site configuration.
# Enable Site - Create the symlink sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
# Disable Site
sudo rm /etc/nginx/sites-enabled/example.com
# OR sudo unlink /etc/nginx/sites-enabled/example.com
Apply the configuration using the below-mentioned commands.
# Check configurations sudo nginx -t
# Reload configuration sudo nginx -s reload # OR sudo systemctl reload nginx
Now add the index.html file having content as shown below.
# Add index.html sudo nano /var/www/example.com/html/index.html
# Content <!DOCTYPE html> <html lang="en"> <head> <title>My Domain</title> </head> <body> <h1>Welcome to My Domain.</h1> </body> </html>
# Save and exit the editor
If your domain is correctly pointing to your system, you must be able to access it from the browser by navigating to http://www.example.com. It should show the output of our simple HTML file - Welcome to My Domain.
Install SSL Certificate
We will install the SSL certificate in this step. It can be done using the command as shown below.
# Install Certificate - Syntax - Single Domain sudo letsencrypt --nginx -d <domain 1> --email <email address>
# Install Certificate - Syntax - Multiple Domains sudo letsencrypt --nginx -d <domain 1>,<domain 2>,<domain 3> --email <email address>
# Example sudo letsencrypt --nginx -d example.com,www.example.com --email admin@example.com
# Agree - Press A and Enter - First time only
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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
# Share Email for communication - Press Y and Enter
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about our work
encrypting the web, EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y
# Choose redirect options - redirect
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
# Certificate installed successfully
Congratulations! You have successfully enabled https://example.com
You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=example.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/example.com/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/example.com/privkey.pem
Your cert will expire on 2020-01-04. To obtain a new or tweaked
version of this certificate in the future, simply run certbot again
with the "certonly" option. To non-interactively renew *all* of
your certificates, run "certbot renew"
- Your account credentials have been saved in your Certbot
configuration directory at /etc/letsencrypt. You should make a
secure backup of this folder now. This configuration directory will
also contain certificates and private keys obtained by Certbot so
making regular backups of this folder is ideal.
- If you like Certbot, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le
Now if you try to open the URL - http://www.example.com, it must redirect you to https://www.example.com. Make sure that your firewall allows communication on port 443.
This is how we can secure an entire website or application using the SSL certificate for secure communication over the Nginx web server and the clients(Browser etc).
Analysis
Now if you again open the virtual host file, you must see that Certbot has removed the listen directive for port 80 and added the SSL certificate lines at the bottom of the Server Block.
# Check Virtual Host sudo nano /etc/nginx/sites-available/example.com
server {listen 80;server_name example.com www.example.com; .... .... # deny all; #} listen 443 ssl; # managed by Certbot ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot }
The Certbot client also updates the virtual host and redirect all the HTTP requests to HTTPS as part of the SSL installation process. You can check it's content as shown below.
# Check SSL Virtual Host sudo nano /etc/nginx/sites-available/example.com
# Scroll to bottom ... ... server { if ($host = example.com) { return 301 https://$host$request_uri; } # managed by Certbot listen 80; server_name example.com; return 404; # managed by Certbot }
Auto-Renewal
The SSL certificates issued by Let's Encrypt expires after 90 days from the date of installation. The good point is that the Certbot installed by us from the official repository checks for renewal twice a day using the system timer. The auto-renewal feature on
You can also test the renewal process by simulating the renewal command as shown below.
# Simulate renewal command sudo certbot renew --dry-run
The above command will show the logs having messages to get an idea about how it will be run for actual renewal. We can also run the command manually to renew the certificates that are about to expire in the next 30 days.
# Renew certificates sudo certbot renew
# Renewal messages
Saving debug log to /var/log/letsencrypt/letsencrypt.log
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/example.com.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cert not yet due for renewal
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
The following certs are not due for renewal yet:
/etc/letsencrypt/live/example.com/fullchain.pem expires on 2020-01-01 (skipped)
No renewals were attempted.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
The Nginx service must be reloaded after certificate renewal. We can do it by appending --renew-hook "
# Append renew hook 0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(43200))' && certbot -q renew --renew-hook "systemctl reload nginx"
Now again do a dry run by simulating the renewal command as shown below.
# Simulate renewal command sudo certbot renew --dry-run
It should run successfully to ensure that the certificates will be automatically renewed before the expiry.
Summary
In this tutorial, we have discussed the steps required to install Certbot from the Ubuntu repositories and the official repository. We have installed the Certbot client to communicate with the certificate authority. In the next section, I have explained how to add a Virtual Host and make a website live using a real domain pointing correctly to the server. In the last section, we have successfully installed the free SSL certificate from Let's Encrypt and redirected all the traffic from HTTP to HTTPS for secure communication between the client and the server.