Accessing global config from within a plugin module


I’m curious if there is any easy way for a plugin module to have read access to global Caddy configuration options? For example, a http.hander module “verify_domain” that implements a URL endpoint for use with the on_demand_tls.ask option might be configured like this:

    on_demand_tls {
        ask http://localhost/ask
    order verify_domain last

http:// {
    @ask {
    	host localhost
    	path /ask
        query domain=*
    verify_domain @ask {
        other options

https:// {
	tls {

However it would be a lot more efficient if the module were able to read the global definition for “on_demand_tls.ask” an implement a matcher internally rather than having to re-implement it with matcher directives (especially if the module needs to perform tasks for other request paths).


First, keep in mind that the Caddyfile is only an adapter that produces a JSON config. Run caddy adapt --pretty to see where the ask option is actually located in the config.

What you could do is during provisioning, call ctx.App("tls"), type assert it to caddytls.TLS, then you can grab the config value from tlsApp.Automation.OnDemand.Ask. Keep in mind that Automation or OnDemand may be nil, so you’ll need to check for that.

This isn’t possible in general, it depends whether the app exported those config fields or if they’re computed values stored in unexported struct fields. But in this case, it can be done.

1 Like

Thanks @francislavoie that makes sense and I’ll give it a try (although sounds a little bit hacky!). I was cautious about calling ctx.App() from within Provision() due to the warning in the documentation:

However I’m assuming that it’s “less unsafe” since “tls” is not the parent app of the module?

Yeah, the tls app is a sibling of the http app, of which request handlers are in. It’s safe in this case. The http app does ctx.App("tls") in a few places already.

Perfect @francislavoie looks like it works well. Thanks again!

1 Like

Nah, that’s how it was designed. The App() function gives you the named app, so you can type-assert it and do what you have to do:

But yeah, don’t do it during Provision.

Don’t you mean “don’t do it before Provision”? Provisioning is exactly the point where it should be called.

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