Milestones 1 and 2: proxy with timeouts and size limits, rate limits, country lists and the image #40
@@ -313,7 +313,12 @@ exec chpst -u app:app /usr/local/bin/app \
|
||||
- Port 8080 is the only one the app must leave free: the health check, the
|
||||
metrics and ban management are all on it, under `/_smallwebwaf/`. The image's
|
||||
health check passes while `smallwebwaf` answers and the app accepts
|
||||
connections.
|
||||
connections. `SWWAF_LISTEN_ADDR` can move `smallwebwaf` to another port, which
|
||||
the app then leaves free instead; the health check follows it, and traefik's
|
||||
labels must point at it. The address part of `SWWAF_LISTEN_ADDR` stays empty
|
||||
(for example `:9000`, never `127.0.0.1:9000`), so `smallwebwaf` keeps
|
||||
listening on every address: traefik reaches it on the container's address, and
|
||||
the health check on `127.0.0.1`.
|
||||
- `smallwebwaf` keeps its state files in `/var/lib/smallwebwaf`. Mount a volume
|
||||
there to keep bans and client history when a deploy replaces the container;
|
||||
without one, it still starts.
|
||||
|
||||
@@ -1170,8 +1170,9 @@ The image holds:
|
||||
- The `smallwebwaf` binary, and a user of its own, `smallwebwaf` (uid and gid
|
||||
65532).
|
||||
- The service directory `/etc/service/smallwebwaf`, whose `run` script waits one
|
||||
second (`sleep 1`), makes `SWWAF_STATE_DIR` belong to the `smallwebwaf` user,
|
||||
and starts `smallwebwaf` as that user with runit's `chpst`.
|
||||
second (`sleep 1`), makes `SWWAF_STATE_DIR` and every file in it belong to the
|
||||
`smallwebwaf` user, and starts `smallwebwaf` as that user with runit's
|
||||
`chpst`.
|
||||
- The directory `/var/lib/smallwebwaf` for the state files, and
|
||||
`/etc/smallwebwaf/rules.d` with the default rule file (see "Rule files").
|
||||
- Port 8080 declared (`EXPOSE 8080`), and the health check described below
|
||||
@@ -1261,18 +1262,24 @@ The two processes:
|
||||
status into its directory under `/etc/service`.
|
||||
|
||||
The health check: the image's `HEALTHCHECK` passes while `smallwebwaf` answers
|
||||
`GET /_smallwebwaf/healthz` on `127.0.0.1:8080` and the app accepts connections
|
||||
at the address in `SWWAF_UPSTREAM_URL`, and fails when either does not. The
|
||||
container therefore shows as healthy only while both processes are up. An app
|
||||
with a health check of its own can replace the image's `HEALTHCHECK` with one
|
||||
that checks both.
|
||||
`GET /_smallwebwaf/healthz` on `127.0.0.1`, at the port in `SWWAF_LISTEN_ADDR`,
|
||||
and the app accepts connections at the address in `SWWAF_UPSTREAM_URL`, and
|
||||
fails when either does not. The container therefore shows as healthy only while
|
||||
both processes are up. An app with a health check of its own can replace the
|
||||
image's `HEALTHCHECK` with one that checks both.
|
||||
|
||||
Ports: `smallwebwaf` listens on port 8080 on every address and on no other port;
|
||||
its health check, metrics and ban management are all on that listener, under
|
||||
`/_smallwebwaf/` (see "Admin endpoints"). The app must leave port 8080 free. It
|
||||
listens on `127.0.0.1:8081` only, so that nothing outside the container reaches
|
||||
it except through `smallwebwaf`: an app that listens on every address can be
|
||||
reached around `smallwebwaf` by anything that reaches the container.
|
||||
`/_smallwebwaf/` (see "Admin endpoints"). `SWWAF_LISTEN_ADDR` may set another
|
||||
port: the image's health check takes its port from that setting, and traefik's
|
||||
port label (`traefik.http.services.<name>.loadbalancer.server.port`) must name
|
||||
the same port, and the app must leave that port free. The address part of
|
||||
`SWWAF_LISTEN_ADDR` stays empty (for example `:9000`, never `127.0.0.1:9000`),
|
||||
so `smallwebwaf` keeps listening on every address: traefik reaches it on the
|
||||
container's address, and the health check on `127.0.0.1`. The app listens on
|
||||
`127.0.0.1:8081` only, so that nothing outside the container reaches it except
|
||||
through `smallwebwaf`: an app that listens on every address can be reached
|
||||
around `smallwebwaf` by anything that reaches the container.
|
||||
|
||||
State: `smallwebwaf` keeps its state files in `/var/lib/smallwebwaf`
|
||||
(`SWWAF_STATE_DIR`), a directory of its own beside the app's data, which the app
|
||||
@@ -1280,13 +1287,21 @@ keeps in directories of its own, such as `/var/lib/app`. Without a volume there,
|
||||
the files live in the container: they survive a restart of the container and are
|
||||
lost when a deploy replaces it. A volume mounted at `/var/lib/smallwebwaf`,
|
||||
named or a host directory, keeps them across deploys; the `run` script of
|
||||
`smallwebwaf` makes it belong to the `smallwebwaf` user, so a host directory
|
||||
mounted there needs no change of owner. It is a volume of its own, separate from
|
||||
the app's, holds a few tens of MiB at most with the defaults (see "Persistent
|
||||
state"), and needs no backup beyond whatever the host already does. The image
|
||||
declares no volume, since every app image built on it would inherit it.
|
||||
Milestone 2 (https://git.eeqj.de/sneak/smallwebwaf/issues/14) writes no state
|
||||
files and needs no volume.
|
||||
`smallwebwaf` makes it and every file in it belong to the `smallwebwaf` user, so
|
||||
a host directory mounted there needs no change of owner, and files an earlier
|
||||
owner left in it can be read and replaced. It is a volume of its own, separate
|
||||
from the app's, holds a few tens of MiB at most with the defaults (see
|
||||
"Persistent state"), and needs no backup beyond whatever the host already does.
|
||||
The image declares no volume, since every app image built on it would inherit
|
||||
it. Milestone 2 (https://git.eeqj.de/sneak/smallwebwaf/issues/14) writes no
|
||||
state files and needs no volume.
|
||||
|
||||
Tokens: a token given as a file (`SWWAF_ADMIN_TOKEN_FILE`,
|
||||
`SWWAF_METRICS_TOKEN_FILE`) is out of the app's reach only while the
|
||||
`smallwebwaf` user alone can read the file. The operator makes the file on the
|
||||
host, owned by uid 65532, the `smallwebwaf` user, with mode `0400`, and mounts
|
||||
the directory that holds it into the container read-only; the container sees the
|
||||
same owner and mode.
|
||||
|
||||
Forwarded headers: the app's TCP peer is `smallwebwaf` on `127.0.0.1`, and the
|
||||
`X-Forwarded-For` the app receives ends with traefik's address, which
|
||||
@@ -1305,7 +1320,8 @@ and runs the one container as it runs any app, with the app's traefik labels,
|
||||
environment variables and volumes. The labels route to port 8080
|
||||
(`traefik.http.services.<name>.loadbalancer.server.port=8080`), any `SWWAF_`
|
||||
settings go with the app's environment variables, and the volume for
|
||||
`/var/lib/smallwebwaf` goes beside the app's own.
|
||||
`/var/lib/smallwebwaf` goes beside the app's own, as does the directory that
|
||||
holds any token file.
|
||||
|
||||
- The endpoints of `smallwebwaf` are reached through traefik like any other
|
||||
request, for example `https://app.example.invalid/_smallwebwaf/metrics` for a
|
||||
@@ -1504,7 +1520,7 @@ settings go with the app's environment variables, and the volume for
|
||||
stops the start. The app starts with the same environment variables as
|
||||
`smallwebwaf`, so it can read a token given as one; a token given as a file
|
||||
that only the `smallwebwaf` user can read (`SWWAF_ADMIN_TOKEN_FILE`,
|
||||
`SWWAF_METRICS_TOKEN_FILE`) is out of the app's reach.
|
||||
`SWWAF_METRICS_TOKEN_FILE`) is out of the app's reach (see "Deployment").
|
||||
- GeoJS, the default lookup source: every new visitor's address goes to a third
|
||||
party, and a swarm of fresh addresses, when lookups peak, is when GeoJS may
|
||||
slow down or block `smallwebwaf`. Keeping answers for 7 days and asking about
|
||||
|
||||
Reference in New Issue
Block a user