wger: gunicorn with 2 workers instead of the development server (R-762)
gates / gates (push) Successful in 6s
gates / gates (push) Successful in 6s
WGER_USE_GUNICORN=True + WEB_CONCURRENCY=2. Proven on bench 9401 (anon 44 %) and scratch 9202 (anon 64.1 % of 384M, 0 oom_kill, 0 restarts; login, CSS and a photo 200). wger stays lifecycle: hidden. No ladder entry: no image moves. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
@@ -1,3 +1,26 @@
|
||||
## 2026-10-08 (day) — wger runs on its real web server: gunicorn with 2 workers (R-762)
|
||||
|
||||
**What runs on a box changed:** nothing today. wger stays `lifecycle: hidden`, and no box runs it (hub read 2026-10-08
|
||||
09:46 CEST: wger is in no box's deployed list, containers or app telemetry; paperless-ngx control present on 4 of 4).
|
||||
|
||||
- `templates/wger/docker-compose.yml`: `WGER_USE_GUNICORN=True` and `WEB_CONCURRENCY=2`, with a comment. Before this,
|
||||
the image ran Django's development server (`manage.py runserver`). The image's entrypoint runs
|
||||
`gunicorn ... --preload` only on that switch and passes no `-w`, so gunicorn reads its worker count from
|
||||
`WEB_CONCURRENCY`. The header's RAM line now gives the measured figure.
|
||||
- Proven on the bench (9401, harness v5 verdict `proven`, 606 s watch: anon peak 170 MiB = 44 % of 384M) and on scratch
|
||||
9202 (a fresh install from the drill catalog through the product's deploy endpoint): 2 × „Booting worker" in the
|
||||
log; login page 200; its three CSS links 200 through `wger-files`; a photo uploaded 201 and read back 200 (179 B,
|
||||
`image/png`); an unknown `/static/` file 404 (control). 9202's 600 s watch (10,944 requests): anon peak 246 MiB =
|
||||
64.1 % of 384M, flat for 1,200 more page loads after; oom_kill 0, restarts 0.
|
||||
- **No ladder entry:** the change moves no image (from == to). `ladder.check_entry` refuses a re-test with the same
|
||||
digest („tests nothing new"), and `09` §5.4 renders the catalog template when the images equal the pinned ones. So the
|
||||
change reaches an installed wger at its next `up -d`.
|
||||
- `onboarding/wger.md`: row 1.5 done (gunicorn); row 1.7's „stays unset" sentence corrected; row 9.3's open-row count
|
||||
(8) and register rows corrected.
|
||||
- Evidence: `felhom.eu/documentation/audits/day-2026-10-08/r762/` (`bench/`, `9202/`). Gates: `catalog_gates.py --fast`
|
||||
green. The runtime gates (image-resolvable, volume-persistence) were not run: they need a container runtime, and
|
||||
DooPlex gets no Docker command.
|
||||
|
||||
## Unreleased (2026-10-07) — the shared rule file; no code change
|
||||
|
||||
- `.claude/rules/unprompted-work.md`: rule 11 (every helper prompt carries the brief's fences in full, `09` §3 decision 160) and the §1 line „no hub image build or hub deploy in a session the operator does not attend" (decision 162). Identical in all five copies.
|
||||
|
||||
@@ -1,4 +1,30 @@
|
||||
# REPORT — no code change (2026-10-07 day)
|
||||
# REPORT — wger runs on gunicorn with 2 workers (R-762, 2026-10-08 day)
|
||||
|
||||
Only the shared rule file changed (`09` §3 decision 162: no hub image build or deploy in a session the operator does not
|
||||
attend; and rule 11, every helper prompt carries the brief's fences in full). Controller 0.302.0 stays on the three boxes.
|
||||
**Change:** `templates/wger/docker-compose.yml` sets `WGER_USE_GUNICORN=True` and `WEB_CONCURRENCY=2`. Before this, wger
|
||||
ran Django's development server. wger stays `lifecycle: hidden`. No box runs wger (hub read 2026-10-08 09:46 CEST).
|
||||
|
||||
| venue | workers | anon peak (of 384M) | oom_kill | restarts | login | CSS (3 links) | photo read back |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| bench 9401 (harness v5, 606 s) | 2 | 170 MiB, 44 % | 0 | 0 | 200 | 200 | 200 |
|
||||
| scratch 9202 (drill catalog, product deploy, 600 s) | 2 | 246 MiB, 64.1 % | 0 | 0 | 200 | 200 | 200 (179 B, image/png) |
|
||||
|
||||
On 9202 the anon figure stayed at 246 MiB for 1,200 more page loads after the watch. Control: an unknown `/static/` file
|
||||
answered 404.
|
||||
|
||||
**No ladder entry.** The images do not move (from == to). `ladder.check_entry` refuses a same-digest re-test, and
|
||||
`09` §5.4 renders the catalog template when the images equal the pinned ones.
|
||||
|
||||
**Also corrected:** `onboarding/wger.md` rows 1.5, 1.7 and 9.3.
|
||||
|
||||
**Not changed:** `mem_request: "100M"` in `.felhom.yml`. The measured figure is about 250 MiB, but the controller uses
|
||||
`mem_request` in its install memory check (`deploy.go` L305, `update.go` L489). A change there changes which boxes can
|
||||
install wger, so it is for the operator.
|
||||
|
||||
**Gates:** `catalog_gates.py --fast` green. The runtime gates were not run, because DooPlex gets no Docker command.
|
||||
|
||||
**Teardown on 9202:** wger was removed through the product. Afterwards there was no container and no volume, and the
|
||||
stack directory held only the synced catalog template, as before the test. 9202's catalog setting was put back
|
||||
(`repo_url` = the live catalog; `controller.yaml` sha256 identical to before). The drill commit was reverted (drill
|
||||
`95876a3`).
|
||||
|
||||
Evidence: `felhom.eu/documentation/audits/day-2026-10-08/r762/`.
|
||||
|
||||
+3
-3
@@ -26,9 +26,9 @@ Measured on 9202 2026-10-01 from the drill catalog (e9f50b5, wger template ident
|
||||
1.2 | n/a | wger keeps SQLite on its own volume, no database sidecar
|
||||
1.3 | n/a | no MariaDB or PostgreSQL service in this template
|
||||
1.4 | done | felhom.eu/documentation/audits/new-app-checklist-2026-10-01/C/C2-static-reads.txt ; felhom.eu/documentation/audits/more-night-apps-2026-09-30/box/wger/step.txt — `DJANGO_PERFORM_MIGRATIONS=True`; the 2.6 -> 2.7 step migrated and read back on the box
|
||||
1.5 | open | the container runs `manage.py runserver` — `WGER_USE_GUNICORN` is not set (R-755; C2)
|
||||
1.5 | done | gunicorn with 2 workers since 2026-10-08 (`WGER_USE_GUNICORN=True`, `WEB_CONCURRENCY=2`, R-762): 2 × „Booting worker" in the log; login page, CSS and a photo 200; 10-min watch 0 oom_kill, 0 restarts — bench 9401 and 9202 (`felhom.eu/documentation/audits/day-2026-10-08/r762/`)
|
||||
1.6 | done | felhom.eu/documentation/audits/new-app-checklist-2026-10-01/C/C2-static-reads.txt ; felhom.eu/documentation/audits/new-app-checklist-2026-10-01/C/C3-logins.txt — of 15 key-like env reads: SECRET_KEY generated, JWT pair made at start (phone route 200), DB password unused by SQLite; the rest belong to features off here (S3, mail, reCAPTCHA, OIDC, PowerSync)
|
||||
1.7 | done | `DJANGO_DEBUG=False` (R-762, 2026-10-06): `collectstatic` runs at start; the static files are served by `wger-files` (nginx) — the login page's own CSS links 200 on the bench and on 9202 (`felhom.eu/documentation/audits/design-build-2026-10-06/F/`). `WGER_USE_GUNICORN` stays unset (R-755, closed)
|
||||
1.7 | done | `DJANGO_DEBUG=False` (R-762, 2026-10-06): `collectstatic` runs at start; the static files are served by `wger-files` (nginx) — the login page's own CSS links 200 on the bench and on 9202 (`felhom.eu/documentation/audits/design-build-2026-10-06/F/`). the web server is gunicorn since 2026-10-08 (row 1.5)
|
||||
1.8 | done | felhom.eu/documentation/audits/new-app-checklist-2026-10-01/C/C2-static-reads.txt ; felhom.eu/documentation/audits/new-app-checklist-2026-10-01/C/C3-logins.txt — DEBUG False; an unknown page is a plain 404, no debug page
|
||||
1.9 | n/a | SECRET_KEY signs sessions and reset links only; the JWT pair lives on the data volume and is backed up with it
|
||||
2.1 | open | re-sweep 2026-10-02 with the fixed gate (felhom.eu/documentation/audits/persistence-sweep-2026-10-02/A/sweep/TABLE.md): UNDETERMINED — /home/wger/media stays empty after the seed (no upload in the seed); nothing written outside a preserved folder (R-807). The August CLEAN came from start-time writes alone
|
||||
@@ -71,5 +71,5 @@ Measured on 9202 2026-10-01 from the drill catalog (e9f50b5, wger template ident
|
||||
8.5 | n/a | wger is an existing app; the count does not change
|
||||
9.1 | open | the runtime volume-persistence gate was not re-run today (last CLEAN 2026-08-02); the other gates exit 0 (B3) (R-759)
|
||||
9.2 | done | felhom.eu/documentation/audits/new-app-checklist-2026-10-01/C/C1-install.txt ; felhom.eu/documentation/audits/new-app-checklist-2026-10-01/C/C8-signup-guest-media-static.txt — fresh installs from the drill catalog, as household and stranger
|
||||
9.3 | open | 10 other rows stay open; each is a register row (R-755, R-759, R-762, R-763, R-764)
|
||||
9.3 | open | 8 other rows stay open; each is a register row (R-759, R-763, R-764, R-807)
|
||||
9.4 | n/a | wger is exempt: published 2026-02-15, before the checklist
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# wger - Edzésnapló és fitnesz tervező
|
||||
# Domain: ${SUBDOMAIN}.${DOMAIN}
|
||||
# Database: None (file-based)
|
||||
# RAM: ~100M (mem_limit: 384M) | Pi-compatible: Yes
|
||||
# RAM: ~250M with 2 gunicorn workers (measured 2026-10-08; mem_limit: 384M + wger-files 32M) | Pi-compatible: Yes
|
||||
#
|
||||
# Environment variables:
|
||||
# DOMAIN - Your domain (e.g., demo-felhom.eu)
|
||||
@@ -83,6 +83,14 @@ services:
|
||||
# /home/wger/static, and Django stops serving /static and /media itself (it never did in production — upstream
|
||||
# puts nginx in front). wger-files below serves both from the shared volumes.
|
||||
- DJANGO_DEBUG=False
|
||||
# R-762 (2026-10-08): the real web server. The image's entrypoint.sh runs `gunicorn wger.wsgi:application --preload
|
||||
# --bind 0.0.0.0:$PORT` when WGER_USE_GUNICORN is "True" (else Django's development server, `manage.py runserver`).
|
||||
# It passes no -w and the image has no gunicorn.conf.py, so the worker count is gunicorn's own WEB_CONCURRENCY
|
||||
# (unset = 1). Two workers: measured on the bench and on 9202 (2 x "Booting worker" in the log). anon peak under
|
||||
# load: 170 MiB (44 %) on the bench, 246 MiB (64 %) on 9202 after a photo upload, flat for 1,200 more page loads;
|
||||
# 0 oom_kill, 0 restarts. --preload: the workers share the app's pages with the master.
|
||||
- WGER_USE_GUNICORN=True
|
||||
- WEB_CONCURRENCY=2
|
||||
volumes:
|
||||
- wger_data:/home/wger/db
|
||||
- wger_media:/home/wger/media
|
||||
|
||||
Reference in New Issue
Block a user