Official Power Up Hosting Blog

Everything about Linux, Windows, and hosting ;)


I am an Online Marketer and technology lover. I like to learn new things and share that with people.


Our Newsletter

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.



Official Power Up Hosting Blog

How To Secure Nginx with Let's Encrypt SSL Certificate Ubuntu 16.04 [SSL Test Score A+]



Securing the traffic between the client and server is very essential.

The internet has been growing very large and it resulted in the creation of IPv6.

There are a lot of confidential information are passed through the network between the client and server.

Especially the online money transaction is the critical issue and it should be secured highly.

It is easy to breach and change the data which is transferred without the encryption.

To protect the data that we transfer through the network, we have to encrypt the traffic.

There are a lot of algorithms being used to encrypt the traffic.

We will implement those algorithms and create an SSL/TLS certificate to use it over the network.

Google has started to give preference to the websites which have the SSL.

It is your responsibility to provide the secure environment to browse for your web visitors."

Today we are going to see How to secure the Nginx web server with Let's Encrypt on Ubuntu 16.04.

You have to follow the Nginx security best practices as mentioned this guide.


We are going to use the Let's Encrypt Free SSL certificate.

== You can generate a self-signed SSL certificate for your web server, but it will not be accepted in many browsers since the authority is an unknown one.==

Here is the solution for that.

secure nginx with lets encrypt

Let's Encrypt:

Let's Encrypt is the free open source SSL certificate authority who can provide you with the trusted SSL certificate.

It is very easy to create an SSL certificate for your site using the Let's Encrypt.

If you are Ubuntu User, then your job is much easier now.

Let us what all the things we will require to install and use the lets Encrypt.


  • You will require the Ubuntu 16.04 Server. Also, you have to create a sudo non-root user to perform the installation and configuration. Here is the guide for Ubuntu Initial Server Setup.

  • You should have the domain to create SSL certificate. Only the server is not enough. Buy a domain or use an existing domain.

  • You should point the domain to the Public IP address of the server. For that, you have to add the name server details in the domain DNS settings in the domain registrar account.

  • Check the A record of the domain and Update the IP address. Your domain name should resolve the IP address; then only you can install the certificate for that domain.

  • Install and configure the Nginx server

Step 1: Install Certbot

Certbot is a software coordinately developed by Many Web software giants.

The basic function of the Certbot is to fetch the SSL certificate from the Let's Encrypt.

The special feature of Certbot with Let's encrypt is Certificate Renewal automation.

Here, you can automate the SSL certificate renewal process before it expires. The certificate generated from Let's encrypt through the Certbot is valid for ninety days.

You can create a Cron job and let the operating system do the renewal job.

Certbot comes in the Ubuntu repository by default.

The Developer behind the Certbot always updates the software up to date.

The Certbot developers have their own Ubuntu Repository where you can get the latest version of Certbot.

So, here we are going to install the Certbot from their own Ubuntu Repository instead of using the default one.

First, we have to add that repository, for that execute the below command.

$ sudo add-apt-repository ppa:certbot/certbot

Press enter to accept the installation. After that, you have to update the repository.

$ sudo apt-get update

Now, you can install the Certbot

$ sudo apt-get install certbot

That's all. You have installed the Let's encrypt client. Now we can use it to obtain the SSL certificate.

Step 2: Generating the SSL certificate

There are a lot of plugins available for the Certbot to obtain the SSL certificate. Most of them won't install the SSL certificate.

They only generate the SSL certificate and you have manually configured them.

We call the Plugins "Authenticators" which only generate the SSL certificate and does not install it on the system.

Their only Job is to authenticate a server whether it can be issued with SSL certificate or not.

Here, we are going to use a Plugin called Webroot to obtain the SSL certificate.

Let us see How to use the Plugin to generate the SSL certificate.

Using Web Root:

The web root plugin will place a special file in the /.well-known directory.

The Let's Encrypt will access the file through the web server for the validation to provide the certificate.

You have to ensure the that the permission for the well-known directory allows the file to be accessed from outside.

To enable the access, we are going to make some changes in our configuration.

The configuration file is located at /etc/nginx/sites-available/default.

Let us Open the file using nano editor

$ sudo nano /etc/nginx/sites-available/default

Add the following location block code in the server block.

            Add to SSL server block
    location ~ /.well-known {
            allow all;

Also, you can also check where the document root is located. You will require the document root to use the web root plugin.

If you are using the default configuration file, then the document root will be /var/www/html.

Save and exit the file.


You have to check the configuration for the syntax errors.

$ sudo nginx -t

If you don't get any error in the output, then restart the Nginx.

$ sudo systemctl restart nginx

Here, we are going to use the web root plugin to fetch the SSL certificate from Let's encrypt.

Use the following command and replace the domain name used in the command with your domain name.

If you want the Certbot to request SSL certificates for more than one domain, add them in the command.

$ sudo certbot certonly --webroot --webroot-path=/var/www/html -d -d

When you generate the certificate for the firs time, the prompt will ask you to enter email id and agree with their terms and service.

After that, you will receive the following output.

- Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/live/ Your cert
will expire on 2017-07-26. To obtain a new or tweaked version of
this certificate in the future, simply run certbot again. To
non-interactively renew *all* of your certificates, run "certbot
- If you lose your account credentials, you can recover through e-mails
sent to
- Your account credentials have been saved in your Certbot
configuration directory at /et.c/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:
Donating to EFF:          

Just note down the path and expiration date of your certificate.

If you get any error like Failed to connect to host for DVSNI challenge while trying to generate certificate, you have to enable the ports port 80 and port 443 to allow the TCP traffic.

If you are using Cloudflare for DNS, and you have to disable it until we finish the configuration process.

After the command execution, the Let's Encrypt will create and store certificates on your server. You have to identify the path where the certificates are stored.

Certificates by Let's Encrypt

Those certificates are PEM encoded files. Here are the files generated by Let's Encrypt.

  • cert.pem: The domain certificate
  • chain.pem: The Chain Certificate generated by Let's Encrypt.
  • fullchain.pem: Combination of cert.pem and chain.pem
  • privkey.pem: Private Key for the certificate.

You should know where these files are located to use them in the web server configuration.

These certificates are located in the etc/letsencrypt/archive.

The link to the recently created certificates will be located at in the /etc/letsencrypt/live/domain_name.

You have to use this path in the web server configuration as they are pointing to the most recent certificates.

To ensure that file has the links to the recent file, execute the below command.

$ sudo ls -l /etc/letsencrypt/live/domain_name

The output should contain the files that we have mentioned above.

Also, you have to set the web server to fullchain.pem and privekey.pem.

Here the fullchain.pem is the certificate file and the privekey.pem is certificate key file.

Creating the Diffie-Hellman Group

You have to create the Strong Diffie-Hellman Group to exchange the cryptographic key securely over the network.

Execute the below command to generate Diffie-Hellman Group

$ sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

After the process gets completed, you will get the strong Diffie-Hellman group in the certificate directory at the /etc/ssl/certs/dhparam.pem location.

Step 3: Configuring the SSL/TLS certificate on Nginx.

Once you are done with the above steps, you have to set up the Nginx web server to use SSL to create the secured connection between the client and server.

For that, we are going to create two snippets and add few commands in the Nginx server block to use those snippets.

  • The first snippet will contain the SSL key and Certificate file locations.
  • The another certificate will contain the strong SSL settings that can be used in the near future.
  • Make some changes in the Nginx server block to use the above snippets.

The above configuration settings will reduce the code and keep the server block simple.

Also, the reusability of code keeps the server block clean.

Create Configuration Snippet 1

Here, we are going to create a configuration file which will be pointing to the SSL key and certificate file location.

We will add the ssl- infront of the actual file name to identify its purpose. The extension of the configuration file will be .conf.

You have to create this configuration file at /etc/nginx/snippets.

$ sudo nano /etc/nginx/snippets/

In that configuration file, we are going to use two directives. One is certificate directive and another is SSL key directive.

Here you will add the location of both files the corresponding directives.

Add the code in the configuration file.


Now, save and close the file.

Creating Snippet 2:

We are going to create a strong configuration snippet with Encryption settings.

This setting implement the strong Nginx ssl_ciphers and provides some advanced function to secure the web server.

You can set any name to the snippet. Execute the below command to create the second snippet.

$ sudo nano /etc/nginx/snippets/ssl-params.conf

Next, we are going to set the Nginx configuration to secure it more.
Here, we are going to use a Nginx configuration recommendation from an expert called Remy Van Elst.

We are going to follow the exact settings as he mentioned. In that configuration settings, we will disable the HSTS (https strict transport policy)

It will create an impact if you enable it incorrectly. So, it is better to disable it.

Or, if you want to enable it, just do it at your own risk.

Before going to make changes in the configuration, you also you have to make the changes in * Nginx ssl_dhparam* to make it point to the Diffie-Hellman file that has been generated in the previous step.

Here is the exact code that you can use it on your Nginx configuration server.

# from
# and

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver valid=300s;
resolver_timeout 5s;
# disable HSTS header for now
#add_header Strict-Transport-Security "max-    age=63072000; includeSubDomains; preload";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

ssl_dhparam /etc/ssl/certs/dhparam.pem;

Once you are done with the configuration, just save and close the file.

Make the Nginx Configuration use SSL

Here, we are going to make some changes in the Nginx Server configuration file located at /etc/nginx/sites-available.

The file name is a default one. It refers to the default server block.

Before going to make any changes in the server configuration, make sure that you have a backup for it.

To take the backup, just follow the command.

$ sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default.bak

After that, Open the server block file using Nano editor

$ sudo nano /etc/nginx/sites-available/default

Find the block which has the following directives.

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

# SSL configuration

# listen 443 ssl default_server;
# listen [::]:443 ssl default_server;

. . .

In the above settings, all the HTTP traffic will be automatically redirected to the HTTPS.

This increases the security of the web server.

If you want to allow both HTTP and https server, you can follow the settings as mentioned below.

In that server block, you will set your server a domain name. You can find the server directive after the two 'listen' directives.

After the 'server' directive, you have to set the redirect to the second server block which you are going to create next.

server {
listen 80 default_server;
listen [::]:80 default_server;
return 301 https://$server_name$request_uri;

# SSL configuration

# listen 443 ssl default_server;
# listen [::]:443 ssl default_server;

. . .

You have to start this block next to the above-mentioned block. Here in this block, you have to uncomment the two listen to directives and add the http2 to those lines to enable the HTTP/2.

Both of the Listen directives are listening to the port 443. So, we are disabling them.

After that, you have to add those two snippets which we have created in the previous steps.

server {
listen 80 default_server;
listen [::]:80 default_server;
return 301 https://$server_name$request_uri;

server {

# SSL configuration

listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
include snippets/;
include snippets/ssl-params.conf;

. . .

If there is no server name on the block, you have to add that as mentioned below.

server {
# SSL configuration
. . .
. . .

Now, save the file and close it.

HTTP and HTTPS traffic (Allowing both configurations)

In case, if you need to allow both encrypted and unencrypted traffic to your server, you can do this by making few changes in the server configuration.

You can do this by making two of the server blocks to one and remove the redirection.

It is always recommended to allow only the encrypted traffic.

Here are the directives for the server block.

server {
listen 80 default_server;
listen [::]:80 default_server;
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;

include snippets/;
include snippets/ssl-params.conf;

. . .

Once you entered all these lines in the server block, just save and close the file.

Step 4: Making changes in the firewall.

To allow the Encrypted traffic, you have to make some changes in the Nginx firewall rules.

If you have configured the ufw firewall as mentioned in the guide, you would have the default profile.

To look at the current settings, execute the below command.

$ sudo ufw status

The configuration will look like the following.

Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
Nginx HTTP                 ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
Nginx HTTP (v6)            ALLOW       Anywhere (v6)

Take a closer look at the settings. It only allows the HTTP traffic.

To allow HTTPS traffic, you have to delete the Nginx HTTP settings and enable the Nginx Full profile.

$ sudo ufw allow 'Nginx Full'
$ sudo ufw delete allow 'Nginx HTTP'

Again look at the status after that and it will look like the below one.

$ sudo ufw status

Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
Nginx Full                 ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
Nginx Full (v6)            ALLOW       Anywhere (v6)

Step 5: Restarting the Nginx

Now, it is the time to restart the Nginx. We have made changes in the ufw and inorder to make it work; you have to restart the Nginx.

Before restarting the Nginx, you have to check the syntax of the server blocks.

Execute the below command.

$ sudo Nginx -t

You should get the following result if the syntax is correct.

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

If you get the above output, then it means that you have not made any syntax errors.

Now restart the Nginx to make changes to work.

$ sudo systemctl restart nginx

Now, you got the TLS/SSL certificate in place and the ufw allow traffic to port 80 and 443.

You have to test the website from a browser whether it works with HTTPS.

You can also check the security score of your SSL using the quality labs.

Go to the following URL in a web browser.


Now, you can see the A+ ratings for your SSL.

Step 6: Auto Renewal

The certificates from Let's encrypt are only valid for ninety days. After that, you have to renew them.

But, in the busy schedules, no one will want to remind and do the job.

There is one solution available for that. That is automation. You can automate the renewal process using Cron jobs.

The Cron job will check for the expiring certificates and renews them.

You have to create the job by editing the crontab. Execute the below command.

$ sudo crontab -e

The nano editor will open the crontab file. Add the below lines in that file.

. . .
12 1 * * * /usr/bin/certbot renew --quiet --renew-hook 
"/bin/systemctl reload nginx"

Here, the Cron job will check the certificate at 12:10 am every day.

The Cron job will renew the certificates which are going to expire in 30 days.

Here the --quiet command instructs Cron job to not to output anything or not to get for input from the user.

That's all. Now you are done with Cron job creation.

The Cron job will run daily and it will renew the certificates when they about expire within 30 days.



You have learnt how to improve your server security by making changes in the Nginx server.

A lot of people are lacking in securing their web server. It leads to the attack and data breach in their server.

It will end up in losing money. But if you improve the security of the server, you can avoid the situation.


Go and implement this on your Nginx and get the A+ grade for your SSL. This Nginx security hardening process will provide the best security for your server.

If you have any doubt regarding this, just let us know that in the comment. We will help you to resolve the issue.

Now you have become a little security expert and you can protect your server from the threats.



I am an Online Marketer and technology lover. I like to learn new things and share that with people.