New .felhom.yml field consumed by the controller's Megnyitás link. Audit of all 53 templates: only
gokapi (file-share index redirects away) and ghost (bare / is the public blog; admin at /ghost/) need it;
the rest serve/redirect usefully at root. onlyoffice is API-only (status page at /) — left at root.
Gokapi's bare root '/' redirects to RedirectUrl. It was the upstream default (github.com/Forceu/Gokapi),
so the controller's 'Megnyitás' link (always the bare subdomain root) landed on Gokapi's GitHub instead
of the app. Point it at https://${SUBDOMAIN}.${DOMAIN}/admin so the root + the controller link reach
the Gokapi login/panel.
App now auto-configures (no setup wizard), so first_steps described a flow that no longer happens.
Add default_creds 'Felhasználó: admin · jelszó a Beállítások oldalon' so the app-info page shows the
initial admin user like other apps; password stays on the Beállítások page (generated field).
Gokapi v1.9.6 has no env-var setup and otherwise exposes a public /setup (admin-takeover risk).
Entrypoint seeds config.json on first boot (admin, this app's URL, local storage, no-encryption so
it restarts without a prompt) with password/salts cleared, then runs the documented
--deployment-password one-shot to set the felhom-generated admin password before serving — claims
admin at first boot, never exposes /setup. Seed pinned to v1.9.6 (ConfigVersion 21).
Verified against Gokapi docs + the v1.9.6 binary: no env-var headless admin setup exists in any
version. Non-interactive setup requires a pre-seeded config.json + --deployment-password. Reverting
the non-functional env so the template isn't misleading; choosing a real fix path with the user.
Gokapi sat in maintenance mode since deploy because /setup was never completed and the
template provided no headless-setup env. GOKAPI_USERNAME/PASSWORD configure it on first
start; password is felhom-generated (deploy field, shown to customer). Fixes share.* maintenance page.
Surfaced during the unattended deploy sweep: a fresh gitea reported unhealthy because
the HC hit /api/v1/version (404 until install-lock); /api/healthz returns 200 while
serving. Fixed both the docker HC and the controller .felhom.yml probe; bumped
start_period to 90s for first-boot DB migration. Same class as the komga fix.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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>
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>
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>
The compose fed the +-joined PAPERLESS_OCR_LANGUAGE (e.g. hun+eng) into
PAPERLESS_OCR_LANGUAGES (the install list), so the image tried to apt-install a bogus
'tesseract-ocr-hun+eng' → hun pack missing → Django check crash-loop on the default
hun+eng. PAPERLESS_OCR_LANGUAGES must be space-separated; set a fixed superset
'eng hun deu' (verified each installs). Found live deploying paperless on guest 9201.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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>
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>
The override pointed at a v1-era node /app/extra/healthcheck.mjs that does not
exist in louislam/uptime-kuma:2, so the container was permanently unhealthy and
Traefik withheld the route → the app URL 404'd despite the app running. Point at
the correct binary (extra/healthcheck, WORKDIR /app) and use the image's timing
(180s start_period) to avoid transient unhealthy→404 on first boot.
SECRET_KEY ("Titkosítási kulcs") is a data-encrypting key — regenerating it on
restore would render stored data unreadable. data_key:true makes the controller
recover it from the guest's own app.yaml (live/PBS) and fail closed if it can't,
rather than ever regenerating. Pairs with controller v0.53.0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Model A binds the guest mount /mnt/<drive> directly onto the host's
<drive>/felhom-data namespace, so the guest mount already IS felhom-data.
The templates' ${HDD_PATH}/felhom-data/appdata/<app> therefore double-nested
to <drive>/felhom-data/felhom-data/appdata/<app> on disk, diverging from the
provenance-aware backup helpers (NamespaceRoot(drive,true) -> single-nested).
Change all four HDD app templates (romm, nextcloud, immich, paperless-ngx)
to ${HDD_PATH}/appdata/<app>, matching AppDataDir(NamespaceRoot(HDD_PATH,true)).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add 'nextcloud' to NEXTCLOUD_TRUSTED_DOMAINS so internal callbacks
from other containers (e.g. OnlyOffice Document Server) arriving with
Host: nextcloud are not rejected. Only affects initial install — for
existing deployments, the integration handler sets it via occ.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fixes mixed content errors when OO is behind Traefik HTTPS reverse
proxy. Without this, OO Document Server generates http:// URLs for
editor resources, which browsers block on HTTPS pages.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Declares FileBrowser and Nextcloud as integration targets for the
new app-to-app integration framework in the controller.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The !include directives for automations/scripts/scenes reference files
that don't exist on fresh install, causing HA to enter recovery mode
which ignores trusted_proxies. Simplified to minimal config with just
default_config and http block - HA adds the rest during onboarding.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
HA rejects proxied requests (400 Bad Request) without trusted_proxies
in configuration.yaml. Uses entrypoint wrapper pattern (like romm) to
ensure the http config block exists before HA starts.
Handles both fresh deploys (creates full configuration.yaml) and
existing installs (appends http block if missing).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The /api/ endpoint requires authentication, causing healthcheck to always
fail and spam HA logs with "invalid authentication" warnings.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ghost 6.x redirects all HTTP requests to the configured external URL.
- Docker healthcheck: use node http.get (accepts 301 as healthy)
- Controller probe: switch from api (expect 200) to http (any response)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
The vikunja/vikunja:0.24.6 image is a scratch/distroless build with
only the Go binary. wget, curl, sh, and all other utilities are
missing, making in-container healthchecks impossible.
Removing the healthcheck lets the controller detect the container
as "running" directly from Docker state, which is the correct
behavior for shell-less images.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Vikunja 0.24.6 runs as uid=1000 but named Docker volumes are
created with root ownership, causing permission denied on /db.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Hungarian recipe scraper for Mealie & Tandoor. Supports mindmegette.hu,
streetkitchen.hu, nosalty.hu, sobors.hu, kiskegyed.hu, gastrohobbi.hu
with schema.org fallback for other sites.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All user-facing admin passwords now use type: password instead of
type: secret, giving users a visible editable field with Generate
button (matching Paperless-ngx pattern).
Affected apps: Nextcloud, Grafana, Kimai, Code-server
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Compose templates were mounting app data at ${HDD_PATH}/appdata/ instead
of ${HDD_PATH}/felhom-data/appdata/ as designed in the v0.26.0+ path
structure. Affects: nextcloud, immich, paperless-ngx, romm.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Backend: wget missing from image, use python urllib instead.
Frontend: localhost resolves to IPv6, use 127.0.0.1.
Backend: add SECRET_KEY env var (v0.11.0 reads it directly).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>