# Reverse proxy and letsencrypt certificate

**URL:** <https://community.letsencrypt.org/t/reverse-proxy-and-letsencrypt-certificate/140976>\
**Category:** Help\
**Created:** [December 20, 2020, 5:31pm UTC](https://community.letsencrypt.org/t/reverse-proxy-and-letsencrypt-certificate/140976 "2020-12-20T17:31:32Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![ggamehdtv](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/ggamehdtv/32/45562_2.png) [@ggamehdtv](https://community.letsencrypt.org/u/ggamehdtv)\
**Post date:** [December 20, 2020, 5:31pm UTC](https://community.letsencrypt.org/t/reverse-proxy-and-letsencrypt-certificate/140976/1 "2020-12-20T17:31:32Z")

</div>

Hi,

I have a question about creating a certificate.  
I have 2 servers. One with nginx reverse proxy and one with the webserver itself apache.

Do I need to create the certificate for the domain on the reverse proxy server or on the backend webserver (apache)?

Because I am trying to set it up with dry-run and is succeeds on the webserver itself. But when trying to do this on the reverse proxy server it says unauthorized.

I already have a certificate on the reverse proxy for another domain and this is working as expected.

Thanks in advance!

---

<div class="post-metadata">

**Author:** ![griffin](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/griffin/32/50204_2.png) [@griffin](https://community.letsencrypt.org/u/griffin)\
**Post date:** [December 20, 2020, 7:28pm UTC](https://community.letsencrypt.org/t/reverse-proxy-and-letsencrypt-certificate/140976/2 "2020-12-20T19:28:50Z")

</div>

Welcome to the Let's Encrypt Community 🙂

A certificate belongs to the domain name(s) being served and not to any particular piece of software. When acquiring a certificate using [http-01 challenges](https://letsencrypt.org/docs/challenge-types/), the ACME client (e.g. certbot) is responsible for creating a challenge file accessible via `http://www.example.com/.well-known/acme-challenge/`. Certbot handles the `nginx` and `apache` authenticators differently. For `nginx`, an exception is created in the webserver configuration to serve the directory. For `apache`, the file is created in the directory itself. Thus, you want to be sure to run the client such that the challenge file can actually be found via a GET request over port 80.

In terms of who serves the certificate, that would be the piece of software actually responding for port 443 (or whatever port you're using the certificate with). This is the software that _terminates_ SSL/TLS (i.e. does the encrypting, decrypting, etc.).

> **[NGINX Docs | NGINX SSL Termination](https://docs.nginx.com/nginx/admin-guide/security-controls/terminating-ssl-http/)**
>
> Terminate HTTPS traffic from clients, relieving your upstream web and application servers of the computational load of SSL/TLS encryption.

> **[NGINX Docs | SSL Termination for TCP Upstream Servers](https://docs.nginx.com/nginx/admin-guide/security-controls/terminating-ssl-tcp/)**
>
> Terminate SSL/TLS-encrypted traffic from clients, relieving your upstream TCP servers of the computational load.

---

<div class="post-metadata">

**Author:** ![yens77](https://avatars.discourse-cdn.com/v4/letter/y/f07891/32.png) [@yens77](https://community.letsencrypt.org/u/yens77)\
**Post date:** [December 20, 2020, 7:29pm UTC](https://community.letsencrypt.org/t/reverse-proxy-and-letsencrypt-certificate/140976/3 "2020-12-20T19:29:48Z")

</div>

Hello, you need them on both. I made similar post some minutes ago but it is about a renewal issue.  
You can see there my configs as example.

---

<div class="post-metadata">

**Author:** ![griffin](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/griffin/32/50204_2.png) [@griffin](https://community.letsencrypt.org/u/griffin)\
**Post date:** [December 20, 2020, 7:32pm UTC](https://community.letsencrypt.org/t/reverse-proxy-and-letsencrypt-certificate/140976/4 "2020-12-20T19:32:56Z")

</div>

> [@yens77](#):
>
> you need them on both

Not necessarily. You only need a certificate to be served by the entity responding for port 443 (or whatever port you're using the certificate for). Installing the certificate anywhere else will just leave it sitting there.

---

<div class="post-metadata">

**Author:** ![ggamehdtv](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/ggamehdtv/32/45562_2.png) [@ggamehdtv](https://community.letsencrypt.org/u/ggamehdtv)\
**Post date:** [December 21, 2020, 5:28pm UTC](https://community.letsencrypt.org/t/reverse-proxy-and-letsencrypt-certificate/140976/5 "2020-12-21T17:28:32Z")

</div>

Hey thank you for your help so far.  
I got the certbot certificate request working on the backend server itself. But on the reverse proxy it won't pass.

What do I need to put in the nginx reverse proxy config to proxy to the backend and check the ssl in there?

---

<div class="post-metadata">

**Author:** ![jvanasco](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/jvanasco/32/55900_2.png) [@jvanasco](https://community.letsencrypt.org/u/jvanasco)\
**Post date:** [December 21, 2020, 7:20pm UTC](https://community.letsencrypt.org/t/reverse-proxy-and-letsencrypt-certificate/140976/6 "2020-12-21T19:20:00Z")

</div>

> [@ggamehdtv](#):
>
> Because I am trying to set it up with dry-run and is succeeds on the webserver itself. But when trying to do this on the reverse proxy server it says unauthorized.

Something on your reverse proxy/nginx configuration is blocking this.

Based on "dry run", it sounds like you are running Certbot.

The easiest thing to do, IMHO:

1. Run certbot in standalone mode
2. Pass in the `--http-01-port` flag to run certbot on a port like 8080
3. Have your nginx proxy pass all the traffic on `/.well-known` to port 8080 (or whatever you chose).

That should bypass most ways you may have created conflicts in your nginx setup.

That will allow you to terminate SSL on nginx, and then not worry about any ssl certificates on your apache backend servers.

---

<div class="post-metadata">

**Author:** ![ggamehdtv](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/ggamehdtv/32/45562_2.png) [@ggamehdtv](https://community.letsencrypt.org/u/ggamehdtv)\
**Post date:** [December 21, 2020, 7:36pm UTC](https://community.letsencrypt.org/t/reverse-proxy-and-letsencrypt-certificate/140976/8 "2020-12-21T19:36:29Z")

</div>

Everything below is from and executed on the reverse proxy. This is the command I execute on the reverse proxy webserver:

 ![InkedScreenshot_1_LI](https://global.discourse-cdn.com/letsencrypt/original/3X/9/3/93dd9e25915f553bc7285b8875c35e7eac27cb91.jpeg)

Port 80 of the router is port forwarded to 81 on the reverse proxy.  
And my http reverse proxy config:

```auto
   server {
       listen 81;
       server_name domain.domain.com; 

       location / {
       proxy_http_version 1.1;
       proxy_set_header Host $host;
       proxy_set_header X-Forwarded-Proto $scheme;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_buffering off;
       client_max_body_size 1024M;
       proxy_pass http://192.168.2.151:81/;
       proxy_redirect off;
       }

       location /.well-known/carddav {
       return 301 $scheme://$host/remote.php/dav;
       }

       location /.well-known/caldav {
       return $scheme://$host/remote.php/dav;
       }
}

```

Do I miss something for the ./well-known?  
The ./well-known stated already is needed as per installation instructions of nextcloud.

The webserver itself on the backend through the reverse proxy is working as expected. It went wrong from this part when creating the certificate from the reverse proxy server. When I do the webroot certificate creation on the backend server where the reverse proxy is sent too. It succeeds.

---

<div class="post-metadata">

**Author:** ![schoen](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/schoen/32/79_2.png) [@schoen](https://community.letsencrypt.org/u/schoen)\
**Post date:** [December 22, 2020, 5:04am UTC](https://community.letsencrypt.org/t/reverse-proxy-and-letsencrypt-certificate/140976/9 "2020-12-22T05:04:46Z")

</div>

> [@ggamehdtv](#):
>
> Do I miss something for the ./well-known?  
> The ./well-known stated already is needed as per installation instructions of nextcloud.

The well-known path used by Let's Encrypt for certificate issuance is `/.well-known/acme-challenge`, so I'd think you'll want to add a similar directive for that path.

---

<div class="post-metadata">

**Author:** ![ggamehdtv](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/ggamehdtv/32/45562_2.png) [@ggamehdtv](https://community.letsencrypt.org/u/ggamehdtv)\
**Post date:** [December 22, 2020, 11:34am UTC](https://community.letsencrypt.org/t/reverse-proxy-and-letsencrypt-certificate/140976/10 "2020-12-22T11:34:38Z")

</div>

You mean to add this on the reverse proxy and send /.well-known/acme-challenge to the backend server?

---

<div class="post-metadata">

**Author:** ![schoen](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/schoen/32/79_2.png) [@schoen](https://community.letsencrypt.org/u/schoen)\
**Post date:** [December 22, 2020, 5:12pm UTC](https://community.letsencrypt.org/t/reverse-proxy-and-letsencrypt-certificate/140976/11 "2020-12-22T17:12:08Z")

</div>

Yes, that's right. 🙂

---

<div class="post-metadata">

**Author:** ![ggamehdtv](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/ggamehdtv/32/45562_2.png) [@ggamehdtv](https://community.letsencrypt.org/u/ggamehdtv)\
**Post date:** [December 22, 2020, 5:49pm UTC](https://community.letsencrypt.org/t/reverse-proxy-and-letsencrypt-certificate/140976/12 "2020-12-22T17:49:13Z")

</div>

I will try that right away, But then the question:  
Why will the certificate request succeed on the backend server with the current reverse proxy configuration?  
And fails when I execute the command on the reverse proxy?

Just executed it with the following added to the reverse proxy:  
 ![image](https://global.discourse-cdn.com/letsencrypt/original/3X/0/3/03c988dd37a8ca01975b8bbe18a26c44a4803b67.png)

And tried this one afterwards:  
 ![image](https://global.discourse-cdn.com/letsencrypt/original/3X/4/2/42196952f85dfe3d6025cfdbab1987485f73ff85.png)

But it looks like I got a new error:

 ![InkedScreenshot_2_LI](https://global.discourse-cdn.com/letsencrypt/original/3X/5/2/52404bf0679057501a684ed2508716c3a2d9e725.jpeg)

---

<div class="post-metadata">

**Author:** ![ggamehdtv](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/ggamehdtv/32/45562_2.png) [@ggamehdtv](https://community.letsencrypt.org/u/ggamehdtv)\
**Post date:** [December 22, 2020, 7:30pm UTC](https://community.letsencrypt.org/t/reverse-proxy-and-letsencrypt-certificate/140976/13 "2020-12-22T19:30:17Z")

</div>

Just got the acme challenge working with webroot on the reverse proxy. Can you confirm for me:  
If I set ssl verification with the certificate in the reverse proxy and then proxy pass the connection to the backend. The connection will be encrypted between client and reverse proxy. And unencrypted between reverse proxy and backend. (Within the same lan network).

Is there a possibility to use this certificate between backend and reverse proxy too? so There is a encryption from client to backend?

---

<div class="post-metadata">

**Author:** ![griffin](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/griffin/32/50204_2.png) [@griffin](https://community.letsencrypt.org/u/griffin)\
**Post date:** [December 22, 2020, 7:58pm UTC](https://community.letsencrypt.org/t/reverse-proxy-and-letsencrypt-certificate/140976/14 "2020-12-22T19:58:27Z")

</div>

It's possible to go either way depending upon your configuration. This is the same dilemma that people face when using Cloudflare. If you physically control the LAN and your backend devices have no publicly-facing interface, what's the idea of using https internally? Is there an application requirement? A little guy in a racoon mask bugging your network? 🦝

---

<div class="post-metadata">

**Author:** ![schoen](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/schoen/32/79_2.png) [@schoen](https://community.letsencrypt.org/u/schoen)\
**Post date:** [December 22, 2020, 8:08pm UTC](https://community.letsencrypt.org/t/reverse-proxy-and-letsencrypt-certificate/140976/15 "2020-12-22T20:08:22Z")

</div>

Further to @griffin's point, you could do the same thing as some Cloudflare users and use a self-signed certificate which you somehow explicitly configure the reverse proxy to trust.

> [@griffin](#):
>
> This is the same dilemma that people face when using Cloudflare.

Well, Cloudflare's connection to your origin server is always going over public Internet links, not just over your LAN. So the dilemma is related but a little different, as I think you were suggesting with the raccoon. 🦝

---

<div class="post-metadata">

**Author:** ![griffin](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/griffin/32/50204_2.png) [@griffin](https://community.letsencrypt.org/u/griffin)\
**Post date:** [December 22, 2020, 8:20pm UTC](https://community.letsencrypt.org/t/reverse-proxy-and-letsencrypt-certificate/140976/16 "2020-12-22T20:20:25Z")

</div>

And yet Cloudflare offers their ridiculous "Flexible" option... 😁 The illusion of security: worse than the admission of no security.

> **[End-to-end HTTPS with Cloudflare - Part 3: SSL options](https://support.cloudflare.com/hc/en-us/articles/200170416-End-to-end-HTTPS-with-Cloudflare-Part-3-SSL-options#h_4e0d1a7c-eb71-4204-9e22-9d3ef9ef7fef)**
>
> Understand which Cloudflare SSL options encrypt HTTPS traffic between Cloudflare and the origin web server.
> 
> 
> Overview
> Off
> Flexible
> Full
> Full (strict)
> Strict (SSL-Only Origin Pull)
> SSL/TLS Recommen...

---

<div class="post-metadata">

**Author:** ![schoen](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/schoen/32/79_2.png) [@schoen](https://community.letsencrypt.org/u/schoen)\
**Post date:** [December 22, 2020, 8:23pm UTC](https://community.letsencrypt.org/t/reverse-proxy-and-letsencrypt-certificate/140976/17 "2020-12-22T20:23:40Z")

</div>

> [@griffin](#):
>
> And yet Cloudflare offers their ridiculous "Flexible" option... 😁

Yeah, I remember some conversations where people argued that someone (maybe browser root programs) should try to forbid Cloudflare from offering that option, because it would undermine users' ability to predict how well-protected their communications are. I think the counterargument was that someone operating a web service can _always_ choose to share or transmit user data in some unexpectedly insecure way, and browsers can never do anything to guarantee that this isn't happening.

---

<div class="post-metadata">

**Author:** ![griffin](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/griffin/32/50204_2.png) [@griffin](https://community.letsencrypt.org/u/griffin)\
**Post date:** [December 22, 2020, 8:29pm UTC](https://community.letsencrypt.org/t/reverse-proxy-and-letsencrypt-certificate/140976/18 "2020-12-22T20:29:51Z")

</div>

Seems like they might as well just rename the "Flexible" option to "Padlock Deceiver". Their own excuse for having the option is almost as ridiculous as the option itself:

> Use Flexible only as a last resort if you are unable to setup SSL at your origin web server.

---

<div class="post-metadata">

**Author:** ![ggamehdtv](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/ggamehdtv/32/45562_2.png) [@ggamehdtv](https://community.letsencrypt.org/u/ggamehdtv)\
**Post date:** [December 22, 2020, 9:23pm UTC](https://community.letsencrypt.org/t/reverse-proxy-and-letsencrypt-certificate/140976/19 "2020-12-22T21:23:15Z")

</div>

Thanks, will take care of client to reverse proxy ssl encryption at first.

I am physically in control of the LAN network so no problem in there.  
There is no need or application requirement for reverse proxy to backend (lan) ssl communication. But I think that it's more about how crazy you want to set it.

Maybe a little for the 🦝 in the garage running around the reverse proxy 😛.

---

<div class="post-metadata">

**Author:** ![yens77](https://avatars.discourse-cdn.com/v4/letter/y/f07891/32.png) [@yens77](https://community.letsencrypt.org/u/yens77)\
**Post date:** [December 23, 2020, 9:22pm UTC](https://community.letsencrypt.org/t/reverse-proxy-and-letsencrypt-certificate/140976/20 "2020-12-23T21:22:29Z")

</div>

Have a look here for nextcloud configuration:  
[Reverse proxy - nextcloud](https://docs.nextcloud.com/server/19/admin_manual/configuration_server/reverse_proxy_configuration.html)  
Besides the setting on the proxy, I had to enter in the nextcloud config.php  
` 'trusted_proxies' => ['proxy IP here'],`  
in order to work.

---

<div class="post-metadata">

**Author:** ![system](https://global.discourse-cdn.com/letsencrypt/original/3X/c/a/ca6c06ea1ea201324bba7048c6841ce60236468d.png) [@system](https://community.letsencrypt.org/u/system)\
**Post date:** [January 22, 2021, 9:24pm UTC](https://community.letsencrypt.org/t/reverse-proxy-and-letsencrypt-certificate/140976/21 "2021-01-22T21:24:49Z")

</div>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
