How to dynamically reverse_proxy?

Hello! I have a website builder application. Our customers can build their websites using our application. We provide a subdomain each site like 21fsdf3424.mysaasapp.com. Our customers will use their own subdomains or apex domains. Caddy seems like a good solution for this. The on-demand tls and reverse_proxy features are very nice. Let’s say we have a key value store like Redis. Example:

key value
app.customer1.com 21fsdf3424.mysaasapp.com
customer2.com 2656sxf344.mysaasapp.com
subdomain.othercustomer.net 2134d3534s.mysaasapp.com
sync.customer3.org 34qwfz4r32.mysaasapp.com

How can I dynamically proxy them? The ask option in on_demand_tls doesn’t exactly work for this.

You’ll still need to use ask for TLS automation. The ask endpoint is only called when Caddy needs to decide whether it should have a certificate issued. That means it’ll only happen once every couple months for each domain that is known, i.e. initially for issuance, and then for renewals after that. For domains that you reject in the ask, they’ll call your ask endpoint every time. But that’s fine as long as you make sure the ask endpoint is very fast with an O(1) lookup.

For proxying, you can write your own dynamic upstreams provider module to do a lookup in your Redis DB for the upstream address to use based on the incoming hostname.

2 Likes

Is there any example about how I can write dynamic upstreams provider module?

Also this way there needs to be 2 different services: one for on_demand tls ask and the other for dynamic upstreams provider module. 2 separate workloads. Do you have any other advice?

What comes to my mind is: dynamically sending saas app id to a single proxy upstream with a custom header? For example:

{
  on_demand_tls {
    ask checkapp
  }
}


:443 {
  tls {
    on_demand
  }

  reverse_proxy mysaasapp.com {
    header_up X-App-ID ???
    // How to get dinamically App ID from redis
  }
}

Is it possible anything like that? Or better solution?

Yeah, they have totally different purposes.

See the docs:

And see caddy/upstreams.go at master · caddyserver/caddy · GitHub where the existing dynamic upstreams modules are implemented. You’ll just need to swap in your logic for getting the correct upstream in the GetUpstreams function.