The image apps build FROM, with its health check (closes #45)
check / check (push) Failing after 3s
check / check (push) Failing after 3s
The Dockerfile's last stage is now the image of "Deployment" in SPEC.md: Ubuntu 26.04 with ca-certificates, nix-bin and runit from a dated snapshot whose InRelease files are checked by hash, nixpkgs from its release file checked by SHA-256, runsvinit built at a fixed commit, and smallwebwaf as a runit service. smallwebwaf answers /_smallwebwaf/healthz, and `smallwebwaf healthcheck`, which takes no further argument, is the image's HEALTHCHECK. script/example-app builds an app on the image and checks it end to end. The Nix profile comes last on the PATH: first, busybox from nixpkgs replaced runit's own runsvdir and sv. SPEC.md is corrected to match what was built. Model: opus-5-5
This commit was merged in pull request #57.
This commit is contained in:
@@ -1263,14 +1263,19 @@ image's digest does. `apt-get update` keeps the snapshot's `InRelease` files,
|
||||
which apt checks against the archive's signature, in `/var/lib/apt/lists/`; each
|
||||
lists the SHA-256 hash of the package lists it covers, and each package list the
|
||||
hash of every package in it. The Dockerfile also names the SHA-256 hash of each
|
||||
`InRelease` file apt uses, and the build checks them after `apt-get update` and
|
||||
before `apt-get install`, so every package apt installs is checked, through
|
||||
those files, against hashes the Dockerfile names. The snapshot service is
|
||||
reached over HTTPS, and the Ubuntu image has no CA certificates of its own, so
|
||||
this one install uses those of the Go image that `smallwebwaf` is built in,
|
||||
which is pinned by digest too: apt's `Acquire::https::CaInfo` option names that
|
||||
image's CA certificate file, `/etc/ssl/certs/ca-certificates.crt`, copied into
|
||||
the build.
|
||||
of the snapshot's `InRelease` files, and the build checks them after
|
||||
`apt-get update` and before `apt-get install`, so every package apt installs is
|
||||
checked, through those files, against hashes the Dockerfile names.
|
||||
`apt-get update` also fetches the live archive's `InRelease` files into the same
|
||||
directory; their hashes change whenever the archive does, and the install does
|
||||
not use them, so the check leaves them out. The hashes are those of the archive
|
||||
for amd64, and so the image is built for amd64: other architectures use Ubuntu's
|
||||
ports archive, whose `InRelease` files differ. The snapshot service is reached
|
||||
over HTTPS, and the Ubuntu image has no CA certificates of its own, so this one
|
||||
install uses those of the Go image that `smallwebwaf` is built in, which is
|
||||
pinned by digest too: apt's `Acquire::https::CaInfo` option names that image's
|
||||
CA certificate file, `/etc/ssl/certs/ca-certificates.crt`, mounted for that one
|
||||
step.
|
||||
|
||||
Packages from nixpkgs: nixpkgs is fixed at one commit of its newest release
|
||||
branch, `nixos-26.05` today. For each commit of the branch that has passed its
|
||||
@@ -1281,15 +1286,18 @@ bytes can change. The image's Dockerfile names the release and the SHA-256 hash
|
||||
of that file, which the release's page lists, and the build checks the hash
|
||||
before unpacking it. nixpkgs is set up for root under the name `nixpkgs`, so the
|
||||
app's Dockerfile installs a package with `nix-env -iA nixpkgs.<name>`, and
|
||||
whatever it installs is on the `PATH` of every service. Because nixpkgs stays at
|
||||
that commit, an app built on the same `smallwebwaf` image gets the same packages
|
||||
each time it is built. Unpacked, nixpkgs takes about 500 MiB of disk, more on
|
||||
some filesystems such as ZFS, and each package an app installs from it adds its
|
||||
own size, with everything it depends on. A newer commit of the branch, with its
|
||||
security fixes, comes with a newer `smallwebwaf` image, as do Ubuntu's own
|
||||
fixes; an app takes them by changing the digest in its `FROM` line. When nixpkgs
|
||||
makes its next release, every six months, the image moves to that release's
|
||||
branch.
|
||||
whatever it installs is on the `PATH` of every service: the image adds root's
|
||||
Nix profile, `/nix/var/nix/profiles/default/bin`, at the end of the `PATH`,
|
||||
after Ubuntu's own directories, so that no package hides the image's own
|
||||
commands. busybox, for one, brings its own `sv`, which looks for services
|
||||
elsewhere. Because nixpkgs stays at that commit, an app built on the same
|
||||
`smallwebwaf` image gets the same packages each time it is built. Unpacked,
|
||||
nixpkgs takes about 500 MiB of disk, more on some filesystems such as ZFS, and
|
||||
each package an app installs from it adds its own size, with everything it
|
||||
depends on. A newer commit of the branch, with its security fixes, comes with a
|
||||
newer `smallwebwaf` image, as do Ubuntu's own fixes; an app takes them by
|
||||
changing the digest in its `FROM` line. When nixpkgs makes its next release,
|
||||
every six months, the image moves to that release's branch.
|
||||
|
||||
The two processes:
|
||||
|
||||
@@ -1315,12 +1323,15 @@ The two processes:
|
||||
- The container's root filesystem stays writable: runit writes each service's
|
||||
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`, 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.
|
||||
The health check: the image's `HEALTHCHECK` runs `smallwebwaf healthcheck`,
|
||||
which passes while `smallwebwaf` answers `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. traefik
|
||||
sends a container no requests until it shows as healthy, so the check runs every
|
||||
second from the container's start until it first passes, for up to a minute, and
|
||||
every 30 seconds after that. 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
|
||||
@@ -1609,7 +1620,9 @@ holds any token file.
|
||||
- The container image described under "Deployment", with runit and the
|
||||
container's health check. The health check calls `/_smallwebwaf/healthz`,
|
||||
so milestone 2 answers that path, although the other admin endpoints come
|
||||
later.
|
||||
later. The image's `/var/lib/smallwebwaf`, which the `run` script gives to
|
||||
the `smallwebwaf` user, and `/etc/smallwebwaf/rules.d` come with the state
|
||||
files and the rule files.
|
||||
- Milestone 3 and later: the rest of the design, in this order:
|
||||
- static lists, the bans that broken request limits lead to, the ban ledger
|
||||
and the JSON state files with edits taken in while running, exemptions,
|
||||
|
||||
Reference in New Issue
Block a user