Settle the open points of the Ubuntu and nixpkgs image (closes #38)
check / check (push) Successful in 2m26s

ca-certificates, nix-bin and runit come from a dated Ubuntu snapshot.
The snapshot service needs HTTPS and the Ubuntu image has no CA
certificates, so that one install uses those of the Go image, pinned by
digest. ca-certificates is installed by name. The image writes
build-users-group = to /etc/nix/nix.conf so root can build without a
daemon. nixpkgs comes from its release file on releases.nixos.org,
checked by SHA-256, and adds about 200 MiB. runsvinit is archived
upstream and is built at a fixed commit with a go.mod made for the
build. The example run scripts put their code in a main function.

Model: opus-5-5
This commit is contained in:
2026-10-03 23:55:58 +00:00
parent 983192ace3
commit 939ff89fc0
2 changed files with 66 additions and 24 deletions
+9 -4
View File
@@ -291,10 +291,15 @@ stand for the app's own options:
```bash
#!/usr/bin/env bash
set -euo pipefail
sleep 1
exec chpst -u app:app /usr/local/bin/app \
--listen 127.0.0.1:8081 \
--trusted-proxies 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,127.0.0.1/32,::1/128
main() {
sleep 1
exec chpst -u app:app /usr/local/bin/app \
--listen 127.0.0.1:8081 \
--trusted-proxies 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,127.0.0.1/32,::1/128
}
main "$@"
```
- The image's entrypoint, `runsvinit`, has runit start `smallwebwaf` and the app
+57 -20
View File
@@ -1155,13 +1155,26 @@ The image holds:
- Ubuntu 26.04 LTS, the newest long-term support release of Ubuntu, pinned by
digest. The image moves to the next LTS release when that ships.
- Three packages from Ubuntu, `ca-certificates`, `nix-bin` and `runit`,
installed from a dated snapshot of Ubuntu's archive (see "Packages from
Ubuntu" below). The Ubuntu image has no CA certificates, and they come with
`nix-bin` only because a library it uses recommends them, so `ca-certificates`
is installed by name. Without it Nix cannot download packages, and
`smallwebwaf`, unable to reach GeoJS, would count every visitor as coming from
an unknown country.
- Nix, the package manager, from Ubuntu's own `nix-bin` package, and nixpkgs,
the collection of packages Nix installs from, fixed at one commit (see
"Packages from nixpkgs" below). Root uses Nix directly, and no Nix daemon runs
in the container.
- runit, from Ubuntu's own `runit` package, and `runsvinit` as the entrypoint.
Neither Ubuntu nor nixpkgs packages `runsvinit`, so the image builds it from
its source (`github.com/peterbourgon/runsvinit`) at a version fixed by hash.
in the container. Nix run by root expects a group of build users, `nixbld`,
which `nix-bin` does not create, so the image writes `build-users-group =` to
`/etc/nix/nix.conf`, and root's builds then run without build users.
- runit, from Ubuntu's own `runit` package, and `runsvinit` as the entrypoint,
as the owner's code style guide asks for service containers. Neither Ubuntu
nor nixpkgs packages `runsvinit`, so the image builds it from its source
(`github.com/peterbourgon/runsvinit`) at a fixed commit hash. Its repository
is archived and has not changed since 2015, and its last tag is `v2.0.0`. It
has no `go.mod`, which Go needs to build it, so the build writes one; since
`runsvinit` uses only Go's standard library, that file names nothing else.
`runsvinit` starts runit's `runsvdir`, which starts a `runsv` for each
directory under `/etc/service`; each `runsv` runs the `run` script in its
directory, and runs it again whenever it exits. Ubuntu's runit looks for
@@ -1179,8 +1192,9 @@ The image holds:
(`HEALTHCHECK`).
Every `run` script, the app's included, is a bash script that starts with
`#!/usr/bin/env bash` and `set -euo pipefail`, as the owner's code style guide
asks; Ubuntu ships bash.
`#!/usr/bin/env bash` and `set -euo pipefail` and puts its code in a `main`
function, called on its last line, as the owner's code style guide asks; Ubuntu
ships bash.
Beyond its `FROM` line, the app's Dockerfile adds:
@@ -1219,23 +1233,46 @@ with `app.run` beside the Dockerfile:
```bash
#!/usr/bin/env bash
set -euo pipefail
sleep 1
exec chpst -u app:app /usr/local/bin/app \
--listen 127.0.0.1:8081 \
--trusted-proxies 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,127.0.0.1/32,::1/128
main() {
sleep 1
exec chpst -u app:app /usr/local/bin/app \
--listen 127.0.0.1:8081 \
--trusted-proxies 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,127.0.0.1/32,::1/128
}
main "$@"
```
Packages from Ubuntu: the image installs `ca-certificates`, `nix-bin` and
`runit` from Ubuntu's snapshot service, which serves the archive as it was at a
given moment, rather than from the archive itself, whose packages change with
every update. The image's Dockerfile names that moment, in apt's
`--snapshot 20261001T000000Z` form, on both `apt-get update` and
`apt-get install`, so the same Dockerfile always installs the same files, which
apt checks against the archive's signature as usual. 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
file.
Packages from nixpkgs: nixpkgs is fixed at one commit of its newest release
branch, `nixos-26.05` today. The image's Dockerfile names the commit and the
hash of its contents, and the build checks that hash. 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. 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.
branch, `nixos-26.05` today. For each commit of the branch that has passed its
tests, the Nix project publishes a release on `releases.nixos.org`, such as
`nixos-26.05.11045.774debe7a0d1`, and the image takes nixpkgs from that
release's file `nixexprs.tar.xz`, not from a GitHub archive of the commit, whose
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 adds about 200 MiB to the image, 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: