Remove what is about deploying behind Gitea (closes #209)
check / check (push) Successful in 3m15s

Delete the Gitea compose setup, its document, its two scripts and their
make targets. Documents and tests no longer use Gitea as the example
deployment. The Core Rule Set exclusions for Gitea's false positives in
internal/waf stay, with their comments and tests.

Model: opus-5-5
This commit is contained in:
2026-11-07 02:01:53 +00:00
parent f8676debda
commit 3543a9f616
19 changed files with 87 additions and 1236 deletions
+26 -28
View File
@@ -402,10 +402,10 @@ scrapers that send many requests slowly over hours or days. The hour limit is
the main one.
- Per minute: 120, 2 requests a second. It leaves room for a person opening two
pages at once with an empty cache. A gitea page opened with an empty cache
pages at once with an empty cache. A web app's page opened with an empty cache
loads 20 to 60 files, and a handful once cached.
- Per hour: 1,500. A person reading code in gitea for a whole hour, a page every
20 seconds, makes about 900 requests. A scraper making one request every 2
- Per hour: 1,500. A person reading a site for a whole hour, a page every 20
seconds, makes about 900 requests. A scraper making one request every 2
seconds makes 1,800 an hour, more than the limit.
- Per day: 6,000, four hours at the hour limit. A scraper making one request
every 10 seconds makes 8,640 a day, more than the limit.
@@ -417,7 +417,7 @@ the blocklists. An abuser that trips none of them is not caught.
Some legitimate clients pass the limits:
- An Actions runner asks gitea for work all day and can pass the limits.
- A CI runner asks its code forge for work all day and can pass the limits.
- Everyone behind one shared address, such as an office, shares one client's
limits.
@@ -550,12 +550,11 @@ service's abuse comes from.
By default the Core Rule Set reads the method, the URL with its query string,
and the headers of every request. That is where automated attacks show:
injection in query strings, path traversal, attacks carried in headers,
scanners' user agents. It reads no request body. In front of a code forge such
as gitea, bodies carry what people write and publish, such as issue text and
files saved in the web editor. The Core Rule Set takes the shell commands and
code in them for attacks. The default gives up refusing an attack carried in a
body. The rule files, the limits and the bans still apply to the client that
sends it.
scanners' user agents. It reads no request body. In front of a code forge,
bodies carry what people write and publish, such as issue text and files saved
in the web editor. The Core Rule Set takes the shell commands and code in them
for attacks. The default gives up refusing an attack carried in a body. The rule
files, the limits and the bans still apply to the client that sends it.
- The Core Rule Set skips a path under `SWWAF_WAF_EXEMPT_PATHS`.
- `SWWAF_WAF_PARANOIA_LEVEL` and `SWWAF_WAF_ANOMALY_THRESHOLD` are the Core Rule
@@ -591,15 +590,14 @@ sends it.
data, where binary content such as a git push trips rules written for text. A
body the Core Rule Set cannot parse adds 5 to the score, and so does a
multipart body cut by the limit in the middle of a part's header. Body
inspection suits apps whose forms carry no code; `docs/gitea.md` records what
it refuses in front of gitea.
inspection suits apps whose forms carry no code.
- `SWWAF_TRAP_PATHS` names paths the app never serves and only scanners ask for,
such as `/wp-login.php` in front of gitea. This is the short form of a `path`
rule with the `ban` action, for deployments that mount no rule files. A trap
path is matched whole, without the query, against the path as sent and once
percent-decoded: `/wp-login.php` matches `/wp-login.php?x=1` and
`/%77p-login.php`, and does not match `/wp-login.php/` or
`/blog/wp-login.php`.
such as `/wp-login.php` in front of an app that is not WordPress. This is the
short form of a `path` rule with the `ban` action, for deployments that mount
no rule files. A trap path is matched whole, without the query, against the
path as sent and once percent-decoded: `/wp-login.php` matches
`/wp-login.php?x=1` and `/%77p-login.php`, and does not match `/wp-login.php/`
or `/blog/wp-login.php`.
- `SWWAF_ERROR_BURST_THRESHOLD` counts a client's refusals per minute of these
kinds, and of no other:
- a rule file match;
@@ -609,8 +607,8 @@ sends it.
More than this breaks a limit (see "Bans"). A client trying one attack after
another is refused many times a minute; a person rarely more than a few
times. Answers the app gives are not counted, since they do not tell a
scanner from an ordinary client. In front of gitea, registry and git clients
get `404` and `401` by design, hundreds of times a minute.
scanner from an ordinary client. In front of a code forge, registry and git
clients get `404` and `401` by design, hundreds of times a minute.
`smallwebwaf` changes the Core Rule Set 4.25.0 in six ways, since in front of
gitea it would otherwise refuse ordinary requests. The changes hold in front of
@@ -836,7 +834,7 @@ and the default file.
runs. It reads the files again once the directory has had no change for 2
seconds, so that a file still being written is read whole. A file whose name
starts with `.`, such as an editor's lock file, is not a rule file.
- Files are read in name order (`00-default.rules` before `50-gitea.rules`),
- Files are read in name order (`00-default.rules` before `50-site.rules`),
rules in line order.
- A rule's regex is Go's RE2 syntax. It has no backreferences or lookaround; in
exchange matching time is linear in the input, so no rule can be made to stall
@@ -865,14 +863,15 @@ and the default file.
- The image ships a default file, kept short and limited to patterns that are
wrong for every app, with its path rules anchored at the site root. In front
of gitea, `/.env` is a probe, while
of a code forge, `/.env` is a probe, while
`/<owner>/<repo>/src/branch/main/.env.example` is a file in a repository that
any visitor may open. Anchor the paths of your own `ban` rules at the site
root too. Anything else, such as a rule banning WordPress probes in front of
gitea, belongs in a file the deployer adds to the image `servewaf` runs from,
or mounts. A rule has one target, so a `path` rule applies on every site
behind that `servewaf`. A directory mounted over `SWWAF_RULES_DIR` replaces
the default file; single files mounted into it add to it.
an app that is not WordPress, belongs in a file the deployer adds to the image
`servewaf` runs from, or mounts. A rule has one target, so a `path` rule
applies on every site behind that `servewaf`. A directory mounted over
`SWWAF_RULES_DIR` replaces the default file; single files mounted into it add
to it.
- Rules meant to be edited while `servewaf` runs belong in a mounted directory,
not a mounted file. Many editors save a file by replacing it, and a container
keeps seeing the old one when the file alone is mounted. The lookup database
@@ -1695,8 +1694,7 @@ with no change to upaas. upaas builds the app's Dockerfile and runs the one
container as it runs any app. The traefik labels route to port 8080, and the
`SWRP_` settings go with the app's environment variables. `servewaf` runs in a
container of its own, on a network the app's container can reach, with its state
volume and the directory of any token file. `docs/gitea.md` records what the
defaults do in front of gitea, and `script/gitea-requests` checks those notes.
volume and the directory of any token file.
## Planned, not built