1. The problem I’m having:
My infrastructure has a public server running nginx as a reverse proxy.
Then, I have a server with caddy running that redirect the requests to different Docker containers. Caddy itself is running under Docker.
The request is redirected by Caddy itself, not the service. To ensure this, I stopped the service (frontend), and the redirection still persist.
I have no clue why this happen.
The https if managed by NGINX (reverse proxy), and caddy is serving as http in a private network.
2. Error messages and/or full log output:
caddy-1 | {"level":"debug","ts":1748963671.2795904,"logger":"http.handlers.reverse_proxy","msg":"selected upstream","dial":"cacafrontend:80","total_upstreams":1}
caddy-1 | {"level":"debug","ts":1748963671.2806203,"logger":"http.handlers.reverse_proxy","msg":"upstream roundtrip","upstream":"cacafrontend:80","duration":0.000991199,"request":{"remote_ip":"192.168.102.103","remote_port":"50824","client_ip":"redacted_ipv6:9374","proto":"HTTP/1.1","method":"GET","host":"redacted.example.net","uri":"/","headers":{"X-Forwarded-For":["redacted_ipv6:9374, 192.168.102.103"],"Upgrade-Insecure-Requests":["1"],"Accept-Language":["en-US,en;q=0.5"],"Sec-Fetch-Dest":["document"],"Sec-Fetch-Site":["cross-site"],"X-Forwarded-Server":["redacted.example.net"],"X-Real-Ip":["redacted_ipv6:9374"],"X-Forwarded-Proto":["https"],"Sec-Gpc":["1"],"X-Forwarded-Host":["redacted.example.net"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Priority":["u=0, i"],"User-Agent":["Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:138.0) Gecko/20100101 Firefox/138.0"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"],"Sec-Fetch-Mode":["navigate"]}},"headers":{"X-Cache-Lookup":["HIT from proxy1:82"],"Connection":["keep-alive"],"Server":["nginx"],"Date":["Tue, 03 Jun 2025 15:14:32 GMT"],"Content-Type":["text/html"],"Content-Length":["162"],"Location":["https://redacted.example.net/"],"X-Cache":["MISS from proxy1"],"Via":["1.1 proxy1 (squid/5.7)"]},"status":301}
caddy-1 | {"level":"info","ts":1748963671.2810364,"logger":"http.log.access","msg":"handled request","request":{"remote_ip":"192.168.102.103","remote_port":"50824","client_ip":"redacted_ipv6:9374","proto":"HTTP/1.1","method":"GET","host":"redacted.example.net","uri":"/","headers":{"X-Forwarded-Proto":["https"],"Accept-Language":["en-US,en;q=0.5"],"Priority":["u=0, i"],"X-Forwarded-For":["redacted_ipv6:9374"],"Sec-Gpc":["1"],"Sec-Fetch-Dest":["document"],"Sec-Fetch-Site":["cross-site"],"X-Forwarded-Host":["redacted.example.net"],"X-Forwarded-Server":["redacted.example.net"],"Connection":["close"],"User-Agent":["Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:138.0) Gecko/20100101 Firefox/138.0"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Upgrade-Insecure-Requests":["1"],"Sec-Fetch-Mode":["navigate"],"X-Real-Ip":["redacted_ipv6:9374"]}},"bytes_read":0,"user_id":"","duration":0.001466639,"size":162,"status":301,"resp_headers":{"Content-Type":["text/html"],"Content-Length":["162"],"Location":["https://redacted.example.net/"],"X-Cache":["MISS from proxy1"],"Server":["Caddy","nginx"],"X-Cache-Lookup":["HIT from proxy1:82"],"Via":["1.1 proxy1 (squid/5.7)"],"Date":["Tue, 03 Jun 2025 15:14:32 GMT"]}}
caddy-1 | {"level":"debug","ts":1748963671.3094547,"logger":"http.handlers.reverse_proxy","msg":"selected upstream","dial":"cacafrontend:80","total_upstreams":1}
caddy-1 | {"level":"debug","ts":1748963671.3142984,"logger":"http.handlers.reverse_proxy","msg":"upstream roundtrip","upstream":"cacafrontend:80","duration":0.004796872,"request":{"remote_ip":"192.168.102.103","remote_port":"50826","client_ip":"redacted_ipv6:9374","proto":"HTTP/1.1","method":"GET","host":"redacted.example.net","uri":"/","headers":{"Upgrade-Insecure-Requests":["1"],"Sec-Fetch-Mode":["navigate"],"X-Forwarded-Proto":["https"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Gpc":["1"],"X-Real-Ip":["redacted_ipv6:9374"],"User-Agent":["Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:138.0) Gecko/20100101 Firefox/138.0"],"Accept-Language":["en-US,en;q=0.5"],"X-Forwarded-Server":["redacted.example.net"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"],"Priority":["u=0, i"],"X-Forwarded-Host":["redacted.example.net"],"X-Forwarded-For":["redacted_ipv6:9374, 192.168.102.103"],"Sec-Fetch-Dest":["document"],"Sec-Fetch-Site":["cross-site"]}},"headers":{"Content-Length":["162"],"Location":["https://redacted.example.net/"],"X-Cache-Lookup":["HIT from proxy1:82"],"Via":["1.1 proxy1 (squid/5.7)"],"Connection":["keep-alive"],"Content-Type":["text/html"],"Date":["Tue, 03 Jun 2025 15:14:32 GMT"],"X-Cache":["MISS from proxy1"],"Server":["nginx"]},"status":301}
caddy-1 | {"level":"info","ts":1748963671.3143983,"logger":"http.log.access","msg":"handled request","request":{"remote_ip":"192.168.102.103","remote_port":"50826","client_ip":"redacted_ipv6:9374","proto":"HTTP/1.1","method":"GET","host":"redacted.example.net","uri":"/","headers":{"Connection":["close"],"Sec-Fetch-Dest":["document"],"Priority":["u=0, i"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"],"X-Forwarded-Host":["redacted.example.net"],"X-Forwarded-Server":["redacted.example.net"],"X-Forwarded-For":["redacted_ipv6:9374"],"User-Agent":["Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:138.0) Gecko/20100101 Firefox/138.0"],"Accept-Language":["en-US,en;q=0.5"],"Sec-Gpc":["1"],"Upgrade-Insecure-Requests":["1"],"Sec-Fetch-Mode":["navigate"],"X-Real-Ip":["redacted_ipv6:9374"],"X-Forwarded-Proto":["https"],"Sec-Fetch-Site":["cross-site"]}},"bytes_read":0,"user_id":"","duration":0.004950677,"size":162,"status":301,"resp_headers":{"Via":["1.1 proxy1 (squid/5.7)"],"Date":["Tue, 03 Jun 2025 15:14:32 GMT"],"X-Cache":["MISS from proxy1"],"Server":["Caddy","nginx"],"Content-Type":["text/html"],"Content-Length":["162"],"Location":["https://redacted.example.net/"],"X-Cache-Lookup":["HIT from proxy1:82"]}}
3. Caddy version:
caddy 2.10.0 (docker)
4. How I installed and ran Caddy:
Caddy is running under Docker:
caddy:
image: caddy
ports:
- 8080:8080
volumes:
- ./caddy:/etc/caddy
a. System environment:
Debian 12
Docker 28.2.2
b. Command:
c. Service/unit/compose file:
PASTE OVER THIS, BETWEEN THE ``` LINES.
services:
frontend:
init: true
build:
context: ./frontend
target: dev
backend:
init: true
tty: true
build:
context: ./backend
target: dev
environment:
- {redacted}
caddy:
image: caddy:2.7.2
ports:
- 8080:8080
volumes:
- ./caddy:/etc/caddy
d. My complete Caddy config:
{
debug
servers {
trusted_proxies static 192.168.102.103/24 192.168.102.88/24
}
}
http://redacted.example.net:8080 {
log {
output stdout
format console
}
reverse_proxy frontend:80 {
trusted_proxies 192.168.102.103/24 192.168.102.88/24
}
}
http://redactedback.example.net:8080 {
log {
output stdout
format console
}
reverse_proxy backend:5000
}
e. My complete nginx config:
server {
listen 80;
listen [::]:80;
server_name redacted.example.net;
rewrite ^(.*)$ https://$host$1 permanent;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name redacted.example.net;
access_log /var/log/nginx/redacted_front.access.log;
error_log /var/log/nginx/redacted_front.error.log;
location / {
proxy_pass http://192.168.102.39:8080;
proxy_http_version 1.1;
allow all;
}
}
proxy.conf
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_hide_header X-Powered-By;
proxy_intercept_errors on;
proxy_buffering on;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
other headers:
add_header Strict-Transport-Security $hsts_header always;
If you need any other information I can share other configs.
I tested a lot, searched a lot. I know caddy could be used as standalone without nginx and it would be much easier but I don’t want to expose the server publicly.
Thanks