Setting reverse proxy from withing docker caddy to localhost service

1. Caddy version (caddy version):

Using docker caddy:latest

2. How I run Caddy:

Docker

a. System environment:

Docker running on Arch Linux

b. Command:

docker-compose up

c. Service/unit/compose file:

$ cat docker-compose.yml
---
version: '3'
services:
  caddy:
    image: caddy:latest
    container_name: caddy
    restart: unless-stopped
    healthcheck:
      disable: true
    ports:
      - 80:80  # Needed for the ACME HTTP-01 challenge.
      - 443:443
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - /appdata/caddy/caddy-config:/config
      - /appdata/caddy/caddy-data:/data
    environment:
      - EMAIL=user@example.com        # The email address to use for ACME registration.
    networks:
      - proxy_net
networks:
  proxy_net:
    driver: bridge

d. My complete Caddyfile or JSON config:

$ cat Caddyfile
# vaultwarden
vaultwarden.artafinde.me:443 {
  log {
    level INFO
    output file /data/vaultwarden.artafinde.me.access.log {
      roll_size 10MB
      roll_keep 10
    }
  }
  tls {$EMAIL}
  encode gzip
  reverse_proxy /notifications/hub vaultwarden:3012
  reverse_proxy vaultwarden:80 {
       header_up X-Real-IP {remote_host}
  }
}

# pastebin
paste.artafinde.me:443 {
  log {
    level INFO
    output file /data/paste.artafinde.me.access.log {
      roll_size 10MB
      roll_keep 10
    }
  }
  tls {$EMAIL}
  encode gzip
  reverse_proxy localhost:8000 {
       header_up X-Real-IP {remote_host}
  }
}

3. The problem I’m having:

As you see from above I have two services which I use caddy to secure over https. The vaultwarden one is reverse proxied OK since it is running in a docker container itself but the pasebin does not and it’s not running inside a docker container.

I suspect the localhost which I used on the reverse_proxy command is referencing the container caddy docker itself and not the actual server host.

Is there a way to reference the network outside the container?

4. Error messages and/or full log output:

5. What I already tried:

6. Links to relevant resources:

Yep, this is correct.
To work around that, you could either add extra_hosts to your docker-compose.yml like so:

      - /appdata/caddy/caddy-data:/data
    environment:
      - EMAIL=user@example.com        # The email address to use for ACME registration.
    networks:
      - proxy_net
+   extra_hosts:
+     - host.docker.internal:host-gateway

networks:
  proxy_net:

Which adds another hostname to /etc/hosts within the caddy container.
With that, you will be able to use that new hostname to reference your actual host docker is running on:

  encode gzip
- reverse_proxy localhost:8000 {
+ reverse_proxy host.docker.internal:8000 {
       header_up X-Real-IP {remote_host}
  }
}

However, you have to make sure your service on the actual host is listening on whatever host.docker.internal resolves to (usually 172.17.0.1 - the docker0 interface).
Meaning, if you configured that service on the host to only listen on 127.0.0.1, you will have to change that.

The alternative would be to run caddy either outside of the container (directly on your host) or with network_mode: host:

        - EMAIL=user@example.com        # The email address to use for ACME registration.
+     network_mode: host
-     networks:
-        - proxy_net
- networks:
-   proxy_net:
-     driver: bridge

The downside here is, that you will have to manually map a port for each Docker service and can’t use your proxy_net. But localhost will refer to the actual hosts’ localhost.

  whoami:
    image: jwilder/whoami
    ## exposes :8000
    ## so we can use `reverse_proxy 127.0.0.1:8000`
    ports:
      - 127.0.0.1:8000:8000
3 Likes

@IndeedNotJames thanks for your reply. I actually tried both approaches with first the extra_hosts but no real luck there (I have a suspicion I messed up my systemd services start ups or daemon-reloads).

The second approach to run caddy docker container on host mode worked :tada:

I will try to actually configure them to run without docker, since caddy exists as a package in Arch Linux - but for now this will do.

2 Likes

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