How to Setup Let’s Encrypt with Nginx Reverse Proxy

Nginx rewrite rules for Let's Encrypt ".well-known" directory when using Nginx as a reverse proxy

Let’s Encrypt SSL certificate issuing or renewing doesn’t work out of the box when you’re running Nginx as a reverse proxy. This is because Nginx will be routing requests to a different location and certbot too routed to the proxied application or directory. This tutorial will show you how to setup Let’s Encrypt with Nginx reverse proxy properly.

The Problem: Let's Encrypt Acme Challenge Failed

Let’s Encrypt uses acme challenges to verify the domain before issuing its free SSL certificates. These challenges are automatically created by certbot in the ‘.well-known’ directory in domains public_html directory. When using Nginx as a reverse proxy, content is not served from the public_html directory.  Instead, Nginx route requests to the proxied application or the proxied directory. A couple of examples for this kind of setup are Invoice Ninja and Elgg installations with our Virtualmin – Nginx server setup. Although not really “proxy” setups, public content are served from outside of public_html directory in both occasions.

So, when certbot create acme challenges in the public_html directory, these challances are not publically available because Nginx route those requests to a different location. And the challenge fails so does the certificate creation.


The Solution: Add Nginx Rewrite Rules for ".well-known" Directory

Certbot creates ‘.well-known’ directory inside public_html directory for acme challenges. We can simply add three lines of code to Nginx configuration file which tells Nginx to serve all requests to “.well-known” directory from within the public_html directory.

Let’s open Nginx virtual host configuration file for the domain,

nano /etc/nginx/sites-available/

Look for the following line,

	fastcgi_param HTTPS $https;

I usually ask you to add custom Nginx rules immediately after this line. So, it’s possible I’ve already asked you to add some codes after this line on a previous tutorial. And I may ask you to add more codes in the future tutorials you follow on But remember to keep the codes you’ve already added or will add in the future below the rewrite rules you add here to avoid conflicts.

With that in mind, add following rewrite rules immediately after fastcgi_param HTTPS $https; in a new line.

    location /.well-known {
            alias /home/username/public_html/.well-known;

Note that you need to change the correct public_html directory in above code. Save the file and then restart Nginx webserver.

systemctl restart nginx.service

Now you can go back and install Let’s Encrypt SSL certificate for your domain with Virtualmin as usual.


Hey!! I'm Tharindu. I'm from Sri Lanka. I'm a part time freelancer and this is my blog where I write about everything I think might be useful to readers. If you read a tutorial here and want to hire me, contact me here.

Related Articles

Leave a Reply

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

Back to top button