Commit Graph

15 Commits

Author SHA1 Message Date
admin db88ee94f6 R-764: wger sends its mail through the box's relay (smtp_mapping, plaintext :2526, ENABLE_EMAIL gate; hidden app, 9202 boots owed)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 21:49:04 +02:00
admin 1968527a86 R-763: wger closes its own sign-up and guest users (hidden app; 9202 stranger walk owed)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 21:49:04 +02:00
admin 82fff329a4 wger: a stranger locks only the name they try, for 5 min — not every household member for 30 (R-752, 09 decision 58 — decided by CC unattended, operator may reverse)
gates / gates (push) Successful in 2s
django-axes keyed on ip_address, and behind the tunnel every visitor has the tunnel container's address (R-753).
Measured on 9202 (felhom.eu/documentation/audits/lockouts-2026-10-01/B/): live template — 10 wrong tries on admin
locked the second member too; with AXES_LOCKOUT_PARAMETERS=username, AXES_COOLOFF_TIME=5 and the database handler —
the second member unaffected, admin in again at 7.5 min after one retry during the lock, a wrong password still
refused. Settings only: no image moves, no ladder entry (gates OK).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-01 12:46:58 +02:00
admin 45d84827ad wger: its app login API gets its JWT key pair (R-737)
gates / gates (push) Successful in 2s
The template set no JWT_PRIVATE_KEY/JWT_PUBLIC_KEY, so the app login (the mobile app's route) answered 500
on a CORRECT password. The deploy's generators cannot make an RSA pair, so the start command makes it ONCE
with wger's own `manage.py generate-jwt-keys`, keeps it 0600 on wger's data volume (a restore brings it
back), and loads it before the image's own entrypoint. Measured on the bench (2.7): right password 200 with
an access token that reads the API (200); wrong password 400 (allauth's answer); the key survives a
restart. No image moves.

Evidence: felhom.eu/documentation/audits/night-rulings-2026-09-30/D/

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-09-30 22:27:13 +02:00
admin 4ad32aa768 wger: 2.6 -> 2.7, its first ladder step, both venues proven (R-462, R-738)
gates / gates (push) Successful in 2s
A new front-door fixture: the web login, then a weight entry through the app's own API, read back
with a no-session and a never-entered-weight control. Both venues ran on the R-738 template (7a4ff48,
migrations at start): bench 9401 proven, its migrations ran, 10-min watch 0 kills (anon peak 49.8 %);
box 9202 done in 46.2 s, the migrations ran, the entry read back. The first box walk WITHOUT the fix
failed (login 500, 12 migrations unapplied) and wrote nothing. Putting 2.6 back after the migration
loses the entries (recorded, as always; the box's undo restores the pre-update copy instead).
Written by upgrade-test.py --write-ladder.

Evidence: felhom.eu/documentation/audits/more-night-apps-2026-09-30/

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-09-30 18:25:51 +02:00
admin 7a4ff48590 wger: run the database migrations at start (R-738)
gates / gates (push) Successful in 2s
wger's image runs `manage.py migrate` only when DJANGO_PERFORM_MIGRATIONS=True (entrypoint.sh).
Without it, 2.6 -> 2.7 through the guarded Update on 9202 ended `done` and left 12 migrations
unapplied: the web login answered 500 (no such column: core_userprofile.time_zone). With the switch,
the same step on 9202 ran the migrations and the seeded weight entry read back. No image moves here;
no box reporting to the hub runs wger.

Evidence: felhom.eu/documentation/audits/more-night-apps-2026-09-30/box/wger/

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-09-30 18:05:48 +02:00
admin d0e7e2eb51 Setup gate on immich/n8n/audiobookshelf/uptime-kuma (decision 46); mealie/wger/calibre-web after_install; romm/zipline stale notes; grafana R-708; wger R-712
gates / gates (push) Successful in 2s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-09-29 09:19:05 +02:00
admin fd4426b1b2 wger: probe and route port 8000 (the image exposes 8000, not 80)
With 2.6 pulling and booting, wger still sat unhealthy: the healthcheck got
wget rc=4 (network failure, not an HTTP error) because nothing listens on :80.
wger's own log says it plainly -- 'Using django's development server on port
8000...' -- and the image declares ExposedPorts {"8000/tcp"}.

Corrected both the healthcheck target and the Traefik loadbalancer port, which
was pointing at :80 as well (so routing would have failed even once healthy).

Campaign 7 catalog sweep.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nn3VgQk9iwEGgyx6QJ2NvE
2026-07-19 03:17:26 +02:00
admin 94074840d1 wger: 2.6 with the full DJANGO_DB_* set (2.3 no longer exists upstream)
Correcting my own earlier revert. Reverting to 2.3 was WRONG: wger/server:2.3 is
no longer published on Docker Hub (only 2.4, 2.5, 2.6 resolve), so that pin could
not be pulled at all -- the deploy was accepted and no container was ever created.
An unpullable pin is strictly worse than the problem it was meant to avoid.

Every available version (2.4/2.5/2.6, verified) reads the whole DJANGO_DB_* set
unconditionally, even with the sqlite engine. So supplying it is not a hack
around one version -- it is now the only way to run wger at all. Verified live:
2.6 with the full set boots and applies its migrations ('Applying auth.0001_initial
... OK').

USER/PASSWORD/HOST/PORT are ignored by the sqlite backend but must be present.
DJANGO_DB_DATABASE points into the existing wger_data volume (/home/wger/db),
which is where wger's own default sqlite file lived -- so an existing install is
not pointed at an empty database somewhere else.

Campaign 7 catalog sweep.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nn3VgQk9iwEGgyx6QJ2NvE
2026-07-19 03:04:55 +02:00
admin 7350cd905a wger: revert 2.6 -> 2.3 (2.6 needs a full DB config the template cannot supply)
wger 2.6 crash-loops on a fresh deploy. Its settings/main.py reads the whole
DJANGO_DB_* set unconditionally -- even when the engine is sqlite:

  ImproperlyConfigured: Set the DJANGO_DB_DATABASE environment variable
  ...then, once that was supplied:
  ImproperlyConfigured: Set the DJANGO_DB_USER environment variable

Satisfying it means either stuffing in dummy USER/PASSWORD/HOST/PORT values that
the sqlite backend ignores, or giving wger a real Postgres sidecar. The first is
a hack, the second is compose restructuring -- both outside this campaign's
allowed-fix set.

Reverted to the previously shipped 2.3. NOTE: the interim DJANGO_DB_DATABASE
line added earlier in this campaign is reverted TOO, deliberately -- on 2.3 the
sqlite path came from wger's own default, and pinning a different explicit path
would have pointed an existing customer's wger at an empty database.

Campaign 7 catalog sweep.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nn3VgQk9iwEGgyx6QJ2NvE
2026-07-19 02:26:02 +02:00
admin a35d67ba63 wger: set DJANGO_DB_DATABASE (2.6 dropped the sqlite default)
wger 2.6 crash-looped 15 times on a fresh deploy:

  django.core.exceptions.ImproperlyConfigured:
  Set the DJANGO_DB_DATABASE environment variable

The template already selected the sqlite3 engine, but 2.6 no longer supplies a
default database path -- it must be given explicitly even for sqlite. Pointed at
the existing wger_data volume (/home/wger/db) so the database survives redeploys.
Env var proven wrong by the deploy.

Campaign 7 catalog sweep.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nn3VgQk9iwEGgyx6QJ2NvE
2026-07-19 01:27:22 +02:00
admin e43fa89f80 wger: 2.3 -> 2.6
Campaign 7 catalog sweep.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nn3VgQk9iwEGgyx6QJ2NvE
2026-07-18 23:27:06 +02:00
admin 8ddd3c9da5 fix(healthcheck): sweep localhost -> 127.0.0.1 across all 48 templates
BusyBox wget (+ node/python/curl one-shots, incl mealie's socket tuple) resolve
localhost -> IPv6 ::1 with no cross-family fallback; an IPv4-only-binding app
reads docker-unhealthy while serving (vaultwarden, re-run 2026-07-06). Escalates
that instance to the class. Scoped strictly to healthcheck test: lines
(diff-reviewed: no env/config/label changed; .felhom.yml already clean). New
REUSE.md convention row.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-06 20:25:54 +02:00
admin 87d0e5e59d feat: use ${SUBDOMAIN} variable in all templates
All 51 docker-compose.yml: replaced hardcoded subdomain.${DOMAIN}
with ${SUBDOMAIN}.${DOMAIN} in Traefik labels, app env vars, and
comments.

All 51 .felhom.yml: added SUBDOMAIN deploy field (type: subdomain)
with default matching existing subdomain metadata value.

Works with felhom-controller v0.27.0 which validates and stores the
user-chosen subdomain in app.yaml. Existing deployed apps get
SUBDOMAIN auto-injected via InjectMissingFields() on next sync.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 15:06:44 +01:00
admin 0bd3f2a0e2 added apps! 2026-02-15 08:47:15 +01:00