1. Caddy version (caddy version
):
I’m running caddy:2.4.6 (docker image)
2. How I run Caddy:
I’m running a set of services in docker-compose and I wanted to expose one particular service (a web app built with react and served in a container with caddy) and a api (python’s FastAPI) running in another container vía a reverse proxy executed as a container with caddy image.
The api and client are accessible in http://client:8888 and http://server:8000, both in the same docker network as the proxy container.
a. System environment:
- Ubuntu 20.04.4 LTS
- Kernel Version: 5.13.0-39-generic
- Architecture: x86_64
- Docker App (Docker Inc., v0.9.1-beta3)
- Docker Buildx (Docker Inc., v0.8.1-docker)
- Docker Scan (Docker Inc., v0.17.0)
b. Command:
docker-compose up
c. Service/unit/compose file:
version: "3.9"
services:
proxy:
image: caddy:2.4.6
ports:
- "80:80"
- "443:443"
volumes:
- "caddy_data:/data"
- "caddy_config:/config"
- type: bind
source: ./config/Caddyfile
target: /etc/caddy/Caddyfile
read_only: true
depends_on:
- server
- client
client:
image: my-app-react
volumes:
- "client_data:/data"
- "client_config:/config"
# ports:
# - "127.0.0.1:8888:8888"
depends_on:
- server
server:
image: my-backend-server
entrypoint: "python -m server.app"
# ports:
# - "127.0.0.1:8000:8000"
d. My complete Caddyfile or JSON config:
localhost {
# reverse_proxy http://client:8888
handle_path /client* {
basicauth * {
test_c JDJhJDE0JHNVR1ZWci8zRGpLNGZBaVh0NVppZS5BTWQuTS9RTzdGY0ZuNGN3Q2VnT2x3LnhCZ1ZaUUJX
}
reverse_proxy http://client:8888 {
header_up X-Forwarded-Host {host}
header_up Host {upstream_hostport}
header_up X-Real-IP {remote_host}
}
}
handle_path /backend* {
basicauth * {
test_s JDJhJDE0JHNVR1ZWci8zRGpLNGZBaVh0NVppZS5BTWQuTS9RTzdGY0ZuNGN3Q2VnT2x3LnhCZ1ZaUUJX
}
reverse_proxy http://server:8000 {
header_up X-Forwarded-Host {host}
header_up Host {upstream_hostport}
header_up X-Real-IP {remote_host}
}
}
}
Usernames/Passwords are dummy, do not worry
3. The problem I’m having:
I was trying to give two different endpoints vía paths, one for each service (/client and /backend) in order to have different auth credentials for each one of them.
The error/problem I’m facing is that backend works nice and well but client only returns empty responses as only fetches “/” (as seen in docker-compose logs) insted of retrieving static files too (like /static/css/main.b612e82a.css). The client is working well (or so I suppose).
In the logs
4. Error messages and/or full log output:
HTML blank response, no headers, no hard errors.
Excerpt of docker-compose log:
client_1 | 1.6487547796050353e+09 info http.log.access.log0 handled request {"request": {"remote_addr": "192.168.96.3:43232", "proto": "HTTP/1.1", "method": "GET", "host": "client:8888", "uri": "/", "headers": {"X-Forwarded-Proto": ["https"], "Accept-Encoding": ["gzip, deflate, br"], "Upgrade-Insecure-Requests": ["1"], "X-Forwarded-For": ["192.168.96.1"], "User-Agent": ["Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36"], "Sec-Ch-Ua-Mobile": ["?0"], "Sec-Ch-Ua-Platform": ["\"Linux\""], "Sec-Fetch-Mode": ["navigate"], "Sec-Fetch-Site": ["none"], "X-Forwarded-Host": ["localhost"], "X-Real-Ip": ["192.168.96.1"], "Dnt": ["1"], "Sec-Ch-Ua": ["\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"99\", \"Google Chrome\";v=\"99\""], "Sec-Fetch-User": ["?1"], "Accept": ["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"], "Accept-Language": ["en-GB,en;q=0.9"], "Sec-Fetch-Dest": ["document"]}}, "common_log": "192.168.96.3 - - [31/Mar/2022:19:26:19 +0000] \"GET / HTTP/1.1\" 200 846", "user_id": "", "duration": 0.000102318, "size": 846, "status": 200, "resp_headers": {"Etag": ["\"r9mij8ni\""], "Content-Type": ["text/html; charset=utf-8"], "Last-Modified": ["Thu, 31 Mar 2022 19:09:08 GMT"], "Accept-Ranges": ["bytes"], "Content-Length": ["846"], "Server": ["Caddy"]}}
With alternative presented in #5:
client_1 | 1.648754875040305e+09 info http.log.access.log0 handled request {"request": {"remote_addr": "192.168.128.3:57980", "proto": "HTTP/1.1", "method": "GET", "host": "client:8888", "uri": "/", "headers": {"Sec-Fetch-Site": ["none"], "Accept-Encoding": ["gzip, deflate, br"], "Cache-Control": ["max-age=0"], "Sec-Ch-Ua-Platform": ["\"Linux\""], "Sec-Fetch-Mode": ["navigate"], "Accept": ["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"], "Sec-Fetch-Dest": ["document"], "Upgrade-Insecure-Requests": ["1"], "X-Forwarded-Proto": ["https"], "X-Real-Ip": ["192.168.128.1"], "Accept-Language": ["en-GB,en;q=0.9"], "Sec-Ch-Ua": ["\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"99\", \"Google Chrome\";v=\"99\""], "Sec-Fetch-User": ["?1"], "X-Forwarded-Host": ["localhost"], "User-Agent": ["Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36"], "Authorization": ["Basic dGVzdF9jOnRlc3Q="], "Dnt": ["1"], "Sec-Ch-Ua-Mobile": ["?0"], "X-Forwarded-For": ["192.168.128.1"]}}, "common_log": "192.168.128.3 - - [31/Mar/2022:19:27:55 +0000] \"GET / HTTP/1.1\" 200 846", "user_id": "", "duration": 0.002590092, "size": 846, "status": 200, "resp_headers": {"Last-Modified": ["Thu, 31 Mar 2022 19:09:08 GMT"], "Accept-Ranges": ["bytes"], "Content-Length": ["846"], "Server": ["Caddy"], "Etag": ["\"r9mij8ni\""], "Content-Type": ["text/html; charset=utf-8"]}}
client_1 | 1.648754875053717e+09 info http.log.access.log0 handled request {"request": {"remote_addr": "192.168.128.3:57980", "proto": "HTTP/1.1", "method": "GET", "host": "client:8888", "uri": "/static/js/main.ba4e6b81.js", "headers": {"Accept": ["*/*"], "Dnt": ["1"], "Sec-Ch-Ua-Platform": ["\"Linux\""], "Authorization": ["Basic dGVzdF9jOnRlc3Q="], "Referer": ["https://localhost/"], "Sec-Fetch-Site": ["same-origin"], "User-Agent": ["Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36"], "Accept-Language": ["en-GB,en;q=0.9"], "Sec-Ch-Ua-Mobile": ["?0"], "X-Forwarded-For": ["192.168.128.1"], "X-Forwarded-Host": ["localhost"], "X-Real-Ip": ["192.168.128.1"], "Accept-Encoding": ["gzip, deflate, br"], "Sec-Ch-Ua": ["\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"99\", \"Google Chrome\";v=\"99\""], "Sec-Fetch-Dest": ["script"], "Sec-Fetch-Mode": ["no-cors"], "X-Forwarded-Proto": ["https"]}}, "common_log": "192.168.128.3 - - [31/Mar/2022:19:27:55 +0000] \"GET /static/js/main.ba4e6b81.js HTTP/1.1\" 200 606760", "user_id": "", "duration": 0.000559949, "size": 606760, "status": 200, "resp_headers": {"Server": ["Caddy"], "Etag": ["\"r9mij8d06g\""], "Content-Type": ["application/javascript"], "Last-Modified": ["Thu, 31 Mar 2022 19:09:08 GMT"], "Accept-Ranges": ["bytes"], "Content-Length": ["606760"]}}
client_1 | 1.6487548750539007e+09 info http.log.access.log0 handled request {"request": {"remote_addr": "192.168.128.3:57982", "proto": "HTTP/1.1", "method": "GET", "host": "client:8888", "uri": "/static/css/main.b612e82a.css", "headers": {"Accept": ["text/css,*/*;q=0.1"], "Sec-Ch-Ua-Platform": ["\"Linux\""], "Sec-Fetch-Mode": ["no-cors"], "X-Forwarded-For": ["192.168.128.1"], "User-Agent": ["Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36"], "Sec-Ch-Ua-Mobile": ["?0"], "Sec-Fetch-Dest": ["style"], "Sec-Fetch-Site": ["same-origin"], "Referer": ["https://localhost/"], "X-Forwarded-Host": ["localhost"], "Dnt": ["1"], "Sec-Ch-Ua": ["\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"99\", \"Google Chrome\";v=\"99\""], "X-Forwarded-Proto": ["https"], "X-Real-Ip": ["192.168.128.1"], "Accept-Encoding": ["gzip, deflate, br"], "Accept-Language": ["en-GB,en;q=0.9"], "Authorization": ["Basic dGVzdF9jOnRlc3Q="]}}, "common_log": "192.168.128.3 - - [31/Mar/2022:19:27:55 +0000] \"GET /static/css/main.b612e82a.css HTTP/1.1\" 200 1087", "user_id": "", "duration": 0.000127709, "size": 1087, "status": 200, "resp_headers": {"Content-Length": ["1087"], "Server": ["Caddy"], "Etag": ["\"r9mij8u7\""], "Content-Type": ["text/css; charset=utf-8"], "Last-Modified": ["Thu, 31 Mar 2022 19:09:08 GMT"], "Accept-Ranges": ["bytes"]}}
client_1 | 1.6487548756851745e+09 info http.log.access.log0 handled request {"request": {"remote_addr": "192.168.128.3:57980", "proto": "HTTP/1.1", "method": "GET", "host": "client:8888", "uri": "/favicon.ico", "headers": {"Authorization": ["Basic dGVzdF9jOnRlc3Q="], "Sec-Ch-Ua": ["\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"99\", \"Google Chrome\";v=\"99\""], "Sec-Fetch-Mode": ["no-cors"], "Accept-Encoding": ["gzip, deflate, br"], "Sec-Ch-Ua-Mobile": ["?0"], "Sec-Ch-Ua-Platform": ["\"Linux\""], "Sec-Fetch-Dest": ["image"], "Referer": ["https://localhost/"], "Sec-Fetch-Site": ["same-origin"], "X-Forwarded-For": ["192.168.128.1"], "X-Forwarded-Host": ["localhost"], "User-Agent": ["Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36"], "Accept": ["image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8"], "Accept-Language": ["en-GB,en;q=0.9"], "Dnt": ["1"], "X-Real-Ip": ["192.168.128.1"], "X-Forwarded-Proto": ["https"]}}, "common_log": "192.168.128.3 - - [31/Mar/2022:19:27:55 +0000] \"GET /favicon.ico HTTP/1.1\" 200 3870", "user_id": "", "duration": 0.000330509, "size": 3870, "status": 200, "resp_headers": {"Server": ["Caddy"], "Etag": ["\"r9miit2zi\""], "Content-Type": ["image/vnd.microsoft.icon"], "Last-Modified": ["Thu, 31 Mar 2022 19:08:53 GMT"], "Accept-Ranges": ["bytes"], "Content-Length": ["3870"]}}
5. What I already tried:
If I use the reverse proxy that is commented out in the sencond line of the Caddyfile (commenting out the rest of the caddyfile) I got the app in the browser and everithing works fine.
6. Links to relevant resources:
None