Reverse Proxy to AWS ALB using AWS ACM Wildcard

1. The problem I’m having:

For a specific scenario I would like to add Caddy in front of AWS ALB, high availability of Caddy here is not the most important thing at this point. This way Caddy could generate certificates on demand and do the reverse proxy to the ALB, and then the ALB which has the following rules:

  • Everything that is HTTP redirects to HTTPS
  • And in HTTPS the condition that if the Host Header is equal to *, redirect to the Target Group with Fargate
  • In the default rule, the Host Header condition does not exist and forwards to another Target Group

This can be represented in the drawing below:

Question 1:
Without adding anything in Caddy, I realized that AWS ALB was not “recognizing” the “Host Header” rule, but adding:

header_up Host {host}


header_up Host {http.reverse_proxy.upstream.hostport}

It works, so just to confirm here which would be the most appropriate to use?

Question 2:
Is it possible for Caddy to “skip” certificate generation for * I would just like it to reverse proxy my ALB without generating a certificate since the ALB already has a wildcard attached.

Please let me know if this is possible?


2. Error messages and/or full log output:

3. Caddy version:

v2.7.6 h1:w0NymbG2m9PcvKWsrXO6EEkY9Ru4FJK8uQbYcev1p3A=

4. How I installed and ran Caddy:

a. System environment:

Ubuntu 22.04 LTS

b. Command:

sudo apt update -y
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf '' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf '' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy

c. Service/unit/compose file:

d. My complete Caddy config:

        on_demand_tls {
        interval 5m
        burst 20

https:// {
    tls {
    reverse_proxy {
        header_up Host {host}
        #header_up Host {http.reverse_proxy.upstream.hostport}

* {
    reverse_proxy {
        header_up Host {host}
        #header_up Host {http.reverse_proxy.upstream.hostport}

:80 {
        respond /online "I am healthy" 200

5. Links to relevant resources:

That doesn’t do anything useful at all. Caddy already passes through the original Host header as-is, by default.

This is what you want, but there is a shortcut. See the docs:

For Caddy to accept TLS connections, it needs a valid TLS cert to complete the handshake. You haven’t configured Caddy to use a specific cert, so it will attempt to issue one.

It sounds like you’re looking for TCP proxying instead (to just proxy the TLS bytes as-is, not decrypted), which vanilla Caddy does not do currently. You’d need something like GitHub - mholt/caddy-l4: Layer 4 (TCP/UDP) app for Caddy which unfortunately doesn’t have official Caddyfile support yet.

Much simpler to let Caddy handle all TLS if possible. You can configure Caddy to use the DNS challenge for your * with the route53 plugin to issue a wildcard cert that Caddy can use.

Hi Francis,
Thank you for the response and for your time.

I’ve already used the Route53 plugin, the problem is that sometimes I get errors when renewing wildcards in random ways, for example sometimes it generates and renews without any problem, but other times I’ve seen it “duplicate the values” and not generate , here is an example:

                     "action": "UPSERT",
                     "resourceRecordSet": {
                         "name": "",
                         "type": "TXT",
                         "tTL": 0,
                         "resourceRecords": [
                                 "value": "\"7krYbHv4jhDcfG3REDACTED\""
                                 "value": "\"7krYbHv4jhDcfG3REDACTED\""

But I don’t know whether or not this is a bug in the plugin.

Using Caddy Layer 4 seems to make things more complex at this point.

Anyway, another alternative I have would be for this wildcard not to “go through” Caddy, that is, the DNS does not “point” to Caddy and it does a reverse proxy for the ALB, but rather a direct CNAME from this specific domain to my ALB. Although this makes me have 2 different DNS records, it seems acceptable and works.

Thanks again for the help!

Unfortunately I think that is a bug in the plugin.

Glad you came up with a solution.