Files
felhom.eu/documentation/audits/day-2026-10-08/r762

R-762 (wger's real web server: gunicorn with 2 workers): 2026-10-08 day, Part D

Status: the bench half is done. The 9202 half is NOT done, so nothing was committed to the catalog. To reach 9202, the drill catalog had to be brought up to date and wger un-hidden in it (wger is lifecycle: hidden, and the controller refuses to deploy a hidden app, router.go L461). The permission check refused that write („Modify Shared Resources"). The brief says a refusal stops the item, so it stopped there. The drill repo, 9202's catalog setting and the live catalog were not changed. app-catalog-felhom.eu is clean at 32d1346.

The definition tested

definition-docker-compose.yml is the current templates/wger/docker-compose.yml with two more env lines and a comment: WGER_USE_GUNICORN=True and WEB_CONCURRENCY=2.

Checked in the image wger/server:2.7 (sha256:1c5789b9…, the same digest the ladder records) on bench 9401:

  • /home/wger/entrypoint.sh runs gunicorn wger.wsgi:application --preload --bind 0.0.0.0:$PORT only when WGER_USE_GUNICORN == "True". Otherwise it runs manage.py runserver.
  • There is no -w, no gunicorn.conf.py in the working directory /home/wger/src, and no GUNICORN or WEB_ env in the image.
  • gunicorn 26.1.0's own Config() gives workers 1 by default and 2 with WEB_CONCURRENCY=2. The default timeout is 30 s.

Bench 9401 (demo-hp), two runs

  1. upgrade-test.py --soak 600 --move-to wger wger@gunicorn (harness v5): FROM the template as it stands (runserver) TO the gunicorn definition. Raw output: bench/R762-gunicorn.log and bench/evidence/MV-wger/.
    • The verdict is proven. The seed was read back before and after the switch. The app was healthy after it. The abort was starts-and-serves. Measured at 2026-10-08T06:19:56Z.
    • The memory watch ran for 606.5 s with 11,584 requests (all 302) and load: reached.
      • wger: anon peak 178,151,424 B = 170 MiB = 44.2 % of 384M; 0 oom_kills; 0 restarts; the cgroup peak was 100 % (page cache).
      • wger-files: anon peak 15.8 %; 0 kills; 0 restarts.
    • to-full.log has „Using gunicorn on port 8000..." and 2 × „Booting worker" (pids 18 and 19).
  2. check/benchcheck.sh: the definition started fresh in project r762b, then the login page, its CSS, a photo and the workers were read. Results in check/.
    • Ready after 77 s. Login page 200.
    • CSS 200 for all 3 of the page's own links, through wger-files (text/css; 2481 B, 277042 B and 1006 B).
    • Web login 302 with a session. POST /api/v2/gallery/ with a 179 B PNG returned 201. The photo read back through wger-files: 200, 179 B, image/png.
    • Control: an unknown /static/ file returned 404.
    • The container's env holds WGER_USE_GUNICORN=True and WEB_CONCURRENCY=2. Its log has 2 × „Booting worker".
    • anon peak 174,047,232 B = 166 MiB = 43.2 %. oom 0, oom_kill 0. restarts=0, oomkilled=false.
    • 20 parallel login GETs all returned 200.
    • This run is short. The 10-minute watch is run 1.

The night's figure (night-burndown-2026-10-06/r762/) was 157 MiB, 41 %, on the template without traefik's env. Today it is 166 to 170 MiB, 43 to 44 %, on the full catalog template.

The ladder: why no step file was written

The ladder records image moves. This change moves no image: from and to would both be {wger: wger/server:2.7, wger-files: nginx:1.30.5-alpine} (step key 10df849ded803b6e). The writer handles from == to as a re-test, and ladder.check_entry refuses that entry: „a re-test (from == to) whose digest is the same as its digest_from tests nothing new — no new digest" (tool output, 2026-10-08). 09 §5.4's render table says „deployed, pinned, catalog images equal → the catalog template — fixes flow". So a compose-only change reaches an installed wger at its next up -d, and the product's restart is up -d (manager.go ~L1411). It needs no ladder entry. No box runs wger (hub read, 07:58).

Teardown

  • Machine (bench 9401): project r762b was taken down with down -v; afterwards 0 containers and 0 r762 volumes. The harness ran its own down -v. /root/r762b and the helper scripts were deleted. /opt/upg/templates/wger@gunicorn was deleted. /opt/upg's scripts and templates/wger were updated to the catalog's 32d1346 copies; they were older before. /opt/upg/evidence/MV-wger now holds today's run (the 10-06 run is kept in audits/design-build-2026-10-06/F/bench/). /opt/upg/R762-gunicorn.log stays. 9401 was stopped (pct status: stopped), as it was found.
  • Machine (9202): only GETs and a dashboard login. 0 wger containers; repo_url is still the live catalog. Its deployed list was paperless-ngx, privatebin and recipe-importer at 08:0x CEST and paperless-ngx and privatebin at 08:35. This session did not touch recipe-importer; something else removed it in that window.
  • Host (demo-hp): the /tmp copy files were deleted. Nothing else was created.
  • Hub: nothing.
  • No Docker command ran on DooPlex. Nothing was pruned.

The image's default admin password is redacted in every file here.