How to serve dynamic content for custom domains

1. Caddy version (caddy version):


2. How I run Caddy:

I am using a docker image caddy/caddy:2.2.1-alpine

a. System environment:

This is my docker version 19.03.13-ce

b. Command:

docker run -p 80:80 -p 443:443 -v "${PWD}":/srv/ -v "${PWD}"/Caddyfile:/etc/caddy/Caddyfile -v "${PWD}"/certs:/data -v "${pwd}"/config:/config caddy/caddy:2.2.1-alpine

c. Service/unit/compose file:

I am using docker container 

d. My complete Caddyfile or JSON config:

  on_demand_tls {
    interval 2m
    burst 5

:443 {
        log {
                output stdout
        tls {

        reverse_proxy {
            header_up Host {http.reverse_proxy.upstream.hostport}
            header_up X-Forwarded-For {http.request.remote}
            header_up X-Real-IP {http.reverse-proxy.upstream.address}
            header_up X-Forwarded-Proto {http.request.scheme}
            header_up X-Forwarded-Port {http.request.port}
            header_up X-Forwarded-Host {}

3. The problem I’m having:

The main issue I am having is that the external application does a redirect and my custom domain url changes to the redirected url. I want to user to remain the address they typed in.

for example as client
i go to
i want to serve this the content from my saas application{id}

4. Error messages and/or full log output:

5. What I already tried:

I tried different Caddy file configuration to see what works as shown above.

6. Links to relevant resources:

Hmm, where did you get these from? Did you verify that these lines are actually necessary?

What is the output of curl -v?

Hey Matt,
I dont think they are necessary to be honest and haven’t noticed any difference if leave them out.

This is the curl output after curl -v (i replaced the urls and ip address)

 curl -v
*   Trying
* Connected to ( port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* 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, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-ECDSA-AES256-GCM-SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject:
*  start date: May 25 03:50:33 2021 GMT
*  expire date: Aug 23 03:50:33 2021 GMT
*  subjectAltName: host "" matched cert's ""
*  issuer: C=US; O=Let's Encrypt; CN=R3
*  SSL certificate verify ok.
* 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 0x7fde6400c400)
> GET /g/sqI0tKiVvHT HTTP/2
> Host:
> User-Agent: curl/7.64.1
> Accept: */*
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!
< HTTP/2 302
< cache-control: no-cache, private
< content-type: text/html; charset=UTF-8
< date: Sun, 30 May 2021 05:13:36 GMT
< location:
< server: Caddy
< server: nginx/1.15.8
< set-cookie: laravel_session=4fbp2M3TduOdU5t9HHWRaTDGNrD0aVP7A3uC7a9u; expires=Tue, 01-Jun-2021 17:13:36 GMT; Max-Age=216000; path=/; httponly; samesite=lax
< x-content-type-options: nosniff
< x-frame-options: SAMEORIGIN
< x-frame-options: SAMEORIGIN
< x-robots-tag: none
< x-xss-protection: 1; mode=block
<!DOCTYPE html>
        <meta charset="UTF-8" />
        <meta name="robots" content="noindex,nofollow" />
        <style>                body { background-color: #fff; color: #222; font: 16px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; margin: 0; }
                .container { margin: 30px; max-width: 600px; }
                h1 { color: #dc3545; font-size: 24px; }</style>
                        <div class="container">
                    <h1>Whoops, looks like something went wrong.</h1>
* Connection #0 to host left intact

That’s not the official docker image, use caddy instead. The caddy/caddy image is our CI pipeline target instead. See on Docker Hub

Also, please upgrade! v2.2.1 is pretty old now. v2.4.1 came out last week.

As Matt said, you don’t need these lines. Caddy will set the appropriate headers correctly, automatically.

Try to avoid copy-pasting bits of config you don’t understand.

The redirect must be coming from your nginx server, or from your application. This isn’t a problem with Caddy. Make sure they’re configured to not trigger redirects, or to correctly handle/detect the X-Forwarded-Host header to make any redirects retain the original domain.

It looks like you’re serving a Laravel app from what I can tell (the clue is the set-cookie header). I would recommend to use Caddy instead of Nginx to serve your app. Caddy can easily serve Laravel apps with the php_fastcgi directive, and you would avoid the indirection of having to proxy through another server for your custom domains. Just let Caddy handle it all.

1 Like

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