Skip to content
Follow
Ubuntu Linux

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

Richard
Written by
Richard
Sep 8, 2021 Updated Oct 6, 2026 8 min read
How to Setup Let’s Encrypt with Nginx on Ubuntu Linux
How to Setup Let’s Encrypt with Nginx on Ubuntu Linux

Let’s Encrypt certificates give your Ubuntu Linux web server free HTTPS, with the padlock icon in browsers and encrypted connections between your visitors and the site. Certbot is a free tool that works with Nginx. It handles the setup and renews your certificates automatically, so the site stays secure without manual work. Each certificate is valid for 90 days.

Advertisement

Before you start, check three things. Your domain’s DNS record must point to this server. Ports 80 and 443 must be reachable from the internet, including through any firewall in front of the server. And you need a user with sudo rights. Let’s Encrypt checks your domain over port 80, so if that port is blocked the certificate request will fail.

⚡ Quick Answer

Install Certbot using `sudo apt update` and `sudo apt install certbot`. Then, generate your certificate with `sudo certbot certonly –agree-tos –email admin@example.com –webroot -w /var/www/html -d your_domain.com`.

Advertisement

How to install Certbot on Ubuntu Linux

Certbot is a command line tool that automates getting and renewing Let’s Encrypt SSL certificates. Other tools do the same job, but Certbot is efficient, well documented and easy to use. It talks to the Let’s Encrypt servers, proves you control the domain, downloads the certificate and keeps it renewed.

Install Certbot on Ubuntu by running the commands below in a terminal. Enter your sudo password if you are asked for it. When the commands finish without errors, Certbot is ready to use.

🐧Bash / Shell
sudo apt update
sudo apt install certbot

How to generate Let’s Encrypt certificates for Ubuntu Linux

Certbot can use the Webroot plugin to verify your domain. The plugin creates and renews your free SSL certificates by checking a specific folder on your web server. Your site stays online the whole time, because Nginx keeps serving pages while the check runs.

The Webroot plugin automates certificate creation and renewal. It places a small challenge file in the /.well-known/acme-challenge folder inside your web server’s main directory. Let’s Encrypt then requests that file over HTTP. If it can fetch the file from your domain, that proves the domain points to the server that asked for the certificate, and so confirms you own the site.

Advertisement

Next, create a challenge/response configuration file. It tells Nginx how to serve the challenge files, so Let's Encrypt can validate the server the certificates are issued for.

Run the commands below to create a configuration file called well-known.conf in the /etc/nginx/snippets directory. This directory holds reusable pieces of configuration that you can include in any Nginx server block. Because you will include this file in every server block that needs a certificate, you only have to write it once.

🐧Bash / Shell
sudo nano /etc/nginx/snippets/well-known.conf

The commands above open the new file in an editor. Copy the content below, paste it into the file and save it. If you are using a terminal editor, check that the text pasted exactly as shown and that no lines were cut off.

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

This file lets Let's Encrypt validate the web server through the Webroot plugin. If a server block does not include it, the validation request for that domain will usually fail with a 404 or a similar error.

Advertisement

Before you add SSL and HTTPS, a typical Nginx server block file looks like the one below. Make sure it includes the well-known snippet you created above. Replace example.com with your own domain and adjust the document root to match your site.

🐘PHP
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

A strong Diffie-Hellman key group is an important part of a secure SSL configuration on Ubuntu Linux. It strengthens the key exchange that happens when a browser sets up an encrypted connection with your server.

Run the commands below to generate the key in the /etc/ssl/cert directory on Ubuntu Linux. Generating the key can take a few minutes on a small server, and the terminal may look idle while it works. Wait for the prompt to come back before you go on.

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

How to obtain Let's Encrypt certificates on Ubuntu Linux

Before Certbot can get a certificate, Nginx has to be serving your domain. To do that, link your site configuration file into the enabled sites folder.

Advertisement
  1. Run the command sudo ln -s /etc/nginx/sites-available/example.com.conf /etc/nginx/sites-enabled/ and replace example.com with the name of your own configuration file.

The command prints nothing when it works. The link tells Nginx to load your site settings. To undo this later, delete the link from the sites-enabled folder. Your original file in sites-available stays untouched.

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

Once the link is in place, reload Nginx by running the commands below. A reload applies the new configuration without dropping existing connections. If Nginx reports an error, fix the configuration file it points to before you continue.

🐧Bash / Shell
sudo systemctl restart nginx

Now you can generate the Let's Encrypt SSL certificate. Run the commands below, and replace example.com with your domain. Certbot may ask for an email address and for you to agree to the terms of service. The email address is used for expiry notices and important account messages.

🐧Bash / Shell
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 prints a message similar to the one below. If the request fails, the most common causes are a DNS record that does not point to this server, a blocked port 80, or a server block that is missing the well-known snippet. Let's Encrypt also limits how many requests you can make in a short time, so avoid repeating failed requests over and over.

Advertisement
🟨JavaScript
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. Point the SSL settings in each server block at the files Certbot reported in its success message.

After you add the recommended SSL settings, your configuration should look similar to the one below. Here is what the two server blocks do:

  • The first server block listens on port 80. It contains a 301 redirect that sends all HTTP traffic to HTTPS, so visitors who type the plain address still end up on the secure site.
  • The second server block listens on port 443. It contains a 301 redirect that sends the www address to the non-www domain, so the site has a single address.
🐘PHP
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.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/letsen

Change the configuration above to suit your environment, for example the domain names, document root and any extra locations your application needs. The settings should work in most Nginx environments as they are.

Apply the new configuration by restarting the server with the command below. Afterwards, open your site in a browser using https:// and check that the padlock appears. Also try the http:// address, which should redirect to HTTPS.

Advertisement

How to auto-renew Let's Encrypt certificates

Renewal is handled by the systemd timer that comes with Certbot, so you do not have to set anything up. This matters because Let's Encrypt certificates expire every 90 days, and an expired certificate makes browsers show a security warning to your visitors. The timer checks for renewals twice a day and updates your certificate files in the background before they expire.

The certbot package renews Let's Encrypt certificates automatically. The systemd timer included with certbot renews them 30 days before they expire. On most days it finds nothing due and does nothing.

The renewal schedule file is created at the location below.

💻Code
cat /etc/cron.d/certbot

You can now use the certificate and key files referenced in your Nginx configurations to enable HTTPS. Because renewal replaces the files in place, you do not need to change the configuration again when a certificate renews.

Conclusion:

  • Let's Encrypt is a cost-effective way to secure your web applications with SSL certificates.
  • Certbot automates getting and renewing certificates, which limits the need for manual work.
  • HTTPS improves your website's security, builds user trust and can help your search rankings.
  • Keeping the Nginx configuration correct makes the move to HTTPS smooth for your visitors.
  • Review your server configuration regularly and watch the certificate status. That is essential for ongoing security.
  • Back up your Certbot configuration directory to protect your SSL certificates and account credentials.

Have a question about this guide?

Answered by AI from this guide. Good questions may be added to this page — please don't include personal details.

Did this guide fix your problem?

Richard

About the Author

Richard

Tech Writer, IT Professional

Richard is a writer at Geek Rewind who turns complex IT tasks into clear, step-by-step guides. He draws on years of hands-on experience in system administration and enterprise IT operations, focusing on Windows, Linux and WordPress: the problems people actually run into, and the fixes that work. His server and WordPress guides come from systems he runs himself. Richard builds and maintains the platform behind Geek Rewind, from its Ubuntu servers and Nginx configuration to its custom WordPress plugins. Many new tutorials start with readers' questions, and he's always glad to answer them in the comments.

Advertisement

20 Comments

Leave a Comment

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