Caddy reverse-proxying to port 80 on target container instead of 5055

1. The problem I’m having:

I’m running caddy and overseerr as two separate docker containers connected to the same docker network. Overseerr runs on port 5055. I’m trying to use caddy to reverse proxy requests to my custom subdomain overseerr.unrishable.com to the overseerr container, but am getting a “connection refused” error.

Looking at the error message output, I see that the connection refused error is coming from dial tcp 172.19.0.3:80. This is the IP address of the overseerr container (as shown by docker network inspect caddy), but for some reason it seems to be trying to connect to port 80 on the overseerr container instead of port 5055 as configured in my Caddyfile.

Any help would be greatly appreciated!

2. Error messages and/or full log output:

Caddy logs:

{
  "level":"error",
  "ts":1721709622.0955613,
  "logger":"http.log.error",
  "msg":"dial tcp 172.19.0.3:80: connect: connection refused",
  "request":{
    "remote_ip":"172.71.147.77",
    "remote_port":"17464",
    "client_ip":"172.71.147.77",
    "proto":"HTTP/2.0",
    "method":"GET",
    "host":"overseerr.unrishable.com",
    "uri":"/",
    "headers":{
      "Accept-Encoding":[
        "gzip, br"
      ],
      "Sec-Fetch-Mode":[
        "navigate"
      ],
      "Cf-Connecting-Ip":[
        "172.92.175.140"
      ],
      "Cf-Ipcountry":[
        "US"
      ],
      "X-Forwarded-For":[
        "172.92.175.140"
      ],
      "Accept":[
        "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8"
      ],
      "Upgrade-Insecure-Requests":[
        "1"
      ],
      "Cdn-Loop":[
        "cloudflare"
      ],
      "Cf-Ray":[
        "8a78fdf21bdf306c-SEA"
      ],
      "X-Forwarded-Proto":[
        "https"
      ],
      "Accept-Language":[
        "en-US,en;q=0.5"
      ],
      "Sec-Fetch-Site":[
        "none"
      ],
      "Sec-Fetch-User":[
        "?1"
      ],
      "Cf-Visitor":[
        "{\"scheme\":\"https\"}"
      ],
      "User-Agent":[
        "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
      ],
      "Sec-Fetch-Dest":[
        "document"
      ],
      "Priority":[
        "u=0, i"
      ]
    },
    "tls":{
      "resumed":false,
      "version":772,
      "cipher_suite":4865,
      "proto":"h2",
      "server_name":"overseerr.unrishable.com"
    }
  },
  "duration":0.000621503,
  "status":502,
  "err_id":"gqie98ni9",
  "err_trace":"reverseproxy.statusError (reverseproxy.go:1269)"
}

Output of docker network inspect caddy:

rish@Jade-Shadow:/opt/docker/caddy$ docker network inspect caddy
[
    {
        "Name": "caddy",
        "Id": "97a26334a3f18a77b0abb690cf596319ce3ce959adc312f9634adef630229861",
        "Created": "2024-07-22T15:57:29.311272373-07:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.19.0.0/16",
                    "Gateway": "172.19.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "0e01ef6239011d80ceec63fab76d82a65d1ba2111eb1b976e31b41688930bc97": {
                "Name": "caddy",
                "EndpointID": "aa49381bbc2deb699895145fa3937dc5e9ddf34da4e3c4db1cf8cfcd78f84f7b",
                "MacAddress": "02:42:ac:13:00:02",
                "IPv4Address": "172.19.0.2/16",
                "IPv6Address": ""
            },
            "acf6b954cad7bf06ef8d4a0ab262106a065875eb32c54ec68c1e15b2405373fd": {
                "Name": "overseerr",
                "EndpointID": "6ef095145fbb122913b8a2d3d5757992ddb9e2705816bf2fe76ea81ffe7c1673",
                "MacAddress": "02:42:ac:13:00:03",
                "IPv4Address": "172.19.0.3/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

3. Caddy version:

v2.8.4 h1:q3pe0wpBj1OcHFZ3n/1nl4V4bxBrYoSoab7rL9BMYNk=

4. How I installed and ran Caddy:

Running a docker container using docker-compose with https://github.com/lucaslorentz/caddy-docker-proxy

a. System environment:

Docker with docker-compose on Linux Mint

b. Command:

docker-compose up -d

c. Service/unit/compose file:

version: "3.7"
services:
    caddy:
        image: lucaslorentz/caddy-docker-proxy:ci-alpine
        container_name: caddy
        ports:
            - 80:80
            - 443:443
        environment:
            - CADDY_INGRESS_NETWORKS=caddy
        networks:
            - caddy
        volumes:
            - /var/run/docker.sock:/var/run/docker.sock
            - /opt/caddy/data:/data
            - /opt/caddy/config/Caddyfile:/etc/caddy/Caddyfile
        restart: unless-stopped

networks:
  caddy:
    external: true

d. My complete Caddy config:

tls {
	dns cloudflare {
        api_token {env.CLOUDFLARE_DNS_API_TOKEN}
        zone_token {env.CLOUDFLARE_ZONE_API_TOKEN}
    }
}

{
    email ${USER_EMAIL}
    acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
}

overseerr.unrishable.com {
	reverse_proxy overseerr:5055
}

{
	debug
}

5. Links to relevant resources:

Managed to fix it :woman_facepalming:

My original Overseerr config had a leftover label from the template using port 80:

overseerr:
        image: lscr.io/linuxserver/overseerr:latest
        container_name: overseerr
        volumes:
            - ${MEDIASERVER_CONFIG_ROOT}/overseerr:/config
        ports:
            - 5055:5055
        networks:
            - caddy
        depends_on:
            - radarr
            - radarr4k
            - sonarr
        labels:
            caddy: overseerr.unrishable.com
            caddy.reverse_proxy: "{{upstreams 80}}"

Changing the last line to the below fixed it.

caddy.reverse_proxy: "{{upstreams 5055}}"

Glad you figured it out!

That said, some feedback:

FWIW your Caddyfile as you quoted there is totally messed up:

  • You can’t have more than one global options block, and it should always appear at the top. Merge the debug with the email & acme_ca one.
  • You can’t use the tls directive outside of a site block, it needs to go within your site block (i.e. overseerr.unrishable.com)
  • ${USER_EMAIL} is invalid syntax, the syntax for env vars is {$USER_EMAIL} (i.e. inside the{}`)

Either way, I’m pretty sure your Caddyfile isn’t being used at all because you’re using caddy-docker-proxy which only uses labels for configuration by default. If you wanted to also use a Caddyfile, you’d need to configure CADDY_DOCKER_CADDYFILE_PATH to tell CDP to use it as a base config, appending the config from labels to it.

You don’t need this. What this does is it publishes port 5055 to the host, which means that you’re exposing your overseerr to be accessible separately from Caddy, so if something is able to connect to your server it could bypass HTTPS. Just remove that, let Caddy act as the gateway and connect to it through the Docker network.

2 Likes

Thank you for the feedback, that makes sense! Follow-up question about the port thing - I originally had this running in order to be able to access the service from my server machine without having to go through my custom domain. Do you know if it would be possible to set up an additional proxy for localhost requests to 5055 and send those to the overseerr container as well? Looked into this a bit but not sure quite how to achieve this especially with caddy-docker-proxy using tags to determine routing.

Why not just use your domain? What’s wrong with that?

1 Like

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