Caddy not passing header to upstream

1. Caddy version (caddy version):

v2.2.1 h1:Q62GWHMtztnvyRU+KPOpw6fNfeCD3SkwH7SfT1Tgt2c=

2. How I run Caddy:

a. System environment:

Docker version 19.03.11, build 42e35e61f3
docker-compose version 1.17.1, build unknown

b. Command:

sudo docker-compose -f docker-compose-base.yml up

c. Service/unit/compose file:


FROM caddy:2-builder AS builder

RUN xcaddy build \

FROM caddy:2

COPY --from=builder /usr/bin/caddy /usr/bin/caddy

Docker compose file:

version: "3"


    image: "node:12"
    working_dir: /home/node/app
      - ./:/home/node/app
    command: "node serv.js"

      - .env
    build: .
    restart: unless-stopped
      - "80:80"
      - "443:443"
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config


d. My complete Caddyfile or JSON config:


	tls {
		dns route53 {
			max_retries 10

	reverse_proxy {$ELB_HOST} {
		header_up +codomain {host}

	reverse_proxy /app* {$ELB_HOST} {
		header_up +codomain {host}
		header_up +service admin-ui

	reverse_proxy /embed* {$ELB_HOST} {
		header_up +codomain {host} # TODO: remove codomain since host gets passed through
		header_up +service embed

	uri /app/_next* strip_prefix /app
	uri /app/static* strip_prefix /app

	log {
		output stdout

3. The problem I’m having:

For this request https://app.{$WILDCARD_DOMAIN}.com/app/_next/static/runtime/main-87b364dedc78de6f0c78.js no service header get set.

I expect service header to be set to admin-ui for the backend server.

4. Error messages and/or full log output:

These are headers I received in my node app:

  host: 'app.{$WILDCARD_DOMAIN}.com',
  'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:84.0) Gecko/20100101 Firefox/84.0',
  accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
  'accept-encoding': 'gzip, deflate, br',
  'accept-language': 'en-US,en;q=0.5',
  'cache-control': 'max-age=0',
  codomain: 'app.{$WILDCARD_DOMAIN}.com',
  cookie: 'REDACTED',
  te: 'trailers',
  'upgrade-insecure-requests': '1',
  'x-forwarded-for': 'REDACTED IP',
  'x-forwarded-proto': 'https'

5. What I already tried:

It appears it’s matching reverse_proxy with the implicit wildcard due to the uri directive because when I comment out the following, it doesn’t even send traffic to the backend:

	reverse_proxy {$ELB_HOST} {
		header_up +codomain {host}

I’m not sure how to get around that.

6. Links to relevant resources:

You should use handle instead here, so that once you’ve stripped the path prefix, you don’t need to rely on a matcher afterwards for reverse_proxy.

handle /app* {
    uri /app/_next* strip_prefix /app
    reverse_proxy {$ELB_HOST} {
        header_up +codomain {host}
        header_up +service admin-ui

Also if you use handle for one route, I recommend using it for all routes. It’s helpful to keep routes mutually exclusive (so if one is matched, other handle are not run - use one without a matcher as a fallback)

Some additional reading:

1 Like

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