# 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.