Deploy model: apps build FROM the smallwebwaf image, with smallwebwaf on :8080 in front of the app on 127.0.0.1:8081 #12

Open
opened 2026-09-24 12:09:15 +02:00 by clawbot · 2 comments
Collaborator

Directive (sneak, in chat, 10:00 UTC on 24 September), verbatim:

the recommended deploy methodology for smallwebwaf is going to be to make an application dockerfile be built FROM the smallwebwaf docker file base, and smallwebwaf will listen on :8080 and the web app will listen on 127.0.0.1:8081 and the smallwebwaf default backend will be 127.0.0.1:8081 .

this way each app remains one container, no changes needed for upaas, and applications can harden their containers just by changing the FROM base (and perhaps installing deps).

this will mean we need a service runner like runsvinit or similar because we are moving away from the single-service-as-init container model, but that is ok.

This replaces the deploy shape in SPEC.md. That shape is a separate container between traefik and the app, running one static binary. It includes the docker-compose sidecar from sneak's ruling on sneak/upaas#206. For the service runner, the org style guide already requires runit with runsvinit as the entrypoint of service containers, with sleep 1 at the top of each run script: https://git.eeqj.de/sneak/prompts/src/branch/main/prompts/CODE_STYLEGUIDE.md ("Docker Containers (for services)"). The spec uses that.

Definition of done

SPEC.md and README.md on next describe this as the recommended deploy method. They say:

  • how an app's Dockerfile uses the smallwebwaf image as its base, and the least it must add beyond its FROM line: its binary, any packages, and its runit service. The image's base must therefore allow installing packages.
  • smallwebwaf listens on :8080 and the app on 127.0.0.1:8081. The default backend is http://127.0.0.1:8081, so UPSTREAM_URL is no longer required. The spec also names the ports the app must leave free (today admin 127.0.0.1:9090 and metrics :9100).
  • how runit and runsvinit start both processes, where the app's service goes, and which user each process runs as.
  • what happens when either process exits, and what the container's health check checks.
  • where smallwebwaf's state files live beside the app's own data, and the volume they sit on, for the milestones that write state (milestone 2 writes none).
  • that the app must trust 127.0.0.1 and ::1 for forwarded headers, and how it is set to: in this deploy its TCP peer is smallwebwaf on loopback, and the fleet's default trusted-proxy set, the private ranges, does not include loopback, so an app left at that default sees every visitor as 127.0.0.1 (added 25 September).
  • new defaults for settings that assumed a separate app container, such as INSTANCE_NAME (today the host name in UPSTREAM_URL).
  • that upaas needs no change.
  • an example app Dockerfile built on the image, replacing the docker-compose sidecar example.

The word "sidecar" no longer describes the deploy shape. This is spec and docs only, with no code.

Order

This lands as its own PR to next after #9, so PR 9's rework and review do not restart. It starts once a worker account has room, after webhooker and pixa (sneak's ruling of 24 September).

Model: opus-5-5

Directive (sneak, in chat, 10:00 UTC on 24 September), verbatim: > the recommended deploy methodology for smallwebwaf is going to be to make an application dockerfile be built FROM the smallwebwaf docker file base, and smallwebwaf will listen on :8080 and the web app will listen on 127.0.0.1:8081 and the smallwebwaf default backend will be 127.0.0.1:8081 . > > this way each app remains one container, no changes needed for upaas, and applications can harden their containers just by changing the FROM base (and perhaps installing deps). > > this will mean we need a service runner like runsvinit or similar because we are moving away from the single-service-as-init container model, but that is ok. This replaces the deploy shape in `SPEC.md`. That shape is a separate container between traefik and the app, running one static binary. It includes the docker-compose sidecar from sneak's ruling on https://git.eeqj.de/sneak/upaas/issues/206. For the service runner, the org style guide already requires runit with `runsvinit` as the entrypoint of service containers, with `sleep 1` at the top of each `run` script: https://git.eeqj.de/sneak/prompts/src/branch/main/prompts/CODE_STYLEGUIDE.md ("Docker Containers (for services)"). The spec uses that. ## Definition of done `SPEC.md` and `README.md` on `next` describe this as the recommended deploy method. They say: - how an app's Dockerfile uses the smallwebwaf image as its base, and the least it must add beyond its `FROM` line: its binary, any packages, and its runit service. The image's base must therefore allow installing packages. - smallwebwaf listens on `:8080` and the app on `127.0.0.1:8081`. The default backend is `http://127.0.0.1:8081`, so `UPSTREAM_URL` is no longer required. The spec also names the ports the app must leave free (today admin `127.0.0.1:9090` and metrics `:9100`). - how runit and `runsvinit` start both processes, where the app's service goes, and which user each process runs as. - what happens when either process exits, and what the container's health check checks. - where smallwebwaf's state files live beside the app's own data, and the volume they sit on, for the milestones that write state (milestone 2 writes none). - that the app must trust `127.0.0.1` and `::1` for forwarded headers, and how it is set to: in this deploy its TCP peer is smallwebwaf on loopback, and the fleet's default trusted-proxy set, the private ranges, does not include loopback, so an app left at that default sees every visitor as `127.0.0.1` (added 25 September). - new defaults for settings that assumed a separate app container, such as `INSTANCE_NAME` (today the host name in `UPSTREAM_URL`). - that upaas needs no change. - an example app Dockerfile built on the image, replacing the docker-compose sidecar example. The word "sidecar" no longer describes the deploy shape. This is spec and docs only, with no code. ## Order This lands as its own PR to `next` after https://git.eeqj.de/sneak/smallwebwaf/pulls/9, so PR 9's rework and review do not restart. It starts once a worker account has room, after webhooker and pixa (sneak's ruling of 24 September). Model: opus-5-5
clawbot self-assigned this 2026-09-24 12:09:15 +02:00
Author
Collaborator

Directive (sneak, in chat, 10:13 UTC on 24 September), verbatim:

prefix all smallwebwaf config keys with SWWAF_ given that it will now share a container with the application it protects.

Added to this issue's definition of done: every smallwebwaf setting in SPEC.md and README.md carries the SWWAF_ prefix, for example SWWAF_UPSTREAM_URL, SWWAF_LISTEN_ADDR and SWWAF_ADMIN_TOKEN. The file form of each setting follows the prefixed name, for example SWWAF_ADMIN_TOKEN_FILE. Names are otherwise unchanged, including the ones sneak chose himself in #8.

Model: opus-5-5

Directive (sneak, in chat, 10:13 UTC on 24 September), verbatim: > prefix all smallwebwaf config keys with SWWAF_ given that it will now share a container with the application it protects. Added to this issue's definition of done: every smallwebwaf setting in `SPEC.md` and `README.md` carries the `SWWAF_` prefix, for example `SWWAF_UPSTREAM_URL`, `SWWAF_LISTEN_ADDR` and `SWWAF_ADMIN_TOKEN`. The file form of each setting follows the prefixed name, for example `SWWAF_ADMIN_TOKEN_FILE`. Names are otherwise unchanged, including the ones sneak chose himself in https://git.eeqj.de/sneak/smallwebwaf/issues/8. Model: opus-5-5
Author
Collaborator

Milestone 2, #14, builds the image this spec describes, so this spec lands on next before milestone 2 starts. Two points for it:

  • Milestone 2 writes nothing to disk: its GeoJS answers are kept in memory only (sneak, 25 September; writing them to disk comes in milestone 3 or later). The spec still names smallwebwaf's state directory and the volume it sits on, for the milestones that write state.
  • In this deploy the app's TCP peer is smallwebwaf on 127.0.0.1. The fleet's default trusted-proxy set is the private ranges, which do not include loopback, so an app left at that default ignores X-Forwarded-For and sees every visitor as 127.0.0.1. The spec says how an app is set to trust 127.0.0.1 and ::1.

Model: opus-5-5

Milestone 2, https://git.eeqj.de/sneak/smallwebwaf/issues/14, builds the image this spec describes, so this spec lands on `next` before milestone 2 starts. Two points for it: - Milestone 2 writes nothing to disk: its GeoJS answers are kept in memory only (sneak, 25 September; writing them to disk comes in milestone 3 or later). The spec still names smallwebwaf's state directory and the volume it sits on, for the milestones that write state. - In this deploy the app's TCP peer is smallwebwaf on `127.0.0.1`. The fleet's default trusted-proxy set is the private ranges, which do not include loopback, so an app left at that default ignores `X-Forwarded-For` and sees every visitor as `127.0.0.1`. The spec says how an app is set to trust `127.0.0.1` and `::1`. Model: opus-5-5
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/smallwebwaf#12