You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
So, my apologies for throwing the somewhat poorly outlined feature request up there, I did it in the midst of other things.
After thinking about it some more it would perhaps make sense to treat this a request to modify caddy global server options as defined here: https://caddyserver.com/docs/caddyfile/options
This would include creating things like custom code snippets that could be reused in other advanced routes, or things such as layer4 apps, trusted proxies and other global server options.
This could be done simply as a caddyfile entry so that users would be able to customize the config based on whatever their current caddy build allows. Doing so would reduce the need for UI work on your part and also increase the flexibility that is offered. Perhaps adding a new section (under the "Configure" section on the left side bar) would seem to be a great place to keep this. Of course offering the option to replicate it across the caddy fleet as well as the standard validation check.
Hopefully this makes sense, let me know if you have any questions.
Thanks for coming back with more detail @BenRLange — that's really helpful.
I dug into this and confirmed something important: adapting a Caddyfile that contains only a global options block (no site addresses) silently drops anything inside the servers { } sub-block — trusted_proxies, listener_wrappers, protocols, etc. never make it into the resulting JSON, because those settings only mean something attached to an actual apps.http.servers.* entry, and CaddyUI generates its own server blocks separately from anything pasted in. So a fully general "paste any global option" box isn't as clean as it sounds — it would silently eat half of what gets pasted into it.
layer4 doesn't have that problem — it's a standalone top-level app (apps.layer4), independent of apps.http.servers, so it survives isolated adaptation just fine.
So here's the scoped plan for v1: a per-server field where you paste your layer4 { ... } Caddyfile block, which CaddyUI sends to that Caddy's own /adapt endpoint and merges the resulting apps.layer4 into the config it pushes — validated the same way everything else is before it's applied, with fleet replication to copy the same block to other nodes. We're also adding the caddy-l4 module to our published Caddy image so it's available out of the box.
Broader "any global server option" support (snippets, trusted_proxies, etc.) is a genuinely harder problem for the reasons above and isn't part of this pass — may revisit separately if there's demand. Building the layer4 piece now.
Added a Layer4 app field to the Caddy server edit form: paste a complete layer4 { ... } Caddyfile block, and CaddyUI adapts it through that server's own admin API and merges only the resulting apps.layer4 subtree into the config it pushes on every sync. A few details that might matter for your setup:
The block is validated against the server's own admin API at save time, so a typo or a Caddy build without the module surfaces immediately rather than breaking the next scheduled sync.
A server running layer4 with no proxy hosts/redirects/routes/certs of its own now syncs normally instead of being refused as "nothing to push."
There's an "Also copy to" picker to replicate the same block across fleet nodes — each target is checked against its own admin API independently, so one node missing the module doesn't block the others.
The published applegater/caddyui-caddy image now ships with caddy-l4 compiled in, so it works out of the box if you're using that image.
As discussed in the thread above, this pass covers layer4 specifically rather than the fully general "any Caddyfile global option" request — I confirmed that a general global-options box would silently drop anything in a servers { } sub-block (trusted_proxies, etc.) since those only mean something attached to an actual http server entry. layer4 doesn't have that problem since it's a standalone top-level app.
Activity
BenRLange commentedon Oct 1, 2026
So, my apologies for throwing the somewhat poorly outlined feature request up there, I did it in the midst of other things.
After thinking about it some more it would perhaps make sense to treat this a request to modify caddy global server options as defined here: https://caddyserver.com/docs/caddyfile/options
This would include creating things like custom code snippets that could be reused in other advanced routes, or things such as layer4 apps, trusted proxies and other global server options.
This could be done simply as a caddyfile entry so that users would be able to customize the config based on whatever their current caddy build allows. Doing so would reduce the need for UI work on your part and also increase the flexibility that is offered. Perhaps adding a new section (under the "Configure" section on the left side bar) would seem to be a great place to keep this. Of course offering the option to replicate it across the caddy fleet as well as the standard validation check.
Hopefully this makes sense, let me know if you have any questions.
X4Applegate commentedon Oct 5, 2026
Thanks for coming back with more detail @BenRLange — that's really helpful.
I dug into this and confirmed something important: adapting a Caddyfile that contains only a global options block (no site addresses) silently drops anything inside the
servers { }sub-block —trusted_proxies,listener_wrappers,protocols, etc. never make it into the resulting JSON, because those settings only mean something attached to an actualapps.http.servers.*entry, and CaddyUI generates its own server blocks separately from anything pasted in. So a fully general "paste any global option" box isn't as clean as it sounds — it would silently eat half of what gets pasted into it.layer4doesn't have that problem — it's a standalone top-level app (apps.layer4), independent ofapps.http.servers, so it survives isolated adaptation just fine.So here's the scoped plan for v1: a per-server field where you paste your
layer4 { ... }Caddyfile block, which CaddyUI sends to that Caddy's own/adaptendpoint and merges the resultingapps.layer4into the config it pushes — validated the same way everything else is before it's applied, with fleet replication to copy the same block to other nodes. We're also adding thecaddy-l4module to our published Caddy image so it's available out of the box.Broader "any global server option" support (snippets, trusted_proxies, etc.) is a genuinely harder problem for the reasons above and isn't part of this pass — may revisit separately if there's demand. Building the layer4 piece now.
feat(caddy-image): add caddy-l4 module (issue #113)
feat(#113): per-server layer4 app support (#118)
X4Applegate commentedon Oct 5, 2026
Shipped in v2.56.0.
Added a Layer4 app field to the Caddy server edit form: paste a complete
layer4 { ... }Caddyfile block, and CaddyUI adapts it through that server's own admin API and merges only the resultingapps.layer4subtree into the config it pushes on every sync. A few details that might matter for your setup:applegater/caddyui-caddyimage now ships withcaddy-l4compiled in, so it works out of the box if you're using that image.As discussed in the thread above, this pass covers layer4 specifically rather than the fully general "any Caddyfile global option" request — I confirmed that a general global-options box would silently drop anything in a
servers { }sub-block (trusted_proxies, etc.) since those only mean something attached to an actual http server entry. layer4 doesn't have that problem since it's a standalone top-level app.applegater/caddyui:v2.56.0+applegater/caddyui-caddy:v2.56.0(both:latest/:stabletoo)Let us know how it works for your routing setup.