From 770ac2be9ed3ff8f647aa3948e1f42d62c97865b Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Wed, 15 Jul 2026 01:08:55 +0200 Subject: [PATCH] fix(self-host): resolve caddy-l4 "unrecognized global option: layer4" error (#10106) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The self-hosted Caddy image relied on the abandoned RussellLuo/caddy-ext/layer4 shim to provide the `layer4` Caddyfile global option, alongside an old (May 2024) pin of mholt/caddy-l4 that predated native Caddyfile support. This combination is fragile: - If the image is ever built without the RussellLuo shim, the `layer4` global option disappears and Caddy fails with "unrecognized global option: layer4" — the reported bug. - Bumping mholt/caddy-l4 to any version with native Caddyfile support makes both modules register `layer4`, panicking at startup with "global option 'layer4' already registered". mholt/caddy-l4 now natively registers the `layer4` global option, so drop the RussellLuo dependency entirely and switch the Caddyfile to the native `route { proxy { upstream ... } }` syntax. The adapted layer4 JSON is byte-identical to the previous output, so runtime behavior is unchanged. Also bump the Caddy base image to 2.11.4 (required by current caddy-l4) and add a path-filtered push trigger so the published `:latest` image is rebuilt whenever the Caddy Dockerfile changes, instead of only on manual dispatch (which is how `:latest` drifted out of sync with the checked-in Caddyfile in the first place). Fixes GIT-903 Co-authored-by: Claude Opus 4.8 (1M context) --- .github/workflows/build-caddy-l4-image.yml | 6 ++++++ Caddyfile | 6 ++++-- docker/DockerfileCaddyL4 | 12 +++++++----- flake.nix | 3 +-- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build-caddy-l4-image.yml b/.github/workflows/build-caddy-l4-image.yml index cafa9f8e47..e4cfdf8112 100644 --- a/.github/workflows/build-caddy-l4-image.yml +++ b/.github/workflows/build-caddy-l4-image.yml @@ -5,6 +5,12 @@ env: name: Build caddy-l4 on: workflow_dispatch: + push: + branches: + - main + paths: + - docker/DockerfileCaddyL4 + - .github/workflows/build-caddy-l4-image.yml permissions: write-all diff --git a/Caddyfile b/Caddyfile index 96c29626f0..b5e5036414 100644 --- a/Caddyfile +++ b/Caddyfile @@ -1,8 +1,10 @@ { layer4 { :25 { - proxy { - to windmill_server:2525 + route { + proxy { + upstream windmill_server:2525 + } } } } diff --git a/docker/DockerfileCaddyL4 b/docker/DockerfileCaddyL4 index eb612cdd46..d2d7bb418f 100644 --- a/docker/DockerfileCaddyL4 +++ b/docker/DockerfileCaddyL4 @@ -1,10 +1,12 @@ -FROM caddy:2.8.4-builder-alpine AS builder +FROM caddy:2.11.4-builder-alpine AS builder +# caddy-l4 natively registers the `layer4` global option used by the Caddyfile. +# Do NOT also add RussellLuo/caddy-ext/layer4: it registers the same global +# option, and building both panics with "global option 'layer4' already registered". RUN xcaddy build \ - --with github.com/mholt/caddy-l4@145ec36251a44286f05a10d231d8bfb3a8192e09 \ - --with github.com/RussellLuo/caddy-ext/layer4@ab1e18cfe426012af351a68463937ae2e934a2a1 + --with github.com/mholt/caddy-l4@bd96009ea7373869bb07d61055554f966b1f5088 -FROM caddy:2.8.4-alpine +FROM caddy:2.11.4-alpine -COPY --from=builder /usr/bin/caddy /usr/bin/caddy \ No newline at end of file +COPY --from=builder /usr/bin/caddy /usr/bin/caddy diff --git a/flake.nix b/flake.nix index 3872ee636f..9062fdb4fd 100644 --- a/flake.nix +++ b/flake.nix @@ -354,8 +354,7 @@ (pkgs.writeScriptBin "wm-caddy" '' cd ./frontend xcaddy build "$@" \ - --with github.com/mholt/caddy-l4@145ec36251a44286f05a10d231d8bfb3a8192e09 \ - --with github.com/RussellLuo/caddy-ext/layer4@ab1e18cfe426012af351a68463937ae2e934a2a1 + --with github.com/mholt/caddy-l4@bd96009ea7373869bb07d61055554f966b1f5088 '') (pkgs.writeScriptBin "wm-setup" '' sqlx database create