CatchAllMiddleware was intercepting Docker healthcheck requests (Host:
localhost) and internal API calls, returning 404 instead of passing
through. Also removed certresolver from catch-all Traefik router to
avoid cert provisioning issues with HostRegexp(.+).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Stopped/undeployed app subdomains now show a branded page instead of
Traefik 404. Deploy settings page gains start/stop/restart controls.
Dashboard shows "Megnyitás" button for running apps.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Deploy API now returns immediately after validation + config save.
docker compose up -d runs in a background goroutine so the UI shows
progress during image pulls instead of blocking for 30-60s.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- New GET /api/debug/telemetry endpoint runs full telemetry pipeline on-demand
- GetTelemetryPreview callback added to DebugCallbacks, wired in main.go
- BuildAppTelemetryForDebug() exported wrapper in report/telemetry.go
- Debug page: new collapsible section with per-app table (memory, CPU, log errors/warnings, issues) and raw JSON viewer
- Available regardless of hub configuration
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Deploy page, pre-start check, and deploy validation now use actual
/proc/meminfo usage instead of declared mem_request sums. New
GetMemoryMB() helper for lightweight real-time memory reads. Monitoring
page gains a stacked memory distribution bar showing per-container
usage, OS overhead, and free memory.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The filebrowser stack has no .env file — domain is baked into compose labels
by docker-setup.sh. The sync always bailed with a WARN and storage paths
were never applied to FileBrowser's config.yaml or docker-compose.yml.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove "Automatikusan generálva" badge from domain field (it's not
generated, it's the customer's configured domain)
- Shrink subdomain input width (8rem) so the .domain suffix appears
directly next to it on the same line
- Suppress redundant "Az alkalmazás aldomainje" description hint for
subdomain fields (the warning hint is sufficient)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Users can now customize the subdomain for each app during deployment
instead of using a fixed value. The deploy page shows an editable text
input with the default pre-filled and the base domain as a suffix.
New "subdomain" deploy field type with DNS-safe format validation,
reserved name blocklist, and uniqueness check across deployed stacks.
Locked after deploy — changing requires Remove + Redeploy.
Backward compatible: InjectMissingFields() auto-fills SUBDOMAIN from
.felhom.yml defaults for existing deployed apps on next sync/restart.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Domain field now displays subdomain.base_domain (e.g. wiki.demo-felhom.eu)
instead of just the base domain, matching the app card display.
Applies to both pre-deploy and post-deploy settings pages.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Pre-generate domain + secret field values when deploy page loads,
so user sees actual domain and masked passwords (with reveal button)
before deploying. Same values submitted as hidden inputs → saved to app.yaml.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Debug-mode-only dashboard (/debug) with 8 collapsible sections:
system diagnostics, notification testing, backup triggers, storage
simulation, hub & connectivity, self-update dry-run, DR/setup wizard,
and in-memory log viewer. Migrates debug dump from API router to web
server. Adds ring buffer log capture, storage disconnect simulation,
event history tracking, and cross-drive/self-update test methods.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
dashboardHandler, stacksHandler, monitoringHandler used blank identifier
for the request param but now call executeTemplate(w, r, ...).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add internal/assets package that downloads and caches app assets from
Hub API with SHA-256 change detection. Assets resolve from synced cache
first, falling back to baked-in directory. Daily sync schedule +
on-demand POST /api/assets/sync endpoint.
Config: assets.sync_enabled + assets.sync_schedule (default 05:00)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The logo handler tried os.ReadFile() on a non-existent filesystem path.
The SVG only exists as an embedded string constant in the web package.
Export FelhomLogoSVG and serve it directly in the setup handler.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New controller features:
- Web-based setup wizard replaces docker-setup.sh interactive config
- Dual listener: :8080 (Traefik) + :8081 (direct HTTP for LAN)
- Drive scanner finds .felhom-infra-backup/ on all block devices
- Hub recovery pull (GET /api/v1/recovery/{id}) with retrieval password
- Fresh install: Hub config download or manual wizard
- CSRF protection, state persistence, Hungarian UI
- Local infra backup written to all connected drives after each backup cycle
- .felhom-infra-backup/backup.json + metadata.json with SHA256 checksum
- Hub verification: parse customer_blocked from report push response
- Limited mode after 7 days without verification
- Recovery info page on Settings + recovery-info.txt file generation
- Pending events queue: DR events sent to Hub on next report push
- docker-setup.sh v6.0.0: removed interactive wizard, minimal controller.yaml only
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add "Eltávolítás" to remove deployed (non-orphaned) stacks — reverts
them to "Nincs telepítve" while preserving templates for redeploy.
Modal offers HDD data and backup data cleanup choices.
Auto-inject missing deploy fields (secrets, domains) into existing
app.yaml when templates are updated via sync or on controller startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Phase 1: Deprecate restic as Tier 2 method (rsync only), auto-migrate on startup
Phase 2: Enhanced per-app migration with backup awareness, DB dump copy, auto-cleanup
Phase 3: Full drive migration with decommissioned state, rollback support, wizard UI
Phase 4: Hub report includes decommissioned drive state
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add StorageBars to backupsHandler so all registered storage paths appear
- Update backups.html to use StorageBars loop (replacing single HDDConfigured block)
- Rename "SSD (/)" → "Rendszer (/)" on backup, monitoring, and dashboard pages
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
FileBrowser reads config.yaml from its working directory
(/home/filebrowser/), not from the data subdirectory.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add server.database to generated config.yaml pointing to the
persistent data volume. Previously the database was at
/home/filebrowser/database.db (outside the volume) and was lost
on every container recreation.
- Call syncFileBrowserMounts after manual storage path add, so newly
registered drives (like sys_drive) also appear in FileBrowser.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ensures config.yaml and docker-compose.yml are regenerated on
controller startup, so new drives added while the controller was
down still get their FileBrowser sources configured.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Generate config.yaml with a separate source per registered storage path.
Each source uses the drive's label as its display name, making it appear
automatically in FileBrowser's sidebar. The config.yaml is bind-mounted
into the container (read-only) alongside the data volume.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
CreateDirectory now returns an error when the folder already exists
instead of silently succeeding. JS validates folder name format
(alphanumeric + underscore, max 32 chars) before sending the request.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
After an interrupted attach wizard, the raw mount stays behind,
causing the device to appear as "mounted" in scan results. Now the
scan button calls cancel first, which unmounts any stale raw mounts
that have no bind mount in fstab.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New Settings wizard to attach drives with existing filesystems without
formatting. Mounts partition at staging path, lets user browse and pick
a subfolder, then bind-mounts it at /mnt/<name> with fstab entries.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Major refactor of backup and storage paths:
- Per-drive restic repos at <drive>/backups/primary/restic/
- Per-app DB dumps at <drive>/backups/primary/<app>/db-dumps/
- Remove global BackupDir, DBDumpDir, ResticRepo config fields
- Add SystemDataPath config (fallback for apps without HDD)
- New backup/paths.go with pure path computation helpers
- Add GetStackHDDPath to StackDataProvider interface
- Restic methods now accept repoPath as parameter
- Cross-drive backup uses new secondary path structure
- Rename storage/ to appdata/ in scripts and compose templates
- Update protected HDD paths (storage → appdata + backups)
- Simplify backup UI (remove global path displays)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Tier 2 cross-drive backup now configurable for all apps (not just HDD apps)
- Non-HDD apps (Mealie, Gokapi) can back up config + DB to secondary drive
- Status dot: removed "auto" gray — all apps start yellow, green = 2+ tiers OK
- Backup page: Tier 2 row always shown, Tier 3 placeholder added
- Deploy page: cross-drive config visible for all deployed apps
- Meta badges: non-HDD apps show "Konfig" or "Konfig + DB" instead of "Auto"
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Cross-drive now copies DB dumps (_db/) and config (_config/) alongside user data
- restic cross-drive includes config dir + full DB dump dir
- UI: per-tier rows (1. mentés / 2. mentés) instead of per-layer (DB/Konfig/Data)
- UI: BackupContents label shows what each tier protects (DB + Konfig + Adatok)
- UI: rsync backups show browsable indicator (📁)
- Cleanup: removed unused filterSnapshotsByPaths + pathCovers from router.go
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fix 1: HDD data backup is now mandatory for all deployed apps.
resolveAppBackupPaths() iterates ListDeployedStacks() directly — no
longer reads GetAppBackupMap() or checks the Enabled flag. DiscoverAppData()
drops backupPrefs parameter; BackupEnabled is set from HasHDDData.
Five dead settings methods removed: IsAppBackupEnabled, SetAppBackup,
GetAppBackupMap, SetAppBackupBulk, GetAppBackupPrefs.
Fix 2: Cross-drive backup now triggers a fresh DB dump (DumpStackDB)
before running. DBDumper interface added to crossdrive.go; Manager
implements it; SetDBDumper wired in main.go. Non-fatal — proceeds with
user data backup even if DB dump fails.
Fix 3: Restore dropdown shows ALL deployed apps (not just HDD+enabled).
restore.go rewritten: always restores config+DB, adds user data if hasHDD.
UI shows restore type banner (full / config+DB / config only) with
color-coded styling. Snapshot API clarified for non-HDD apps.
Fix 4: "Docker kötetek" → "Konfiguráció" — named volumes are not in
the restic backup paths; compose files + app.yaml are what's backed up.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- StackDataProvider interface extended with StopStack/StartStack
- backup.Manager.GetStackHDDMounts() delegates to stackProvider
- RestoreApp() auto-stops app before restic restore, restarts after (even on failure)
- stackAdapter in main.go wires StopStack/StartStack through to stacks.Manager
- GET /api/backup/snapshots?stack={name} filters snapshots by app HDD paths via filterSnapshotsByPaths()
- Restore section simplified: no path list, per-app filtered snapshots, human-friendly timestamp format, single calm warning, empty-result inline message
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Bug 1: Remove hardcoded 'v' prefix from templates (layout.html, settings.html); version tag already contains 'v'
- Bug 2: primaryHDDPath() and metrics collector now use GetDefaultStoragePath() instead of paths[0].Path so the real HDD is used, not the first (SSD) path
- Bug 3: Apps without HDD data show green/yellow based on volumeLastStatus instead of always gray
- Bug 5: Add default background rgba(255,255,255,0.1) to .btn to fix white-on-transparent readability
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>