Deploy model: listen port, token files, state directory owner (closes #33)
check / check (push) Successful in 2m37s
check / check (push) Successful in 2m37s
SWWAF_LISTEN_ADDR may set another port: the health check takes its port from it, and traefik's port label must name the same one. Its address part stays empty (:9000), so smallwebwaf keeps listening on every address, where traefik and the health check on 127.0.0.1 both reach it. A token file is made on the host owned by uid 65532 with mode 0400 and its directory mounted read-only; through upaas, that directory is one of the app's volume mounts. The run script of smallwebwaf makes the state directory and every file in it belong to the smallwebwaf user. Model: opus-5-5
This commit was merged in pull request #41.
This commit is contained in:
@@ -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
|
- 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
|
metrics and ban management are all on it, under `/_smallwebwaf/`. The image's
|
||||||
health check passes while `smallwebwaf` answers and the app accepts
|
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
|
- `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;
|
there to keep bans and client history when a deploy replaces the container;
|
||||||
without one, it still starts.
|
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
|
- The `smallwebwaf` binary, and a user of its own, `smallwebwaf` (uid and gid
|
||||||
65532).
|
65532).
|
||||||
- The service directory `/etc/service/smallwebwaf`, whose `run` script waits one
|
- The service directory `/etc/service/smallwebwaf`, whose `run` script waits one
|
||||||
second (`sleep 1`), makes `SWWAF_STATE_DIR` belong to the `smallwebwaf` user,
|
second (`sleep 1`), makes `SWWAF_STATE_DIR` and every file in it belong to the
|
||||||
and starts `smallwebwaf` as that user with runit's `chpst`.
|
`smallwebwaf` user, and starts `smallwebwaf` as that user with runit's
|
||||||
|
`chpst`.
|
||||||
- The directory `/var/lib/smallwebwaf` for the state files, and
|
- The directory `/var/lib/smallwebwaf` for the state files, and
|
||||||
`/etc/smallwebwaf/rules.d` with the default rule file (see "Rule files").
|
`/etc/smallwebwaf/rules.d` with the default rule file (see "Rule files").
|
||||||
- Port 8080 declared (`EXPOSE 8080`), and the health check described below
|
- 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`.
|
status into its directory under `/etc/service`.
|
||||||
|
|
||||||
The health check: the image's `HEALTHCHECK` passes while `smallwebwaf` answers
|
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
|
`GET /_smallwebwaf/healthz` on `127.0.0.1`, at the port in `SWWAF_LISTEN_ADDR`,
|
||||||
at the address in `SWWAF_UPSTREAM_URL`, and fails when either does not. The
|
and the app accepts connections at the address in `SWWAF_UPSTREAM_URL`, and
|
||||||
container therefore shows as healthy only while both processes are up. An app
|
fails when either does not. The container therefore shows as healthy only while
|
||||||
with a health check of its own can replace the image's `HEALTHCHECK` with one
|
both processes are up. An app with a health check of its own can replace the
|
||||||
that checks both.
|
image's `HEALTHCHECK` with one that checks both.
|
||||||
|
|
||||||
Ports: `smallwebwaf` listens on port 8080 on every address and on no other port;
|
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
|
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
|
`/_smallwebwaf/` (see "Admin endpoints"). `SWWAF_LISTEN_ADDR` may set another
|
||||||
listens on `127.0.0.1:8081` only, so that nothing outside the container reaches
|
port: the image's health check takes its port from that setting, and traefik's
|
||||||
it except through `smallwebwaf`: an app that listens on every address can be
|
port label (`traefik.http.services.<name>.loadbalancer.server.port`) must name
|
||||||
reached around `smallwebwaf` by anything that reaches the container.
|
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`
|
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
|
(`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
|
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`,
|
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
|
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
|
`smallwebwaf` makes it and every file in it belong to the `smallwebwaf` user, so
|
||||||
mounted there needs no change of owner. It is a volume of its own, separate from
|
a host directory mounted there needs no change of owner, and files an earlier
|
||||||
the app's, holds a few tens of MiB at most with the defaults (see "Persistent
|
owner left in it can be read and replaced. It is a volume of its own, separate
|
||||||
state"), and needs no backup beyond whatever the host already does. The image
|
from the app's, holds a few tens of MiB at most with the defaults (see
|
||||||
declares no volume, since every app image built on it would inherit it.
|
"Persistent state"), and needs no backup beyond whatever the host already does.
|
||||||
Milestone 2 (https://git.eeqj.de/sneak/smallwebwaf/issues/14) writes no state
|
The image declares no volume, since every app image built on it would inherit
|
||||||
files and needs no volume.
|
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
|
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
|
`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
|
environment variables and volumes. The labels route to port 8080
|
||||||
(`traefik.http.services.<name>.loadbalancer.server.port=8080`), any `SWWAF_`
|
(`traefik.http.services.<name>.loadbalancer.server.port=8080`), any `SWWAF_`
|
||||||
settings go with the app's environment variables, and the volume for
|
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
|
- The endpoints of `smallwebwaf` are reached through traefik like any other
|
||||||
request, for example `https://app.example.invalid/_smallwebwaf/metrics` for a
|
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
|
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
|
`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`,
|
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
|
- 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
|
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
|
slow down or block `smallwebwaf`. Keeping answers for 7 days and asking about
|
||||||
|
|||||||
Reference in New Issue
Block a user