Help needed with `handle` (or `handle_path` ?) and other subdomains and snippets / Caddyfile syntax

1. The problem I’m having:

monitoring.example.com/oauth2/* {
        reverse_proxy 127.0.0.1:4180
}
monitoring.example.com {
        respond "Hello world! (oauth2)"
}
# [...] snippet and subdomains definition, see full config below

This current version is deprecated according to caddy validate :
Path in a site address is deprecated; please use the 'handle' directive instead

but my understanding of the required change does not work :

monitoring.example.com {
       handle_path /oauth2/* {
               reverse_proxy 127.0.0.1:4180
       }
       handle_path / {
               respond "Hello world! (oauth2)"
       }
}
# [...] snippet and subdomains definition, see full config below

This second version gets rid of the caddy validate depreciation warning, but then subdomains do not re-direct correctly, e.g. alertmanager.monitoring.example.com does not reroutes to alertmanager behind, and sticks to the oauth2-proxy page.

2. Error messages and/or full log output:

when using the handle and handle_path, it seems to overwrite other routes, for example
alertmanager.monitoring.example.com or prometheus.monitoring.example.com

3. Caddy version:

v2.10.0

4. How I installed and ran Caddy:

a. System environment:

b. Command:

  PASTE OVER THIS, BETWEEN THE ``` LINES.
  Please use the preview pane to ensure it looks nice.

c. Service/unit/compose file:


[Unit]
Description=Caddy
Documentation=https://caddyserver.com/docs/
After=network.target network-online.target
Requires=network-online.target

[Service]
Type=notify
User=caddy
Group=caddy
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile --force
TimeoutStopSec=5s
LimitNOFILE=1048576
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE

[Install]
WantedBy=multi-user.target

d. My complete Caddy config:

# logs configuration
{
	log main {
		include http.log.access.main
		output file /var/log/caddy/access.log {
                        roll_size 1gb
		        roll_keep 5
		        roll_keep_for 720h
                }
	}
	log none {
		include http.log.access.none
		output discard
		format console
	}
}

# no auth, grafana handles oauth itself, refer to grafana config
grafana.monitoring.example.com {
	log main
        reverse_proxy 127.0.0.1:3000
}

monitoring.example.com/oauth2/* {
        reverse_proxy 127.0.0.1:4180
}
monitoring.example.com {
	respond "Hello world! (oauth2)"
}

#monitoring.example.com {
#	handle_path /oauth2/* {
#		reverse_proxy 127.0.0.1:4180
#	}
#	handle_path / {
#		respond "Hello world! (oauth2)"
#	}
#}

(authenticated_site) {
	log main
        # Requests to /oauth2/* are proxied to oauth2-proxy without authentication.
        # You can't use `reverse_proxy /oauth2/* oauth2-proxy.internal:4180` here
        # because the reverse_proxy directive has lower precedence than the handle directive.
        handle /oauth2/* {
                reverse_proxy 127.0.0.1:4180 {
                        header_up X-Real-IP {remote_host}
                        header_up X-Forwarded-Uri {uri}
                }
        }

        handle {
                forward_auth 127.0.0.1:4180 {
                        uri /oauth2/auth
                        # oauth2-proxy requires the X-Real-IP and X-Forwarded-{Proto,Host,Uri} headers.
                        # The forward_auth directive automatically sets the X-Forwarded-{For,Proto,Host,Method,Uri} headers.
                        header_up X-Real-IP {remote_host}

                        # If needed, you can copy headers from the oauth2-proxy response to the request sent to the upstream.
                        # Make sure to configure the --set-xauthrequest flag to enable this feature.
                        copy_headers X-Auth-Request-User X-Auth-Request-Email

                        # If oauth2-proxy returns a 401 status, redirect the client to the sign-in page.
                        @error status 401
                        handle_response @error {
                                redir * /oauth2/sign_in?rd={scheme}://{host}{uri}
                        }
                }
                reverse_proxy {args[0]} {
                        header_up X-Forwarded-User {http.request.header.X-Auth-Request-User}
                        header_up X-Forwarded-Email {http.request.header.X-Auth-Request-Email}
                        header_up X-Forwarded-Groups {http.request.header.X-Auth-Request-Groups}

                        header_up X-Real-IP {remote_host}
                        header_up Host {host}
                        header_up X-Forwarded-Uri {uri}
                        header_up X-Forwarded-Method {method}
                        header_up X-Auth-Request-User {>X-Auth-Request-User}
                        header_up X-Auth-Request-Email {>X-Auth-Request-Email}
                        header_up X-Scheme {scheme}
                        header_up X-Auth-Request-Redirect {scheme}://{host}{uri}
                  }
        }
     }
# Public endpoint for oauth2-proxy itself
oauth.monitoring.example.com {
	reverse_proxy localhost:4180
}

# Prometheus UI with OAuth2
prometheus.monitoring.example.com {
	import authenticated_site http://127.0.0.1:9090
}

# Alertmanager UI with OAuth2
alertmanager.monitoring.example.com {
	import authenticated_site http://127.0.0.1:9093
}

5. Links to relevant resources:

Is there a reason why you’re using handle_path instead of handle here?

Have you tried this?

monitoring.example.com {
       handle /oauth2/* {
               reverse_proxy 127.0.0.1:4180
       }
       handle {
               respond "Hello world! (oauth2)"
       }
}
# [...] snippet and subdomains definition, see full config below
1 Like

ok, it was this easy :frowning:

Thanks !

(by the way, is there a more Caddy-way to write the provided caddyfile ?
I would gladly contribute to the documentation or the wiki section with this since it took me some times to integrate the various pieces, but it now works correctly and could help others…

1 Like

Yeah, the reason I asked about your use of handle_path vs handle was just to get a better sense of what you’re trying to achieve. Each has its own purpose depending on the use case, and they behave differently.

Honestly, your Caddyfile looks good :+1: