Search code examples
nginxdnsreverse-proxycnamecaddy

On Demand TLS and Reverse Proxy Support for Custom Domains


I came into a situation today. Please share your expertise 🙏

I have a project (my-app.com) and one of the features is to generate a status page consisting of different endpoints.

Current Workflow

  1. User login into the system
  2. User creates a status page for one of his sites (e.g.google) and adds different endpoints and components to be included on that page.
  3. System generates a link for a given status page.

For Example. my-app.com/status-page/google

  1. But the user may want to see this page in his custom domain.

For Example. status.google.com

  1. Since this is a custom domain, we need on-demand TLS functionality. For this feature, I used Caddy and is working fine. Caddy is running on our subdomain status.myserver.com and user's custom domain status.google.com has a CNAME to our subdomain status.myserver.com

  2. Besides on-demand TLS, I am also required to do reverse proxy as shown below.

For Example. status.google.com ->(CNAME)-> status.myserver.com ->(REVERSE_PROXY)-> my-app.com/status-page/google

But Caddy supports only protocol, host, and port format for reverse proxy like my-app.com but my requirement is to support reverse proxy for custom page my-app.com/status-page/google. How can I achieve this? Is there a better alternative to Caddy or a workaround with Caddy?

My Current Implementation


Solution

  • You're right, since you can't use a path in a reverse-proxy upstream URL, you'd have to do rewrite the request to include the path first, before initiating the reverse-proxy.

    Additionally, upstream addresses cannot contain paths or query strings, as that would imply simultaneous rewriting the request while proxying, which behavior is not defined or supported. You may use the rewrite directive should you need this.

    So you should be able to use an internal caddy rewrite to add the /status-page/google path to every request. Then you can simply use my-app.com as your Caddy reverse-proxy upstream. This could look like this:

    https:// {
        rewrite * /status-page/google{path}?{query}
        reverse_proxy http://my-app.com
    }
    

    You can find out more about all possible Caddy reverse_proxy upstream addresses you can use here: https://caddyserver.com/docs/caddyfile/directives/reverse_proxy#upstream-addresses

    However, since you probably can't hard-code the name of the status page (/status-page/google) in your Caddyfile, you could set up a script (e.g. at /status-page) which takes a look at the requested URL, looks up the domain (e.g. status.google.com) in your database, and automatically outputs the correct status-page.