SSL Issues when Configuring Reverse Proxy for accessing docker services, Self Signed Certificates issued

1. Caddy version (caddy version):

CADDY_VERSION=v2.3.0

2. How I run Caddy:

In a docker container, on a raspberry pi4 running omv5.

a. System environment:

Docker, raspberry pi 4, omv5.

Internet/LAN details:

  • I have ATT Uverse, with a Google Nest Wifi set up in dmz+ mode.
  • The raspberry pi server is wired to the Nest Wifi. 443 and 80 are forwarded to the raspberry pi over both TCP and UDP
  • I am using google domains, a dynamic DNS Synthetic A record exists for the subdomain books..com.
  • I have a container running ddclient successfully keeping this dynamic dns record updated.

b. Command:

sudo docker-compose up -d

c. Service/unit/compose file:

version: "3"
services:

  caddy:
    image: caddy:latest
    container_name: caddy
    hostname: caddy
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    environment:
      - MY_DOMAIN
    volumes:
      - /home/pi/docker/caddy/.Caddyfile:/etc/caddy/Caddyfile
      - /home/pi/docker/caddy/.data:/data
      - /home/pi/docker/caddy/.config:/config

d. My complete Caddyfile or JSON config:

{
     acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
     email email@gmail.com
}


books.website.com {
    reverse_proxy 192.168.86.249:8083
}

3. The problem I’m having:

When accessing the subdomain in my LAN, the service is returned.
When accessing outside the LAN, I get a ssl self signed certificate in chain error message.

I’m not sure what is wrong with my SSL configuration. I have left the acme at staging for the time being (but don’t know what “working” looks like with this set).

4. Error messages and/or full log output:

{"level":"info","ts":1611176853.4052734,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adapter":"caddyfile"}
{"level":"info","ts":1611176853.4110165,"logger":"admin","msg":"admin endpoint started","address":"tcp/localhost:2019","enforce_origin":false,"origins":["localhost:2019","[::1]:2019","127.0.0.1:2019"]}
{"level":"info","ts":1611176853.4118595,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0x2cb9ef0"}
{"level":"info","ts":1611176853.41203,"logger":"http","msg":"server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS","server_name":"srv0","https_port":443}
{"level":"info","ts":1611176853.412362,"logger":"http","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv0"}
{"level":"info","ts":1611176853.4134648,"logger":"tls","msg":"cleaned up storage units"}
{"level":"info","ts":1611176853.4139993,"logger":"http","msg":"enabling automatic TLS certificate management","domains":["books.website.com"]}
{"level":"info","ts":1611176853.4147255,"msg":"autosaved config","file":"/config/caddy/autosave.json"}
{"level":"info","ts":1611176853.414795,"msg":"serving initial configuration"}
{"level":"info","ts":1611176853.4162135,"logger":"tls.obtain","msg":"acquiring lock","identifier":"books.website.com"}
{"level":"info","ts":1611176853.4175136,"logger":"tls.obtain","msg":"lock acquired","identifier":"books.website.com"}
{"level":"info","ts":1611176854.0254877,"logger":"tls.issuance.acme","msg":"waiting on internal rate limiter","identifiers":["books.website.com"]}
{"level":"info","ts":1611176854.0255497,"logger":"tls.issuance.acme","msg":"done waiting on internal rate limiter","identifiers":["books.website.com"]}
{"level":"info","ts":1611176854.159837,"logger":"tls.issuance.acme.acme_client","msg":"trying to solve challenge","identifier":"books.website.com","challenge_type":"http-01","ca":"https://acme-staging-v02.api.letsencrypt.org/directory"}
{"level":"info","ts":1611176854.5906181,"logger":"tls.issuance.acme","msg":"served key authentication","identifier":"books.website.com","challenge":"http-01","remote":"52.58.118.98:20710"}
{"level":"info","ts":1611176854.825973,"logger":"tls.issuance.acme","msg":"served key authentication","identifier":"books.website.com","challenge":"http-01","remote":"66.133.109.36:27690"}
{"level":"info","ts":1611176855.1265519,"logger":"tls.issuance.acme","msg":"served key authentication","identifier":"books.website.com","challenge":"http-01","remote":"18.224.20.83:31060"}
{"level":"info","ts":1611176855.4601676,"logger":"tls.issuance.acme.acme_client","msg":"validations succeeded; finalizing order","order":"https://acme-staging-v02.api.letsencrypt.org/acme/order/17618337/225569706"}
{"level":"info","ts":1611176855.9150028,"logger":"tls.issuance.acme.acme_client","msg":"successfully downloaded available certificate chains","count":2,"first_url":"https://acme-staging-v02.api.letsencrypt.org/acme/cert/fab03aebfaf426bdf9e14d870ddbbacbf366"}
{"level":"info","ts":1611176855.9174347,"logger":"tls.obtain","msg":"certificate obtained successfully","identifier":"books.dnullify.com"}
{"level":"info","ts":1611176855.917513,"logger":"tls.obtain","msg":"releasing lock","identifier":"books.dnullify.com"}

5. What I already tried:

I have started over several times. Most recently I followed the following guide:

  • I ensured that the data directory is bind mounted to the host for persistence.
  • I ensured that my port forwarding rules were up before bringing up the service.
  • I ensured that my dns a record resolves to my home IP address.
    • I am not sure why but nslookup in my lan returns:
❯ nslookup books.website.com
;; reply from unexpected source: 2600:1700:ccf0:5a28:c8e1:88ff:fef3:98a8#53, expected 2600:1700:ccf0:5a28:c8e1:88ff:fef3:98a9#53
Server:		192.168.86.1
Address:	192.168.86.1#53

Non-authoritative answer:
Name:	books.website.com
Address: ***.***.***.***

I’m assuming this is my gatway resolving this domain rather than the internet.

  • I get the expected nslookup response from LAN.

Main issue so far:

  • I used cURL and openssl s_client -connect to my url from outside my LAN and I am seeing motorola certificates presented as the server certificates:

  • the “server” is insisting on using tls1.0.

❯ curl -vk https://books.website.com
* Rebuilt URL to: https://books.website.com/
*   Trying 108.202.***.***...
* TCP_NODELAY set
* Connected to books.website.com (108.202.***.***) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.0 (IN), TLS handshake, Certificate (11):
* TLSv1.0 (IN), TLS handshake, Server finished (14):
* TLSv1.0 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.0 (OUT), TLS change cipher, Client hello (1):
* TLSv1.0 (OUT), TLS handshake, Finished (20):
* TLSv1.0 (IN), TLS change cipher, Client hello (1):
* TLSv1.0 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.0 / AES256-SHA
* ALPN, server did not agree to a protocol
* Server certificate:
*  subject: C=US; ST=California; L=SanDiego; O=Motorola-Mobility Corp.; OU=VIP; CN=BMS; emailAddress=support@motorola-mobility.com
*  start date: Apr 17 18:08:25 2012 GMT
*  expire date: Apr 15 18:08:25 2022 GMT
*  issuer: C=US; ST=California; L=SanDiego; O=Motorola-Mobility Corp.; OU=VIP; CN=BMS; emailAddress=support@motorola-mobility.com
*  SSL certificate verify result: self signed certificate (18), continuing anyway.
> GET / HTTP/1.1
> Host: books.website.com
> User-Agent: curl/7.54.0
> Accept: */*
>
* Empty reply from server
* Connection #0 to host books.website.com left intact
curl: (52) Empty reply from server
~ ❯
❯ openssl s_client -connect books.website.com:443
CONNECTED(00000005)
depth=0 C = US, ST = California, L = SanDiego, O = Motorola-Mobility Corp., OU = VIP, CN = BMS, emailAddress = support@motorola-mobility.com
verify error:num=18:self signed certificate
verify return:1
depth=0 C = US, ST = California, L = SanDiego, O = Motorola-Mobility Corp., OU = VIP, CN = BMS, emailAddress = support@motorola-mobility.com
verify return:1
---
Certificate chain
 0 s:/C=US/ST=California/L=SanDiego/O=Motorola-Mobility Corp./OU=VIP/CN=BMS/emailAddress=support@motorola-mobility.com
   i:/C=US/ST=California/L=SanDiego/O=Motorola-Mobility Corp./OU=VIP/CN=BMS/emailAddress=support@motorola-mobility.com
---

I’m not sure why this is occurring, but if I had to guess my gateway is SSL terminating connection requests - and is not up to date with SSL versions. Hence self signed certs and tls 1.0.

I don’t have a high level of confidence in my interpretation of the output.

Thanks in advance!

6. Links to relevant resources:

I checked my gateway/modem firewall config:

Apparently this is for the wireless set top box.

Looks like this firewall rule is taking precedence over the dmz+ rule I had set when configuring the google wifi

Any advise on my options would be appreciated.
All I can think of is using another port for https, but I’m not sure how to configure or persist that.
I’m at the end of my home networking wit.

Apparently AT&T uses port 443 for testing that your service is working correctly.

That’s definitely… a choice.

I couldn’t say what the side effects might be if you removed that rule, but it’s clear that any HTTPS requests (port 443) will not reach your Caddy server because they get intercepted by your modem.

That’s what I was thinking!

I have no idea why they would have a default rule for 443. I’m not sure what happens if i remove it.

Do you happen to know whether I can run caddy on another port, such as 8443? The services I want to host would be for just me, and a few friends so instructing accessing the domain over a nonstandard port isn’t a deal breaker for me.

I just tried:

  • Port forwarding 8443 to the raspberry pi
  • Bringing down Caddy, and modifying the port assignment to the container as such:
version: "3"
services:

  caddy:
    image: caddy:latest
    container_name: caddy
    hostname: caddy
    restart: unless-stopped
    ports:
      - "80:80"
      - "8443:443"
    environment:
      - MY_DOMAIN
    volumes:
      - /home/pi/docker/caddy/.Caddyfile:/etc/caddy/Caddyfile
      - /home/pi/docker/caddy/.data:/data
      - /home/pi/docker/caddy/.config:/config

I got plenty of error messages in the container logs, and connection reset by peer when navigating to https://books.website.com:8443

Looks like their software reinstates it within a few hours.

Sigh. They could’ve picked any port in the world…

Absolutely. You can do this manually by specifying port 8443 in each site label (e.g. example.com:8443 or https://example.com:8443 if you want to be verbose).

There IS a Caddyfile global option to change the HTTPS port for the whole server, but it’s internal only, not affecting clients; its intended use is for port redirection (i.e. port 443 open at the firewall, but redirecting to another port on the Caddy host). That means Caddy would still issue redirects to 443 instead of the new port, for example. So that global option isn’t ideal for you.

So if you use 8443 instead, make a firewall rule for 8443 straight through to 8443, same with Docker.

Since you won’t be using 443 for challenge purposes, if you aren’t taking advantage of DNS challenges, you might want to disable TLS-ALPN while you’re at it. That can be done with the tls directive inside each site, should look like this:

tls acme {
  disable_tlsalpn_challenge
}

That will force Caddy to rely on the HTTP challenge (on port 80). It should work fine without doing this part, but this will just save Caddy the effort of bothering to try 443 (and likewise LetsEncrypt bothering to ping it).

The biggest concern is whether the upstream server will be happy with this. It might be awkward if it’s expecting 443 and issues redirects as such.

References:
Caddyfile Concepts — Caddy Documentation
tls (Caddyfile directive) — Caddy Documentation
Global options (Caddyfile) — Caddy Documentation

2 Likes

Alternately, have you considered purchasing a static IP?

In the linked thread they seem to mention that clients with static IPs don’t have 443 relegated for this purpose. If that’s feasible, it might be the ideal solution.

2 Likes

Thanks for the information!

Regarding buying a static IP; I think I would rather move all my services to a VPS in Linode, or something likewise. I’m just hosting a books server to collaborate on drafts of a fiction book, so it’s not critical. Install a VPN server on my raspberry pi for all else.

I’m okay moving to a nonstandard port for the time being; just to clarify: I would need to:

  • forward 8443 external to raspberry.pi:8443
  • bind 8443:8443 in docker-compose.yml
  • Caddyfile configuration change moving https to 8443
  • disable TLS-ALPN challenges (i assume this is bound to 443).

What I have running now:

  • Port forwarding 8443 external to raspberry.pi:443 internal
  • Original Caddyfile.

I’m now realizing this won’t work because https traffic from all services on the raspberry pi would be configured to 8443…

Yes to all of the above. Or, rather, yes, this would be the conceptually simplest option. You can get tricky with the interim ports (do some port redirection if you like). You can even go completely manual and override the redirects yourself and use whatever ports at whatever stage. But it will be simplest and easiest if Caddy thinks it’s serving on port x and the firewall is open at port x and traffic flows through both, since when things line up you won’t need to take manual control of stuff like said redirects.

I’m not sure I understand. Your current setup won’t work?

Theoretically you could leave the firewall forwarding 8443 → pi:443 and then Docker port forward from pi:443 to caddy:8443. This would be what I like to refer to as port detouring.

But yeah, if you do 8443 straight through (or, really, any given port as long as it’s the same all the way through), that’d be the easiest working solution.

1 Like

Again, I really appreciate the help!

Here’s what I have now:

Port forwarding:
80 ext > pi:80
443 ext > pi:443
8443 ext > pi:8443

docker-compose.yml:

version: "3"
services:

  caddy:
    image: caddy:latest
    container_name: caddy
    hostname: caddy
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "8443:8443"
    environment:
      - MY_DOMAIN
    volumes:
      - /home/pi/docker/caddy/.Caddyfile:/etc/caddy/Caddyfile
      - /home/pi/docker/caddy/.data:/data
      - /home/pi/docker/caddy/.config:/config

.Caddyfile:

{
     acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
     email email@gmail.com
}


https://books.website.com:8443 {
        reverse_proxy 192.168.86.249:8083
        tls acme {
                disable_tlsalpn_challenge
        }
}

Would this constitute 8443 straight through?

Sorry - I have been grinding at this for like 2 weeks worth of spare time. Caddy is the 3rd server I’ve tried to configure, but only today did I discover the stupid 443 firewall rule on my modem.
I previously got nginx-proxy-manager up working on 80, but couldn’t get a ssl cert working for 443, now i’m realizing that was never the problem.

Yep! 8443 at the firewall, at Docker, and at Caddy.

Theoretically you can ditch 443 at all stages. Docker might be listening but Caddy isn’t anymore (you’ve moved it to 8443) and neither, ostensibly, is the firewall.

1 Like

I think I have made a mistake in my Caddyfile;

From the docker logs:

{"level":"info","ts":1611188660.3357701,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adapter":"caddyfile"}
run: adapting config using caddyfile: parsing caddyfile tokens for 'tls': /etc/caddy/Caddyfile:9 - Error during parsing: single argument must either be 'internal' or an email address
{
     acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
     email email@gmail.com
}


https://books.website.com:8443 {
        reverse_proxy 192.168.86.249:8083
                tls acme {
                        disable_tlsalpn_challenge
                }
}

Line 9 is the tls acme directive; I’m not sure I’ve formatted the Caddyfile correctly.

Nope, my mistake! Giving another look at that doc, the acme block should actually go under issuer, I think, like so:

tls {
  issuer acme {
    disable_tlsalpn_challenge
  }
}

Thanks!

So current status:
Docker-compose:

version: "3"
services:

  caddy:
    image: caddy:latest
    container_name: caddy
    hostname: caddy
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "8443:8443"
    environment:
      - MY_DOMAIN
    volumes:
      - /home/pi/docker/caddy/.Caddyfile:/etc/caddy/Caddyfile
      - /home/pi/docker/caddy/.data:/data
      - /home/pi/docker/caddy/.config:/config

.Caddyfile

{
     acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
     email email@gmail.com
}


https://books.website.com:8443 {
        reverse_proxy 192.168.86.249:8083
        tls {
                issuer acme {
                        disable_tlsalpn_challenge
                }
        }
}

I’m currently getting curl output:

❯ curl -vk https://books.website.com:8443
* Rebuilt URL to: https://books.website.com:8443/
*   Trying xxx.xxx.xxx.xxx...
* TCP_NODELAY set
* Connected to books.website.com (xxx.xxx.xxx.xxx) port 8443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-ECDSA-CHACHA20-POLY1305
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=books.website.com
*  start date: Jan 20 23:35:10 2021 GMT
*  expire date: Apr 20 23:35:10 2021 GMT
*  issuer: CN=Fake LE Intermediate X1
*  SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7fe834006400)
> GET / HTTP/2
> Host: books.website.com:8443
> User-Agent: curl/7.54.0
> Accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
< HTTP/2 302
< content-type: text/html; charset=utf-8
< date: Thu, 21 Jan 2021 00:35:50 GMT
< location: http://books.website.com:8443/login?next=%2F
< server: Caddy
< set-cookie: session=eyJfZmxhc2hlcyI6W3siIHQiOlsibWVzc2FnZSIsIlBsZWFzZSBsb2cgaW4gdG8gYWNjZXNzIHRoaXMgcGFnZS4iXX1dfQ.YAjMZg.pbqXElkV3zKA7LcCvXppxSm_GtA; HttpOnly; Path=/; SameSite=Lax
< strict-transport-security: max-age=31536000; includeSubDomains
< vary: Cookie
< x-content-type-options: nosniff
< x-frame-options: SAMEORIGIN
< x-xss-protection: 1; mode=block
< content-length: 237
<
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>Redirecting...</title>
<h1>Redirecting...</h1>
* Connection #0 to host books.website.com left intact
<p>You should be redirected automatically to target URL: <a href="/login?next=%2F">/login?next=%2F</a>.  If not click the link.%

And browser access: (after clicking proceed, as presumably the staging issued certificates are not trusted).

Is this a failure at the app level or some issue with reverse proxying to the service?

H̶m̶m̶.̶ ̶F̶o̶l̶l̶o̶w̶ ̶t̶h̶e̶ ̶r̶e̶d̶i̶r̶e̶c̶t̶ ̶w̶i̶t̶h̶ ̶c̶u̶r̶l̶?̶ ̶

c̶u̶r̶l̶ ̶-̶k̶I̶L̶ ̶h̶t̶t̶p̶s̶:̶/̶/̶b̶o̶o̶k̶s̶.̶w̶e̶b̶s̶i̶t̶e̶.̶c̶o̶m̶:̶8̶4̶4̶3̶/̶

Actually, there’s one glaringly obvious issue without even bothering.

< location: http://books.website.com:8443/login?next=%2F

The application shouldn’t be issuing a redirect to HTTP on that port.

Why is it even including a scheme at all? It could have been scheme-agnostic and that wouldn’t be a problem…

the application is linuxserver/calibre-web,

It’s hosted on a http

I thought communication between Caddy and the proxied services could be http? After all, that’s happening on the same host within my lan?

No, the issue is that you’re connecting to Caddy over HTTPS.

Caddy then talks to calibre-web over HTTP, hidden from you, the client. All your communication should be HTTPS.

The application, however, is issuing a redirect to you, the client, to reconnect over HTTP. It’s downgrading your connection.

Worse, it’s trying to do it on the port Caddy’s actually listening to HTTPS on, so it won’t even work. Without special software in the way to help interpret (like Conncept, another project by Matt Holt: GitHub - mholt/caddy-l4: Layer 4 (TCP/UDP) app for Caddy) Caddy can’t handle HTTP connections on a HTTPS port (or vice versa).

When the application issues its redirect, ideally it would direct you to https, because when you follow the redirect you’re still going to talk to Caddy, not directly to the app.

It might work if it directed you to HTTP on port 80, because Caddy could then re-upgrade your connection to HTTPS, although it would be quite inefficient. But redirecting to HTTP on 8443, with your current setup, is not a viable option at all.


To be clear, this issue would most likely occur even if you were operating on port 443. The solution is to somehow configure calibre-web to expect the client’s scheme to be HTTPS, or to otherwise act scheme-agnostically.

1 Like

Well crumbs.

Thank you for the clear explanation, I learned from it.

If I am understanding correctly;

  • Caddy is finally receiving the request as expected when accessing https://app.domain.com:8443.
  • Caddy proxies this traffic by https://app.domain.com:8443 in accordance to the config to the service ip:port via HTTP
  • Calibre-web receives this, signals an http downgrade through Caddy to the Client.
  • Traffic flow is broken because the redirect downgrades to 80, which Caddy upgrades to 443

I’ll have to dig into the calibre-web documentation and see whether this is configurable behavior.

After all it’s my understanding that the app was designed to be deployed as a web-app, so I’m not sure why it’s doing a http redirect.

I need to learn/understand this better, because there’s a few other apps I wanted to host on the same pi that I know do https natively. I wasn’t sure how certificates are handled in those situations when you run a Rproxy in front of them; for emby/jellyfin i have read that they have settings to allow reverse proxy to handle TLS termination.

Hopefully I’m not fully borked here… I maybe should install some random service that’s more widely used and see if i can get Caddy to work with it just to ensure I have everything working.

Looks like you’ve got a pretty good understanding.

Yes, this is somewhat along the lines of what’s happening. But it’s actually worse than what you’ve stated. If it downgraded to 80, Caddy could indeed just re-upgrade to 443 (or rather in your case 8443), and this wouldn’t actually break the application. It would still work, but less than optimally.

Try and connect to any website on the internet via HTTP (not HTTPS!) on port 443. If you find one that works, I will be extremely surprised.

That’s what the app is doing right now, effectively.

I don’t know if it’s configurable, but I did stumble across something interesting while doing some quick searching.

It looks like calibre-web looks for the X-Scheme header to take its cues regarding scheme. Caddy doesn’t set this automatically, so if you do it manually, it might solve the problem.

You can tell Caddy to include this header when sending the request upstream by adding a header_up subdirective to your reverse_proxy. So give this a try:

reverse_proxy 192.168.86.249:8083 {
  header_up X-Scheme https
}

References:
Setup Reverse Proxy · janeczku/calibre-web Wiki · GitHub
reverse_proxy (Caddyfile directive) — Caddy Documentation

1 Like

I’m reading the reverse proxy documentation; I’m not sure I’m getting the caddyfile formatting correctly.

Getting the error:

caddy    | {"level":"info","ts":1611201732.692003,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adapter":"caddyfile"}
caddy    | run: adapting config using caddyfile: /etc/caddy/Caddyfile:9: unrecognized directive: header_up
{
     acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
     email email@gmail.com
}


https://books.website.com:8443 {
        reverse_proxy 192.168.86.249:8083{
                header_up X-Scheme https
        }
        tls {
                issuer acme {
                        disable_tlsalpn_challenge
                }
        }
}

I may have json’d myself silly

There is a missing space here causing the opening brace to be included as part of the upstream address.

That means the header_up subdirective below it is read as though it’s top-level, but there’s no top-level header_up directive, so that’s where the Caddyfile throws in the towel, so to speak.

Add a space, should work fine.

1 Like