Skip to content

extract the root from the site block (get rid of double root directive)#2311

Open
henderkes wants to merge 8 commits intomainfrom
enhancement/optional-root
Open

extract the root from the site block (get rid of double root directive)#2311
henderkes wants to merge 8 commits intomainfrom
enhancement/optional-root

Conversation

@henderkes
Copy link
Copy Markdown
Contributor

I got tired of writing

localhost {
    root /path/to/root
    php_server {
        root /path/to/root
   }
}

so here's my idea of fixing it. This accounts for multiple roots being defined with matchers, but it requires a root /path/to/root directive to be defined, as we have no way of distinguishing multiple parsed root <matcher> <path> directives. Or we can, but we can't figure out which one would be a wildcard root.

@mholt @francislavoie would you be generally open to exporting Helpe::parentBlock (either through a ServerBlock() function, or by capitalizing it like h.State)? Alternatively, is there a way to hook into the site block parsing? I thought we could register our own "root" directive, but passing it back into caddy's other unexported fields would be just as dirty.

@francislavoie
Copy link
Copy Markdown
Contributor

I'm confused, why do all this, can't it just be fetched at runtime via GetVar() like file_server does in Caddy?

@henderkes
Copy link
Copy Markdown
Contributor Author

henderkes commented Mar 26, 2026

I'm confused, why do all this, can't it just be fetched at runtime via GetVar() like file_server does in Caddy?

We need the general root of the site block to start workers at Caddy startup. That's why we need to define it inside the php_server block. But we also need to define it for outside the php_server block so that Caddy's own file serving (such as file_server works.

It's also better for performance, as in that we don't always need to parse the current root anew. When the root is explicitly defined (currently), it resolves it once and then reuses it.

@francislavoie
Copy link
Copy Markdown
Contributor

Hmm, fair enough.

I guess we could add a thing to httpcaddyfile.Helper to carry an arbitrary key-val map, then the root directive parser could fill in the root key in that map with its known value, then later whatever other directives could pull the value. This would rely on Caddyfile parsing it in order tho, but as long as users don't override default directive order or throw root and php_server in a route with root being second, it would work pretty consistently I think.

PR welcome in Caddy if you want to wire that up.

@henderkes
Copy link
Copy Markdown
Contributor Author

Sure, I'll look into exposing a key-value map to retrieve any other values from the site config, too. Thank you!

@henderkes
Copy link
Copy Markdown
Contributor Author

State already exists shared for all instances of a site block, so just need to add a root key to it.

@henderkes
Copy link
Copy Markdown
Contributor Author

henderkes commented Mar 26, 2026

caddyserver/caddy#7594

I changed this branch to use a tagged 2.11.3.rc on my repo to let CI pass, will wait for real 2.11.3 release and then combine this with a go mod bump.

@mholt
Copy link
Copy Markdown
Contributor

mholt commented Mar 26, 2026

What if the root has a placeholder in it though? It can't always be known at startup.

@francislavoie
Copy link
Copy Markdown
Contributor

Placeholder for root almost never happens, if it does it would be an env-var if anything. Not really a relevant concern.

@henderkes
Copy link
Copy Markdown
Contributor Author

What if the root has a placeholder in it though? It can't always be known at startup.

Then it would fail us either way. Php must know the root at provision time.

@mholt
Copy link
Copy Markdown
Contributor

mholt commented Mar 26, 2026

I've seen some configs that use map to set the root dynamically (while keeping it in the site owner's control). Or matchers that simply set it to a different value if some condition is matched.

So, just be aware that if you really do piggy-back on the root directive for your PHP root, it may have a placeholder that can't be evaluated until request-time.

If you truly need the root to be 100% correct in all cases, your own root value is probably ideal.

@henderkes
Copy link
Copy Markdown
Contributor Author

That's a valid heads up. I'll try with using placeholders/env variables and test with that. That's on the consumer of the root field to safety check, though.

If anything this probably means we should keep the root setting for php_server for this case, but at the same time I don't see a situation where

localhost
root {placeholder} # resolves to != /path
php_server {
    root /path
}

wouldn't explode in the users face during runtime. At least this way it could warn (/fail with workers) on startup.

@henderkes henderkes marked this pull request as ready for review March 28, 2026 18:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants