Commit Graph

18 Commits

Author SHA1 Message Date
admin 459e78146e komga: remove the client-written X-Forwarded-For chain on its router (R-753)
Spring framework strategy — leftmost XFF into its sign-in audit record. Once traefik trusts the tunnel's fixed address (controller v0.286.0), the leftmost entry is what a
stranger writes; with the chain removed the app reads traefik's X-Real-Ip or its peer, as before — never forgeable.
Measured on 9202: a router with this middleware receives no X-Forwarded-For (felhom.eu audits/visitors-2026-10-01/A/P1).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-01 21:03:06 +02:00
admin 403a8f537a komga: within-major step, both venues proven (R-462, Part F)
gates / gates (push) Successful in 2s
{'komga': 'gotson/komga:1.27.1'} -> {'komga': 'gotson/komga:1.28.0'}
The ONLY image move in this commit. Written by upgrade-test.py --write-ladder (catalog gates rc=0):
- bench LXC 9401 (harness v4): the seed read back before and after; 10-minute memory watch:
  komga anon 64.5 % (cgroup 67.5 %); 0 kills, 0 restarts; the abort starts and serves the data;
- box 9202 (controller 0.283.1, the product's guarded Update, drill catalog): done in 44.2 s, the seed
  read back through the app's own front door.
Evidence: felhom.eu/documentation/audits/pg-last-six-2026-09-30/F/ and .../box/komga/

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-09-30 14:30:27 +02:00
admin 6faf432e22 Setup gate on 28 more apps; signup_block on 11 (decision 47); claper R-713 base64; FIRST-ADMIN current
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 11:08:56 +02:00
admin fc1becc63d komga: 1.25.0 -> 1.27.1 and 768M (proven on the bench AND on 9202, with its test record)
gates / gates (push) Successful in 1s
Bench at 512M: proven but memory_tight (its own memory 94.6 %); per the
bar the limit is raised in the same commit and the watch re-run once:
at 768M 60 %, 0 kills, 11 940 requests all 200; abort starts-and-serves.
Box (9202, guarded Update, at 512M): done, read back, R-626 clean.
The komga fixture was fixed tonight (users/me lives at /api/v2).
09 decision 21.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-09-23 21:47:25 +02:00
admin 1f8065076b English copy — BATCH 3 of 3: the last 16 apps. THE CATALOG IS TRANSLATED.
gates / gates (push) Failing after 2s
actualbudget, claper, docmost, emby, gitea, immich, kimai, komga, onlyoffice,
opengist, plant-it, rallly, recipe-importer, seerr, vaultwarden, zipline — 306
strings. EN_MISSING_CEILING 307 -> 1.

1 031 of 1 032 strings now carry an English twin. The one that does not is papra's
AUTH_SECRET description, a Hungarian defect (R-593) left to fall back rather than
translated wrongly.

The gate convicted two of my own sentences and was half right: vaultwarden's invite
step and sign-up setting ended "can open an account", and the retrieval-promise
pattern reads "can ... open" as the claim that sealed backups can be opened. Opening
an ACCOUNT is not that claim, so the conviction was a false positive — but the
wording was also the weaker wording, so both now read "can sign up". The gate has no
way to REGISTER a legitimate occurrence, which the shared vocabulary's own design
calls for; filed as R-594.

No Hungarian byte moved in any of the three batches; the freeze gate proves it on all
53 apps on every push.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-09-20 16:34:47 +02:00
admin 69761cf91b catalog_since on all 53 apps: the date this repo last moved each app's pinned images
Backfilled from this repo's own git history (newest commit whose image: set differs
from its parent's), excluding the two bentopdf SPIKE commits by hash — they moved a
pin and reverted it in the same hour and are a measurement, not a release.

Four anchors confirmed (nextcloud 5e2c1ae, grafana b789acc, calcom 147cee7,
vikunja 3fa63cd, all 2026-07-18); six apps re-checked against git log by hand.

Consumed by felhom-controller v0.233.0 to render 'Frissitesi elerheto - N napja'.
No version number is ever shown to the customer, so there is no version: key.

Rule added to CLAUDE.md; the missing drift gate is filed as a register row (the
gates runner fetches at --depth 1 and has no parent to diff an image: line against).
2026-09-02 20:15:33 +02:00
admin aa27d0c054 komga: 1.20.0 -> 1.25.0
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:03 +02:00
admin 21e8df1e3a backup classification: backup: blocks for the 13 bind-bearing apps
Adds the referential-coupling backup: block to every app that binds
${HDD_PATH}/${USERDATA_PATH} (immich, paperless-ngx, nextcloud, calibre-web,
audiobookshelf, komga, navidrome, radarr, sonarr, emby, jellyfin, plex, romm).
Each lists its userdata:/hdd: binds with class mandatory|optional|excluded
(operator-ruled + spike SQ2).

Requires controller v0.132.0 (deployed) which parses+validates these blocks.
INERT — no backup tier changes behavior yet (Task 3/4 consume it). All 13
verified against the shipped parser: parse-clean, every bind resolves explicit.
audiobookshelf media/audiobooks = optional (PENDING Viktor veto to excluded).

Ref: felhom.eu/documentation/audits/SPIKE-backup-classification-2026-07-14.md
2026-07-14 18:51:36 +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 9b066de331 komga: fix controller-side health probe path too (/actuator/health)
The .felhom.yml controller probe also pointed at the auth-gated /api/v1/actuator/health
(401) — that is what drives the dashboard 'Nem egészséges' state. Repoint to the
unauthenticated /actuator/health, matching the docker HC fix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 15:04:52 +02:00
admin 3faa5ae193 komga: fix healthcheck — probe unauthenticated /actuator/health (was 401 on /api/v1/...)
The /api/v1 prefix is auth-gated → old HC got 401 → curl -f failed → container
reported unhealthy while serving fine. Diagnosed live on guest 9201.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 15:03:37 +02:00
admin 939864f2a6 catalog: repoint HDD_PATH defaults/placeholders to /mnt/felhom-drives/<name>
Intermediary-mount re-architecture: drives are visible in-guest at the stable
/mnt/felhom-drives/<name>. Composes already use ${HDD_PATH}/${USERDATA_PATH}
(injected + repointed by controller v0.67.0); this updates the UI placeholders,
templates.json defaults, and doc/script examples to the new convention.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 16:48:52 +02:00
admin c99070c105 komga + audiobookshelf: add no-new-privileges (root-fallback hardening)
Address security review: reverting to root removed the user:1000 boundary, so add
security_opt no-new-privileges:true to block SUID-based escalation. Full cap_drop
is intentionally NOT applied — the images' root-init needs CHOWN/SETUID/SETGID to
set up /config and /metadata (dropping them reproduces the crash we hit at user:1000).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 22:17:32 +02:00
admin 0d60a5cb2e komga + audiobookshelf: revert to root (user:1000 fallback)
Live try-then-fallback: pinning user 1000:1000 crash-loops both — their named
config/metadata volumes are Docker-created root-owned and the pinned process can't
write them (komga: SQLite /config open fails; audiobookshelf: EACCES mkdir
/metadata/logs; neither has a PUID-style root-init chown). Reverted to root; they
rely on the setgid 2775 userdata dirs (files land group 1000 → FileBrowser browses/reads).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 22:13:29 +02:00
admin 69611cec18 userdata layout: repoint customer-content mounts to ${USERDATA_PATH}
Move every shared-media + ingest mount off ${HDD_PATH}/media onto the new
${USERDATA_PATH}/... convention (controller injects USERDATA_PATH = <namespace>/userdata):
- jellyfin/emby/plex: media:/media:ro ; navidrome: media/music:ro
- audiobookshelf (user 1000:1000): media/{audiobooks,podcasts}
- komga (user 1000:1000): media/comics
- calibre-web (UMASK=002): library->media/books, ingest->import/calibre
- radarr/sonarr (UMASK=002): media/{movies,tv} + downloads (sibling, same FS)
- romm: ROM library -> userdata/roms (browsable); resources stay in appdata
- immich: + external library media/photos:/external/photos:ro (registration is a
  post-deploy admin step — flagged in compose + .felhom.yml)
- paperless: consume -> import/paperless (USERMAP 1000)
- nextcloud: unchanged (fully app-managed)
.felhom.yml first_steps updated for the new browsable drop-zones.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 21:46:23 +02:00
admin a04882e296 feat: add controller-side healthcheck configs to all 52 apps
Each app template now declares a healthcheck: section in .felhom.yml
with appropriate probe type (http, api, or tcp) and endpoint based on
the app's known health endpoints. The controller uses these to verify
services are actually responding, not just that containers are running.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 11:11:27 +01: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