How to Setup Let’s Encrypt with Nginx on Ubuntu Linux

This article guides readers on setting up free Let’s Encrypt SSL certificates on an Ubuntu server using Nginx. It explains the installation of the Certbot tool, certificate generation, and automatic renewal processes. Implementing this allows secure HTTPS connections, enhancing website security and user trust while improving SEO rankings. Regular backups are recommended.

This article explains how to set up Let’s Encrypt free SSL certificates on Ubuntu Linux with an Nginx HTTP web server. Let’s Encrypt is a free, automated, open certificate authority created by the nonprofit Internet Security Research Group (ISRG).

Instead of purchasing an SSL certificate for your website and other applications, one can use Let’s Encrypt free SSL certificates to secure their web portals and applications. Let’s Encrypt SSL certificates, which are valid for 90 days. However, you can create an automated process to automatically renew before expiring.

If you’re operating a website or need to secure your application with HTTPS, then Let’s Encrypt certificates are great. You can save yourself pretty pennies using it.

For this post, we will use the Let’s Encrypt free SSL certificate to secure a website powered by an Nginx webserver. Your Nginx website will be able to communicate over HTTPS.

Follow the steps below to start with Let’s Encrypt on Ubuntu Linux to secure Nginx.

How to install Certbot on Ubuntu Linux

Certbot is a command line tool that automates acquiring and renewing Let’s Encrypt SSL certificates. There are other tools to perform the same tasks, but Certbot is efficient and easy to use.

To install Certbot on Ubuntu, run the commands below.

sudo apt update
sudo apt install certbot

How to generate Let’s Encrypt certificates for Ubuntu Linux

Now that Certbot is installed, you can generate Let’s Encrypt SSL certificates on Ubuntu Linux.

We will use the Webroot plugin to automate the certificate generation and renewal. This plugin uses the/.well-known/acme-challenge directory at the web server root to validate that the requested domain resolves to the Certbot server.

We will create a challenge/response configuration file to allow Let’s Encrypt to validate the server for which the certificates were generated.

To do that, run the commands below to create a configuration file called well-known.conf in the /etc/nginx/snippets directory. This directory contains all configurations you want to use with the Nginx web server. Include the challenge/response configuration file in all server blocks.

sudo nano /etc/nginx/snippets/well-known.conf

Then copy and paste the content below into the file and save it.

location ^~ /.well-known/acme-challenge/ {
  allow all;
  root /var/www/html/;
  default_type "text/plain";
  try_files $uri =404;
}

The configuration file above allows Let’s Encrypt to validate the web server using the Webroot plugin.

Before SSL and HTTPS, a typical Nginx server block file should look like the one below. Make sure to include the well-known snippet created above.

server {
    listen 80;
    listen [::]:80;
    root /var/www/example.com;
    index  index.php index.html index.htm;
    server_name  example.com www.example.com;

    include snippets/well-known.conf;

    client_max_body_size 100M;
    autoindex off;
    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
         include snippets/fastcgi-php.conf;
         fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
         fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
         include fastcgi_params;
    }
}

How to generate Dh (Diffie-Hellman) Group

Diffie–Hellman key exchange (DH) is a method of securely exchanging cryptographic keys. You’ll want to generate a strong Diffie-Hellman key group in most SSL configurations.

Run the commands below to generate a key in the /etc/ssl/cert directory on Ubuntu Linux.

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

How to obtain Let’s Encrypt certificates on Ubuntu Linux

At this point, you should be ready to obtain a free certificate from Let’s Encrypt. Before you generate your free certificates, run the commands below to enable the Nginx server block.

sudo ln -s /etc/nginx/sites-available/example.com.conf /etc/nginx/sites-enabled/

Once complete, reload Nginx by running the commands below.

sudo systemctl restart nginx

Now you’re ready to generate Let’s Encrypt SSL certificates. Run the commands below, replacing example.com with your domain to generate Let’s Encrypt SSL certificates.

sudo certbot certonly --agree-tos --email admin@example.com --webroot -w /var/www/html -d example.com -d www.example.com

A successful certificate generation message will look similar to the one below:

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 2021-09-07. 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 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

You can now use the certificate and key in your Nginx server block configurations.

Your new configuration, after adding recommended SSL settings, should look similar to the one below:

  • The first server block listens on port 80. It contains a 301 redirect to redirect HTTP to HTTPS.
  • The second server block listens on port 443. It contains a 301 redirect to redirect www to the non-www domain.
server {
    listen 80;
    listen [::]:80;
    root /var/www/example.com;
    index  index.php index.html index.htm;
    server_name  example.com www.example.com;

    include snippets/well-known.conf;

    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    root /var/www/example.com;
    index  index.php index.html index.htm;
    server_name www.example.com;
   
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;

    add_header Strict-Transport-Security "max-age=31536000;  includeSubDomains";
    
    include snippets/well-known.conf;

    return 301 https://example.com$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    root /var/www/example.com;
    index  index.php index.html index.htm;
    server_name example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;

    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:50m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;

    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 30s;

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

    add_header Strict-Transport-Security "max-age=31536000;  includeSubDomains";
    add_header X-Frame-Options SAMEORIGIN;
    add_header X-Content-Type-Options nosniff;
    
    include snippets/well-known.conf;

    client_max_body_size 100M;

    autoindex off;
    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
         include snippets/fastcgi-php.conf;
         fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
         fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
         include fastcgi_params;
    }
}

Make changes to the configurations above to suit your environment. However, the settings above should work in most Nginx environments.

Reload Nginx configurations by restarting the server.

How to auto-renew Let’s Encrypt certificates

Once the certificate is generated, you can set up a process to renew the certificates automatically. By default, it expires in 90 days. Setting up a process so you don’t have to remember to renew is the best option.

The certbot package creates a cronjob and a systemd timer to automatically renew the certificates before expiration. The timer will automatically renew the certificates 30 days before their expiration.

The crontab file is created at the location below.

cat /etc/cron.d/certbot

You can now use the certificate and key files referenced in your Nginx configurations to enable HTTPS.

Conclusion:

  • Let’s Encrypt provides a cost-effective way to secure your web applications with SSL certificates.
  • The process of obtaining and renewing certificates with Certbot is automated, limiting the need for manual intervention.
  • Implementing HTTPS enhances your website’s security, boosts user trust, and can improve your website’s SEO rankings.
  • Maintaining the correct Nginx configurations ensures a seamless transition to HTTPS for your visitors.
  • Regularly updating your server configurations and monitoring SSL certificate status is essential for ongoing security.
  • Consider backing up your Certbot configuration directory to safeguard your SSL certificates and account credentials.

Comments

16 responses to “How to Setup Let’s Encrypt with Nginx on Ubuntu Linux”

  1. Hey, thank you for the great content. Useful tutorial, indeed.

    However, I didn’t like the SSL installation part…. Why so complicated? I remember you had a post with a very simple installation tutorial to follow… I use those two commands below for the SSL setup and it works without problems:

    I simply use:
    >>sudo apt install certbot python3-certbot-nginx
    >>sudo certbot –nginx -d example.com

    Most important it updates automatically. All the other details in this article: https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-20-04

  2. I was directed here from Apache, but this is for Nginx, what is the point to direct here?

  3. C.W. Smith Avatar
    C.W. Smith

    So, I am getting an error 403 and am trying to solve the issue. I am using an Open Social Drupal distribution as the base.

  4. […] How to set up Let’s Encrypt SSL certificate for Nginx on Ubuntu Linux […]

  5. […] How to set up Let’s Encrypt SSL certificate for Nginx on Ubuntu Linux […]

  6. […] How to set up Let’s Encrypt SSL certificate for Nginx on Ubuntu Linux […]

  7. […] How to set up Let’s Encrypt SSL certificate for Nginx on Ubuntu Linux […]

  8. […] How to set up Let’s Encrypt SSL certificate for Nginx on Ubuntu Linux […]

  9. […] How to set up Let’s Encrypt SSL certificate for Nginx on Ubuntu Linux […]

  10. […] How to setup Let’s Encrypt with Nginx web server […]

  11. […] How to set up Let’s Encrypt SSL certificate with Nginx on Ubuntu […]

  12. […] How to set up Let’s Encrypt SSL certificate for Nginx on Ubuntu Linux […]

  13. […] How to set up Let’s Encrypt SSL certificate for Nginx on Ubuntu Linux […]

  14. […] How to set up Let’s Encrypt SSL certificate for Nginx on Ubuntu Linux […]

Leave a Reply

Your email address will not be published. Required fields are marked *