From bb8fa2de56924db28e4eaf9b18bc586d33f1142e Mon Sep 17 00:00:00 2001 From: fab Date: Tue, 28 Jul 2026 12:11:37 +0200 Subject: [PATCH] docs: caddy-waf is registered in Caddy's package registry (#122) The module was claimed on 2026-07-28 at v0.3.5, once the RegisterModule scan fix landed. README.md, docs/installation.md and docs/add-package-guide.md all still told users the install path did not exist and would return HTTP 400. CADDY_MODULE_REGISTRATION.md keeps the root-cause writeup so the &Middleware{} pattern is not reintroduced, and adds maintenance notes. Co-Authored-By: Claude Opus 5 (1M context) --- CADDY_MODULE_REGISTRATION.md | 132 +++++++++++++++++------------------ CHANGELOG.md | 7 +- README.md | 11 ++- docs/README.md | 2 +- docs/add-package-guide.md | 75 ++++++++++---------- docs/installation.md | 12 ++-- 6 files changed, 122 insertions(+), 117 deletions(-) diff --git a/CADDY_MODULE_REGISTRATION.md b/CADDY_MODULE_REGISTRATION.md index ae76d78..fb4ebff 100644 --- a/CADDY_MODULE_REGISTRATION.md +++ b/CADDY_MODULE_REGISTRATION.md @@ -1,85 +1,55 @@ # Caddy Module Registration — Status -Tracks whether `github.com/fabriziosalmi/caddy-waf` is registered in Caddy's +Tracks the registration of `github.com/fabriziosalmi/caddy-waf` in Caddy's package registry, which is what makes the module appear on and installable with `caddy add-package`. -## Current status: NOT REGISTERED +## Current status: REGISTERED -Verified 2026-07-28 against the build service endpoint that `add-package` calls: +Claimed 2026-07-28 at 10:05:52 UTC, at version `v0.3.5`. Verified against the +build service endpoint that `add-package` calls: ```console -$ curl -s "https://caddyserver.com/api/download?p=github.com%2Ffabriziosalmi%2Fcaddy-waf&os=linux&arch=amd64" -{"status_code":400,"error":{"message":"github.com/fabriziosalmi/caddy-waf is not a registered Caddy module package path","id":"aed165cf-9d85-4b97-9b65-c5404988d648"}} +$ curl -s -o caddy -w "HTTP %{http_code} bytes=%{size_download}\n" \ + "https://caddyserver.com/api/download?p=github.com%2Ffabriziosalmi%2Fcaddy-waf&os=linux&arch=amd64" +HTTP 200 bytes=48586914 ``` -Until this returns a build, `caddy add-package github.com/fabriziosalmi/caddy-waf` -fails and users must build with `xcaddy`. See [docs/installation.md](docs/installation.md). - -## Module readiness: verified ready - -The registry validates a package by resolving it from the Go module proxy and -building it. That exact path was reproduced end to end on 2026-07-28 against the -**published** module — not a local `replace` — and it succeeds: +and in the registry index: ```console -$ xcaddy build --with github.com/fabriziosalmi/caddy-waf@v0.3.4 -go: downloading github.com/fabriziosalmi/caddy-waf v0.3.4 -[INFO] Build complete: ./caddy - -$ ./caddy version -v2.11.4 h1:XKxkMTgNSizEvKG6QHue6cAsFOteU2qA61w2tKkCWi0= - -$ ./caddy list-modules | grep waf -http.handlers.waf +$ curl -s "https://caddyserver.com/api/packages?q=caddy-waf" +{ + "path": "github.com/fabriziosalmi/caddy-waf", + "published": "2026-07-28T10:05:52.532759Z", + "listed": true, + "available": true, + "modules": [{"name": "http.handlers.waf", ...}] +} ``` -Checked alongside it: +The module documentation rendered on caddyserver.com is extracted from the +doc comment on the `Middleware` struct in [types.go](types.go). Editing that +comment changes what users read on Caddy's site. -| Requirement | Status | -|---|---| -| Module path matches `go.mod` (`github.com/fabriziosalmi/caddy-waf`) | OK | -| Semantic import versioning (`/vN` suffix required only at v2+; this module is v0.x) | Not applicable | -| Resolvable on `proxy.golang.org` at the latest tag | OK — `v0.3.4` | -| Builds against current Caddy from the proxy | OK — Caddy v2.11.4 | -| Registers module ID `http.handlers.waf` at runtime | OK | -| Cross-compiles for linux/amd64, linux/arm64, windows/amd64 | OK | +## Do not reintroduce `&Middleware{}` -Note that CI builds with `xcaddy build --with github.com/fabriziosalmi/caddy-waf=./`, -a local `replace`. That verifies the working tree but **not** that the published -module resolves and builds from the proxy, which is what the registry does. When -diagnosing a registration failure, always reproduce with `@` rather than `=./`. - -## What is left - -Registration is a web form behind a GitHub login; there is no API for it. - -1. Sign in at . -2. Click **Register package**. -3. Package import path: `github.com/fabriziosalmi/caddy-waf` -4. Version: `v0.3.4` (the field is optional; the registry resolves the latest tag otherwise). -5. Re-run the `curl` above. A `200` with a binary means it is live; a `400` with a - fresh error `id` means it still failed — quote that id when asking the Caddy - maintainers, since it is what lets them find the server-side log. - -## Root cause of the earlier failures — fixed in v0.3.5 - -Registering a package does more than resolve and build the module: the registry -runs a **static analyzer** over the source to discover which Caddy modules the -package registers. That analyzer is deliberately simple, and it only accepts two -forms as the argument to `caddy.RegisterModule`: +Registering a package makes the registry run a **static analyzer** over the +source to discover which Caddy modules it registers. That analyzer is +deliberately simple and accepts only two forms as the argument to +`caddy.RegisterModule`: - a composite literal — `caddy.RegisterModule(Foo{})` - `new()` — `caddy.RegisterModule(new(Foo))` -Anything else fails. Until v0.3.4 this module used: +Until v0.3.4 this module used: ```go caddy.RegisterModule(&Middleware{}) // parses as ast.UnaryExpr -> rejected ``` -`&Middleware{}` is a `*ast.UnaryExpr` wrapping the literal, not a literal, so the -scan aborts and the portal reports the generic: +`&Middleware{}` is a `*ast.UnaryExpr` wrapping the literal, not a literal, so +the scan aborted and the portal reported only: ``` Sorry, something went wrong: @@ -87,21 +57,45 @@ unable to scan modules in package github.com/fabriziosalmi/caddy-waf Please include this error ID if reporting: ``` -That message never names the offending line, which is why the earlier attempts +That message never names the offending line, which is why earlier attempts (error ids `d9ae3bd6-bc8f-4f8a-a0de-dcff0399e7a9` and -`2b782e50-057d-4dac-bbd5-4cd1c1188669`, logged while the module was at v0.0.6) -were never diagnosed. The same failure and its resolution are documented in the -Caddy community thread [Unable to register module in the +`2b782e50-057d-4dac-bbd5-4cd1c1188669`, logged at v0.0.6) went undiagnosed for +so long and were wrongly assumed to be transient server-side faults. The same +failure and its resolution are documented in the Caddy community thread +[Unable to register module in the portal](https://caddy.community/t/unable-to-register-module-in-the-portal/33572), -where Matt Holt identifies the underlying analyzer error: +where Matt Holt quotes the underlying analyzer error: > `unexpected argument to RegisterModule(): &ast.UnaryExpr{...} - expect either composite literal or new()` -**v0.3.5 switches both `caddy.RegisterModule` and `ModuleInfo.New` to `new(Middleware)`.** -The forms are semantically identical — each allocates a zeroed `Middleware` and -yields a pointer — so there is no behavioural change; it only makes the source -legible to the scanner. `Middleware` must stay a pointer here: `CaddyModule` has a -pointer receiver, and the struct carries mutexes that must not be copied. +v0.3.5 switched both `caddy.RegisterModule` and `ModuleInfo.New` to +`new(Middleware)`. The forms are semantically identical — each allocates a +zeroed `Middleware` and yields a pointer — so there is no behavioural change. +The pointer is required either way: `CaddyModule` has a pointer receiver and +`Middleware` carries mutexes that must not be copied. -Do not reintroduce `&Middleware{}` in either place, or registration will break -again on the next version bump. +`TestRegisterModuleArgumentIsScannable` in +[module_registration_test.go](module_registration_test.go) parses the package's +own AST and fails the build if this regresses. Do not delete it. + +## Maintenance + +- **New releases are picked up automatically**; the registry resolves the latest + tag. Use **Rescan** on to force a refresh — + for example after changing the `Middleware` doc comment, since that is what + the module documentation page shows. +- **Verifying a release is installable**, before announcing it: + + ```console + $ xcaddy build --with github.com/fabriziosalmi/caddy-waf@vX.Y.Z + $ ./caddy list-modules | grep waf + http.handlers.waf + ``` + + Use `@vX.Y.Z`, not `=./`. CI builds with `--with github.com/fabriziosalmi/caddy-waf=./`, + a local `replace`, which verifies the working tree but **not** that the + published module resolves and builds from the Go proxy — which is the path the + registry actually exercises. +- **If a future registration or rescan fails**, capture the error `id` verbatim + and quote it when asking the Caddy maintainers; it is what lets them find the + server-side log. The portal message alone is not diagnostic. diff --git a/CHANGELOG.md b/CHANGELOG.md index 52bb5e8..7272813 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,9 +18,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `TestRegisterModuleArgumentIsScannable` — parses the package's own AST and asserts the `caddy.RegisterModule` argument stays a composite literal or `new()`, so the registry constraint cannot silently regress on a future edit. Verified to fail against the v0.3.4 pattern and pass against the fix. ### Changed -- Rewrote `CADDY_MODULE_REGISTRATION.md`, which was stale (referenced v0.0.6 and Caddy v2.9.1) and speculated that the failures were server-side and "may resolve automatically". It now records the verified root cause, the readiness evidence, and the remaining manual step. +- Rewrote `CADDY_MODULE_REGISTRATION.md`, which was stale (referenced v0.0.6 and Caddy v2.9.1) and speculated that the failures were server-side and "may resolve automatically". It now records the verified root cause and the maintenance notes. - Bumped version constant `wafVersion` to `v0.3.5`. +### Registered +With the scan fixed, `github.com/fabriziosalmi/caddy-waf` was claimed in Caddy's package registry on 2026-07-28 at 10:05:52 UTC, at `v0.3.5`. The build service now serves it (`GET /api/download?p=github.com%2Ffabriziosalmi%2Fcaddy-waf` returns a binary instead of HTTP 400), so `caddy add-package github.com/fabriziosalmi/caddy-waf` works and the module is selectable on . `README.md`, `docs/installation.md` and `docs/add-package-guide.md` updated accordingly — they previously documented the install path as unavailable. + +Note the module documentation shown on caddyserver.com is extracted from the doc comment on the `Middleware` struct in `types.go`. + ## [v0.3.4] - 2026-07-28 ### Security diff --git a/README.md b/README.md index b542ad9..fb3bc6b 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,14 @@ xcaddy build --with github.com/fabriziosalmi/caddy-waf=./ ### `caddy add-package` -This module is **not registered** in Caddy's official package registry; `caddy add-package github.com/fabriziosalmi/caddy-waf` will fail with `HTTP 400: ... is not a registered Caddy module package path`. Use one of the build options above. See [`docs/add-package-guide.md`](docs/add-package-guide.md) for details. +The module is registered in Caddy's package registry, so an existing Caddy v2.7+ binary can pull it in without a Go toolchain: + +```bash +caddy add-package github.com/fabriziosalmi/caddy-waf +caddy list-modules | grep waf # expect: http.handlers.waf +``` + +It is also selectable on [caddyserver.com/download](https://caddyserver.com/download). See [`docs/add-package-guide.md`](docs/add-package-guide.md) for version pinning, removal, and when to prefer `xcaddy` instead. --- @@ -176,7 +183,7 @@ A fully annotated example is provided in [`Caddyfile`](Caddyfile) and [`caddyfil | [`docs/scripts.md`](docs/scripts.md) | Helper Python scripts for rule and blacklist generation. | | [`docs/testing.md`](docs/testing.md) | Running the bundled `test.py` suite. | | [`docs/docker.md`](docs/docker.md) | Building and running with Docker / Docker Compose. | -| [`docs/add-package-guide.md`](docs/add-package-guide.md) | Status of `caddy add-package` registration. | +| [`docs/add-package-guide.md`](docs/add-package-guide.md) | Installing with `caddy add-package`. | | [`docs/caddytest.md`](docs/caddytest.md) | The `caddytest.py` traffic-generation tool. | --- diff --git a/docs/README.md b/docs/README.md index d906f10..7603088 100644 --- a/docs/README.md +++ b/docs/README.md @@ -38,7 +38,7 @@ A first-time reader is recommended to follow this sequence: | [testing.md](testing.md) | Running `test.py` against a live WAF. | | [caddytest.md](caddytest.md) | Traffic generator for benchmarks and rule validation. | | [docker.md](docker.md) | Building and running the supplied `Dockerfile` / `docker-compose.yml`. | -| [add-package-guide.md](add-package-guide.md) | Status of `caddy add-package` registration. | +| [add-package-guide.md](add-package-guide.md) | Installing with `caddy add-package`. | ## Bundled rule files diff --git a/docs/add-package-guide.md b/docs/add-package-guide.md index 354e4c4..20f7c4d 100644 --- a/docs/add-package-guide.md +++ b/docs/add-package-guide.md @@ -1,94 +1,89 @@ -# `caddy add-package` — Status and Reference +# `caddy add-package` -> **Important.** This module is **not** registered in Caddy's official package registry at `caddyserver.com`. Attempting to install it with `caddy add-package` returns: -> -> ``` -> Error: download failed: HTTP 400: github.com/fabriziosalmi/caddy-waf is not a registered Caddy module package path -> ``` -> -> Use one of the supported installation methods documented in [installation.md](installation.md) instead: -> -> - [Build with `xcaddy`](installation.md#method-1--build-with-xcaddy-recommended) (recommended) -> - [Quick script](installation.md#method-2--quick-script) -> - [Build from source](installation.md#method-3--build-from-source) +`github.com/fabriziosalmi/caddy-waf` is registered in Caddy's package registry +(since 2026-07-28), so it can be added to an existing Caddy binary without a Go +toolchain. It is also selectable on . -This page is retained as a reference in case the module is registered in the future. Until then, every command shown below will fail. +For registration status and history see +[`CADDY_MODULE_REGISTRATION.md`](../CADDY_MODULE_REGISTRATION.md). -## Prerequisites (if registration ever completes) +## Requirements -- Caddy v2.7 or newer (the `add-package` command was introduced in 2.7). +- Caddy v2.7 or newer (`add-package` was introduced in 2.7). - Network access from the Caddy host to `caddyserver.com`. - Permission to replace the running Caddy binary. -## Hypothetical install +## Install ```bash caddy add-package github.com/fabriziosalmi/caddy-waf ``` -If the registration succeeds, the command would: +This will: 1. Detect the currently running Caddy and its module set. 2. Send a build request to the Caddy build service. -3. Download a new binary that includes the existing modules **plus** `caddy-waf`. -4. Back up the current Caddy binary (deleted unless `--keep-backup` is passed). +3. Download a new binary containing the existing modules **plus** `caddy-waf`. +4. Back up the current binary (deleted unless `--keep-backup` is passed). 5. Replace the Caddy binary in place. Verify: ```bash caddy list-modules | grep waf -# Expected: http.handlers.waf +# expect: http.handlers.waf ``` -## Hypothetical version pinning +## Pin a version ```bash -caddy add-package github.com/fabriziosalmi/caddy-waf@vX.Y.Z +caddy add-package github.com/fabriziosalmi/caddy-waf@v0.3.5 ``` -`vX.Y.Z` is any tag from the [GitHub Releases](https://github.com/fabriziosalmi/caddy-waf/releases) page. +Any tag from the [Releases](https://github.com/fabriziosalmi/caddy-waf/releases) +page works. Without a version the build service uses the latest tag. -## Hypothetical removal +Note that v0.3.4 and earlier carry a high-severity denial-of-service +(GHSA-gfj3-cmff-q8wh); do not pin below v0.3.4. + +## Remove ```bash caddy remove-package github.com/fabriziosalmi/caddy-waf ``` -## Why `add-package` does not work today +## When to build with xcaddy instead -The Caddy build service maintains an allow-list of registered package paths. Until the maintainer of `caddy-waf` registers `github.com/fabriziosalmi/caddy-waf` through `https://caddyserver.com/account/register-package`, the build service refuses requests for it. The registration history and prior error references are tracked in [`CADDY_MODULE_REGISTRATION.md`](../CADDY_MODULE_REGISTRATION.md). - -## Use this instead - -The recommended flow on a host that already has `xcaddy` (and hence Go) installed: +`add-package` replaces a binary in place using a remote build service. Prefer +[`xcaddy`](installation.md#option-1--build-with-xcaddy-recommended) when you +need to build from a fork or an untagged commit, pin the Caddy version itself, +build in an air-gapped environment, or produce reproducible artifacts in CI: ```bash -go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest xcaddy build --with github.com/fabriziosalmi/caddy-waf -./caddy version -./caddy list-modules | grep waf ``` -If Go is not available, run the bundled `install.sh` (see [installation.md](installation.md#method-2--quick-script)) which installs Go and `xcaddy` on first use. - ## Troubleshooting ### `command not found: caddy add-package` -You are running Caddy older than 2.7. Update Caddy and retry — but note the registration warning above still applies. +You are running Caddy older than 2.7. Update Caddy. ### `permission denied` -The new binary cannot replace the existing one. Re-run with `sudo`, or run `add-package` from a directory where the user has write access and copy the resulting binary into place manually. +The new binary cannot replace the existing one. Re-run with `sudo`, or run +`add-package` from a directory the user can write to and move the resulting +binary into place manually. ### `Error: download failed: HTTP 400: ... is not a registered Caddy module package path` -Expected. Use one of the build paths from [installation.md](installation.md). +Check the import path for typos. Go module paths are not URLs, so no `https://` +prefix and no trailing slash. If the path is correct and the error persists, the +registration may have been removed — see +[`CADDY_MODULE_REGISTRATION.md`](../CADDY_MODULE_REGISTRATION.md). ## References -- Caddy command line documentation: +- Caddy command line: - Extending Caddy: - `xcaddy`: -- Module registration tracker: [`CADDY_MODULE_REGISTRATION.md`](../CADDY_MODULE_REGISTRATION.md) diff --git a/docs/installation.md b/docs/installation.md index 8246725..31127a8 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -63,13 +63,17 @@ The `=./` form of `--with` instructs `xcaddy` to use the local checkout rather t ## Method 4 — `caddy add-package` -This module is **not registered** in Caddy's official package registry. Attempting `caddy add-package github.com/fabriziosalmi/caddy-waf` returns: +The module is registered in Caddy's package registry, so an existing Caddy v2.7+ binary can pull it in without a Go toolchain: -``` -Error: download failed: HTTP 400: github.com/fabriziosalmi/caddy-waf is not a registered Caddy module package path +```bash +caddy add-package github.com/fabriziosalmi/caddy-waf ``` -Use Method 1, 2, or 3 above. Background and the registration checklist are in [add-package-guide.md](add-package-guide.md) and [`CADDY_MODULE_REGISTRATION.md`](../CADDY_MODULE_REGISTRATION.md). +This asks the Caddy build service for a binary containing your current module set plus `caddy-waf`, then replaces the binary in place (backing up the old one unless `--keep-backup` is passed). Pin a version with `@v0.3.5` if needed. + +The module is also selectable on . + +See [add-package-guide.md](add-package-guide.md) for the full flow, removal, and troubleshooting. ## Verifying the build