1. The problem I’m having:
I am unable to read client ips. Instrad, I am getting docker’s network IPs.
I have a fairly common simply setup, with caddy running on Docker as reverse-proxy for all domains running inside other docker containers. Some of these domains are publicly accessible (via Cloudflared), whereas others can only be accessed locally (local DNS rewrites with AdGuard Home pointing to the right machine).
I set two “dummy” domains to test the readability of the IPs on both remote and local IPs. I assume that if I hit the Cloudflared domain, I should see my external IP; whereas if I hit the other, I should see my LAN IP.
However, in the first case I see Docker’s Cloudflared network IP (172.23.0.1
), whereas in the second I see caddy’s (both retrieved with docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' caddy
).
Both remote_ip
and client_ip
are the same, as you can see below.
2. Error messages and/or full log output:
{"level":"info","ts":1713640565.0951793,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.23.0.1","remote_port":"47428","client_ip":"172.23.0.1","proto":"HTTP/2.0","method":"GET","host":"ip.{$MY_DOMAIN}","uri":"/","headers":{"Upgrade-Insecure-Requests":["1"],"Sec-Fetch-Mode":["navigate"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8"],"Cookie":[],"Accept-Encoding":["gzip, deflate, br"],"Sec-Fetch-Site":["none"],"Te":["trailers"],"User-Agent":["Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:124.0) Gecko/20100101 Firefox/124.0"],"Accept-Language":["en-GB,en;q=0.5"],"Sec-Fetch-User":["?1"],"Sec-Gpc":["1"],"Dnt":["1"],"Sec-Fetch-Dest":["document"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"ip.{$MY_DOMAIN}"}},"bytes_read":0,"user_id":"","duration":0.000259251,"size":10,"status":200,"resp_headers":{"Server":["Caddy"],"Alt-Svc":["h3=\":443\"; ma=2592000"],"Content-Type":["text/plain; charset=utf-8"],"Content-Length":["10"]}}
3. Caddy version:
v2.7.6 h1:w0NymbG2m9PcvKWsrXO6EEkY9Ru4FJK8uQbYcev1p3A=
4. How I installed and ran Caddy:
Here is my Dockerfile
FROM caddy:builder-alpine AS builder
RUN xcaddy build \
--with github.com/caddy-dns/cloudflare \
--with github.com/fvbommel/caddy-dns-ip-range
FROM caddy:alpine
COPY --from=builder /usr/bin/caddy /usr/bin/caddy
a. System environment:
Apple M2 MacOS Sonoma 14.4.1
colima version 0.6.8
b. Command:
I run docker compose up
c. Service/unit/compose file:
This is my docker-compose.yml
x-default: &default
environment:
- PUID=${DOCKER_PUID}
- PGID=${DOCKER_PGID}
- UMASK=${DOCKER_UMASK}
- TZ=${DOCKER_TZ}
- LOG_LEVEL=ERROR
security_opt:
- no-new-privileges:true
restart: unless-stopped
services:
caddy:
<<: *default
container_name: caddy
image: caddy:builder-alpine
build:
context: ${DOCKER_CONFIG_DIR}/caddy
dockerfile: Dockerfile
volumes:
- ${DOCKER_CONFIG_DIR}/caddy:/data
- ${DOCKER_CONFIG_DIR}/caddy/config/Caddyfile:/etc/caddy/Caddyfile:ro
environment:
- CLOUDFLARE_API_TOKEN=${CLOUDFLARE_API_TOKEN}
- MY_DOMAIN=${MY_DOMAIN}
- MY_EMAIL=${MY_EMAIL}
ports:
- 80:80
- 443:443
networks:
- proxy
networks:
proxy:
driver: bridge
d. My complete Caddy config:
My Caddyfile:
{
email {$MY_EMAIL}
servers {
trusted_proxies dns cloudflared
}
}
(access_log) {
log {
output file /data/log/caddy.log
}
}
(cloudflare) {
tls {
dns cloudflare {$CLOUDFLARE_API_TOKEN}
resolvers 1.1.1.1
}
}
cloudflared-ip.{$MY_DOMAIN} {
templates
respond "{{.RemoteIP}}"
import access_log
import cloudflare
}
ip.{$MY_DOMAIN} {
templates
respond "{{.RemoteIP}}"
import access_log
import cloudflare
}
5. Links to relevant resources:
@francislavoie mentioned this may be due the way Docker implements networking involves a TCP-layer proxy, so all connections’ IP addresses look like they’re coming from the Docker network itself.