Blank page loads when using as a reverse proxy

Hi,

I’m new to Caddy so appreciate any assistance from the community!

I’m planning on introducing Caddy as a reverse proxy on my docker host for internal services. Before introducing LE and certs I wanted to try just using HTTP to ensure I familiar and simplify any debug.

I’ve got Caddy working successfully with HTTP to a whoami container, but any other services I attempt to configure and reach through the reverse proxy just return a blank browser.

My understanding is that Caddy will route to the containers by using the hostname configured within the caddy network (caddy_net in my deployment).

1. Caddy version (caddy version):

v2.4.6 h1:HGkGICFGvyrodcqOOclHKfvJC0qTU7vny/7FhYp9hNw=

2. How I run Caddy:

a. System environment:

Caddy is running on a Debian 10 VM with docker running.
Docker engine 20.10.12
Docker compose version 1.29.2

c. Service/unit/compose file:

I’m currently using docker-compose to deploy Caddy, whoami and heimdall (which is an example of a container experiencing the blank page loading)

caddy-docker-compose.yml

version: "3.7"
services:

  caddy:
    image: caddy
    container_name: caddy
    hostname: caddy
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    environment:
      MY_DOMAIN
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - ./data:/data
      - ./config:/config

networks:
  default:
    external:
      name: $DOCKER_MY_NETWORK

whoami-docker-compose.yml

version: "3.7"
services:

  whoami:
    image: "containous/whoami"
    container_name: "whoami"
    hostname: "whoami"

networks:
  default:
    external:
      name: $DOCKER_MY_NETWORK

Heimdall-docker-compose.yml

version: "3.7"
services:
  heimdall:
    image: lscr.io/linuxserver/heimdall
    container_name: heimdall2
    hostname: heimdall
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Europe/London
    volumes:
      - /home/matt/docker/heimdall:/config
    ports:
      - 880:80
      - 4443:443
    restart: unless-stopped

networks:
  default:
    external:
      name: $DOCKER_MY_NETWORK

Env

MY_DOMAIN=arches.leymanit.co.uk
DOCKER_MY_NETWORK=caddy_net

d. My complete Caddyfile or JSON config:

http://whoami.{$MY_DOMAIN} {
    reverse_proxy whoami:80
}

http://jackett.{MY_DOMAIN} {
    reverse_proxy jackett:9117
}

http://dashboard.{MY_DOMAIN} {
    reverse_proxy heimdall:80
}

3. The problem I’m having:

The only container that works successfully is whoami. When I try to access any other container via HTTP, the browser displays a blank page. Curl indicates I get a 200OK but the content length is 0.

curl -v dashboard.arches.leymanit.co.uk
*   Trying 192.168.0.101...
* TCP_NODELAY set
* Connected to dashboard.arches.leymanit.co.uk (192.168.0.101) port 80 (#0)
> GET / HTTP/1.1
> Host: dashboard.arches.leymanit.co.uk
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: Caddy
< Date: Sun, 20 Feb 2022 21:07:46 GMT
< Content-Length: 0
<
* Connection #0 to host dashboard.arches.leymanit.co.uk left intact
* Closing connection 0

4. Error messages and/or full log output:

caddy    | {"level":"info","ts":1645391588.6524658,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adapter":"caddyfile"}
caddy    | {"level":"warn","ts":1645391588.6540985,"msg":"input is not formatted with 'caddy fmt'","adapter":"caddyfile","file":"/etc/caddy/Caddyfile","line":2}
caddy    | {"level":"info","ts":1645391588.6554434,"logger":"admin","msg":"admin endpoint started","address":"tcp/localhost:2019","enforce_origin":false,"origins":["[::1]:2019","127.0.0.1:2019","localhost:2019"]}
caddy    | {"level":"info","ts":1645391588.6556406,"logger":"http","msg":"server is listening only on the HTTP port, so no automatic HTTPS will be applied to this server","server_name":"srv0","http_port":80}
caddy    | {"level":"info","ts":1645391588.656193,"msg":"autosaved config (load with --resume flag)","file":"/config/caddy/autosave.json"}
caddy    | {"level":"info","ts":1645391588.6562622,"msg":"serving initial configuration"}
caddy    | {"level":"info","ts":1645391588.6565893,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0xc000535dc0"}
caddy    | {"level":"info","ts":1645391588.656664,"logger":"tls","msg":"cleaning storage unit","description":"FileStorage:/data/caddy"}
caddy    | {"level":"info","ts":1645391588.6567392,"logger":"tls","msg":"finished cleaning storage units"}

5. What I already tried:

The destination containers can ping Caddy.

I’ve tried using the exposed port used by heimdall (880) within the Caddyfile.

I can wget from caddy towards heimdall:80, and index.html is downloaded.

/srv # wget heimdall:80
Connecting to heimdall:80 (172.28.0.2:80)
saving to 'index.html'
index.html           100% |***********************************************************************************************************************************|   147  0:00:00 ETA
'index.html' saved

The docker host can resolve the full external hostname (dashboard.arches.leymanit.co.uk) as this is served by local DNS.

I’ve looked at the other examples in the forum of blank pages and none seem to be applicable to my scenario.

Thanks in advance! Hope someone can point out what I’m missing here as I’m a little unclear! :slight_smile:

Hah – the problem is you used {MY_DOMAIN} instead of {$MY_DOMAIN} (missing $) for those two site addresses, so Caddy doesn’t match those domains since you technically didn’t configure it to handle dashboard.arches.leymanit.co.uk

You definitely need to use the port internal to the docker network, not the one you bind to the host machine.

You can probably remove those ports lines from your other containers once you have it sorted, they should only be reachable via Caddy (to make sure requests always come over HTTPS).

2 Likes

Thanks for your help. A case missing the thing staring me in the face!

Out of interest, why doesn’t Caddy return a 404 or another appropriate response code if unable to match the domain?

404 means page not found. In this case the page wasn’t not found because no page was looked up. The server was simply not configured to handle that request with anything, so the default response is 200.

1 Like

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