CFSSL behind caddy reverse proxy with subpath rewrite

1. Caddy version (caddy version):

v2.4.6

2. How I run Caddy:

a. System environment:

Ubuntu 21.10, Podman 3.2.1

b. Command:

#!/bin/bash
sudo podman run -d \
	--name=caddy-server \
	--restart=always \
	--mount type=bind,source=/opt/caddy/Caddyfile,target=/etc/caddy/Caddyfile,readonly \
	--mount type=bind,source=/opt/caddy/config,target=/config \
	--mount type=bind,source=/opt/caddy/data,target=/data \
	-p <ipv4>:80:80/tcp \
	-p <ipv4>:443/tcp \
	-p [<ipv6>]:80:80/tcp \
        -p [<ipv6>]:443:443/tcp \
caddy:2-alpine

c. Service/unit/compose file:

I just start it manually

d. My complete Caddyfile or JSON config:

{
	# General Options
	debug
	http_port 80
	https_port 443

	email admin@unb0rnet.tk

	#        acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
	key_type p384
}

gateway.unb0rnet.tk {
	redir /admin /admin/
	reverse_proxy /admin/* 172.16.16.1:9090

	redir /pki-ecc /pki-ecc/
	handle_path /pki-ecc/* {
		reverse_proxy 172.16.16.1:8888 {
			header_up Host {host}
			header_up X-Real-IP {remote_host}
		}
	}
}

3. The problem I’m having:

I want to set up Caddy as a reverse proxy for my services (cockpit running on the host itself and several containers running in podman)
My cockpit runs fine with this configuration, and of course it waits root to be on /admin path.
My container services (cfssl Web UI) do not work, they give me just a blank space with web page name in browser. And browser returns me an error about invalid MIME for .js script.
It looks like there is no way to switch web root for cfssl, hence this handle_path statement is used.

4. Error messages and/or full log output:

Log for request:

{"level":"debug","ts":1646479682.2201414,"logger":"http.handlers.rewrite","msg":"rewrote request","request":{"remote_addr":"94.233.118.167:54420","proto":"HTTP/2.0","method":"GET","host":"gateway.unb0rnet.tk","uri":"/pki-ecc/","headers":{"Accept-Language":["en-US,en;q=0.5"],"Cookie":["theme_cookie=dark-theme; size_cookie=15; cockpit=dj0yO2s9YzYzYzNiNzYxNDdhNTg2YWY4NmZiMjAxYzY3ZTA2NGZhNDBiMDdjNmJlMWVkNzNlMjhiYjU5N2ZlY2I3ZjUwNw=="],"Upgrade-Insecure-Requests":["1"],"Sec-Fetch-Mode":["navigate"],"Sec-Fetch-User":["?1"],"Te":["trailers"],"User-Agent":["Mozilla/5.0 (X11; Linux x86_64; rv:97.0) Gecko/20100101 Firefox/97.0"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8"],"Accept-Encoding":["gzip, deflate, br"],"Sec-Fetch-Site":["none"],"Pragma":["no-cache"],"Dnt":["1"],"Sec-Fetch-Dest":["document"],"Cache-Control":["no-cache"]},"tls":{"resumed":true,"version":772,"cipher_suite":4865,"proto":"h2","proto_mutual":true,"server_name":"gateway.unb0rnet.tk"}},"method":"GET","uri":"/"}
{"level":"debug","ts":1646479682.220946,"logger":"http.handlers.reverse_proxy","msg":"upstream roundtrip","upstream":"172.16.16.1:8888","duration":0.000615951,"request":{"remote_addr":"94.233.118.167:54420","proto":"HTTP/2.0","method":"GET","host":"gateway.unb0rnet.tk","uri":"/","headers":{"Sec-Fetch-User":["?1"],"Upgrade-Insecure-Requests":["1"],"Accept-Encoding":["gzip, deflate, br"],"Te":["trailers"],"Accept-Language":["en-US,en;q=0.5"],"Sec-Fetch-Mode":["navigate"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8"],"Dnt":["1"],"Sec-Fetch-Dest":["document"],"Cache-Control":["no-cache"],"Cookie":["theme_cookie=dark-theme; size_cookie=15; cockpit=dj0yO2s9YzYzYzNiNzYxNDdhNTg2YWY4NmZiMjAxYzY3ZTA2NGZhNDBiMDdjNmJlMWVkNzNlMjhiYjU5N2ZlY2I3ZjUwNw=="],"Pragma":["no-cache"],"X-Forwarded-For":["94.233.118.167"],"Sec-Fetch-Site":["none"],"X-Real-Ip":["94.233.118.167"],"User-Agent":["Mozilla/5.0 (X11; Linux x86_64; rv:97.0) Gecko/20100101 Firefox/97.0"],"X-Forwarded-Proto":["https"]},"tls":{"resumed":true,"version":772,"cipher_suite":4865,"proto":"h2","proto_mutual":true,"server_name":"gateway.unb0rnet.tk"}},"headers":{"Accept-Ranges":["bytes"],"Content-Length":["639"],"Content-Type":["text/html; charset=utf-8"],"Last-Modified":["Fri, 04 Sep 2020 20:03:56 GMT"],"Date":["Sat, 05 Mar 2022 11:28:02 GMT"]},"status":200}

5. What I already tried:

Opened firewall port 8888 and tried direct communication with container. It works fine.

6. Links to relevant resources:

You don’t need this line, it’s redundant. Caddy passes through the Host header automatically by default.

handle_path isn’t fool-proof. The problem is that if the upstream app uses paths relative to the root in the HTML (for JS/CSS) then there’s not much that can be done to fix it reliably.

This article explains in depth:

I strongly recommend using a subdomain for that service, like pki-ecc.gateway.unb0rnet.tk for example.

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