Commit Graph

168 Commits

Author SHA1 Message Date
admin 4a6ab4d61c feat(debug): add Telemetria teszt section to debug page (v0.28.1)
- 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>
2026-02-23 11:09:06 +01:00
admin 05ecd65412 feat(telemetry): add per-app metrics and log telemetry to hub reports (v0.28.0)
- New internal/metrics/telemetry.go: MetricsStore.GetContainerTelemetry()
  aggregates container memory/CPU from SQLite over the last 15 min
- New internal/metrics/logscanner.go: ScanContainerLogs() scans docker logs
  for errors/warnings, deduplicates via fingerprinting (strips timestamps,
  replaces 6+ digit numbers, hex strings, UUIDs)
- New internal/report/telemetry.go: buildAppTelemetrySection() assembles
  per-stack AppTelemetry by aggregating container metrics and log summaries
- internal/report/types.go: added AppTelemetry field to Report struct plus
  AppTelemetry type with memory/CPU/log fields and LogIssue references
- internal/report/builder.go: calls buildAppTelemetrySection() in BuildReport()
- Backward-compatible: old Hub versions silently ignore app_telemetry field

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 10:46:27 +01:00
admin ac5e3cb14e fix(monitoring): read used_mem_mb from nested system object in API response
The /api/system/info response wraps SystemInfo under data.system,
not directly under data.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 10:13:08 +01:00
admin ad4c005e01 v0.27.3: Use real system memory everywhere, add monitoring memory bar
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>
2026-02-23 10:06:03 +01:00
admin e99067ca60 v0.27.2 — copyable error popups, Tier2 hub reporting, memory bar fixes, new labels
- Replace native alert() with custom showAlert() modal (text selectable)
- Manual Tier2 backup now pushes infra backup to Hub
- CommittedMemory() excludes stopped/exited apps
- Pre-start memory check blocks start if insufficient RAM
- Add hungarian_ui metadata field + "Magyar felület" badge
- Add "USB" badge on storage cards in settings page

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 09:28:29 +01:00
admin b8ab9264f4 fix: SyncFileBrowserMounts reads domain from controller config instead of missing .env
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>
2026-02-22 18:01:43 +01:00
admin 64072f1936 style: subdomain suffix as plain text instead of bordered box
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 15:48:44 +01:00
admin 002c388f9f fix(deploy): polish subdomain field UI
- 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>
2026-02-22 15:21:01 +01:00
admin 66817709ad v0.27.0 — user-configurable app subdomains
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>
2026-02-22 15:06:22 +01:00
admin f7556b0dad v0.26.2 — show full app URL on deploy page
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>
2026-02-22 13:51:39 +01:00
admin f95f570670 v0.26.1 — show auto-generated values on deploy page
- 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>
2026-02-22 13:42:15 +01:00
admin 7abd1c5954 v0.26.0: Storage namespace felhom-data/ + test node wipe script
All felhom-managed data on external drives now lives under felhom-data/
subdirectory, cleanly separating controller data from user files.

- backup/paths.go: add FelhomDataDir constant, update 8 path helpers
- stacks/delete.go: add local felhomDataDir constant (circular import
  boundary), update ProtectedHDDPaths + GetStackBackupData
- storage/migrate_drive.go: import backup pkg, fix conflict check, verify,
  rsync excludes (felhom-data/backups/*/restic/), size estimation
- storage/migrate.go: import backup pkg, fix DB dump paths
- web/handlers.go: fix legacy 'storage' path -> backup.AppDataDir()
- storage/format_linux.go: create felhom-data/ instead of storage/
- storage/attach_linux.go: create felhom-data/ instead of storage/
- scripts/felhom-wipe.sh: new multi-level test node wipe script
  (soft/controller/full/nuclear)
- CHANGELOG.md, controller/README.md, scripts/README.md: updated docs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 10:10:51 +01:00
admin 7f48786312 v0.25.0 — Debug page: operator testing & diagnostics dashboard
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>
2026-02-21 20:18:57 +01:00
admin be7803c0ac v0.24.0 — Pre-testing observability: debug logging, diagnostic dump, startup self-test
- Add [DEBUG] logging across all modules (backup, storage, sync, selfupdate,
  monitor, notify, report, assets, setup) gated behind logging.level: "debug"
- Add /api/debug/dump endpoint returning full controller state JSON (debug only)
- Add startup self-test validating 9 subsystems (Docker, dirs, storage, hub,
  restic repos, metrics DB) with pass/warn/fail summary
- New packages: internal/selftest, internal/util
- Constructor/signature changes: debug bool params, logger params on
  RunHealthCheck and BuildReport, smart watchdog probe logging

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 18:32:26 +01:00
admin fc97199fe2 restore.html fix 2026-02-21 17:05:04 +01:00
admin 51617f55d0 Fix build: rename _ to r in handler signatures for executeTemplate
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>
2026-02-21 16:40:40 +01:00
admin 02650e3202 v0.23.0 — CSRF protection on all browser-facing POST endpoints
Controller:
- internal/web/csrf.go (new): CsrfProtect middleware, csrfToken/csrfField helpers
- auth.go: per-session CSRF token (csrfToken field, csrfTokenForSession method)
- server.go: executeTemplate wrapper auto-injects CSRFField+CSRFToken
- main.go: wire CsrfProtect on all routes; bump to v0.23.0
- handlers.go, storage_handlers.go, handler_restore.go: executeTemplate
- All templates: CSRFField in forms, meta csrf-token, csrfHeaders() JS helper,
  fetch calls updated; sendBeacon→fetch+keepalive in storage_attach.html

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-21 16:38:56 +01:00
admin 538d367cc4 feat(controller): Hub asset syncer for logos and screenshots
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>
2026-02-21 15:29:23 +01:00
admin a5fec20d31 fix: setup wizard logo not loading
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>
2026-02-21 15:08:45 +01:00
admin 296fdbfdcb v0.22.1: Fix setup wizard bugs (detection, CSRF panic, version display, IP)
- NeedsSetup: only check for empty customer.id (not "demo-felhom")
- renderError: pass *http.Request to ensureCSRFToken (was nil → panic)
- Welcome template: remove redundant "v" prefix from version display
- IP detection: read HOST_IP env var for Docker container awareness
- docker-setup.sh: inject HOST_IP into generated docker-compose.yml
- Add logging for Hub config download in setup wizard

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 13:30:32 +01:00
admin 6eb75204b6 v0.22.0: First-run setup wizard, local infra backup, hub verification
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>
2026-02-21 12:33:17 +01:00
admin e217c3a445 v0.21.3: Push infra backup after config apply, fix double-v in events
After successful config apply, immediately push infra backup to Hub
so the config sync status updates right away. Also fix startup event
message that showed "vv0.21.2" instead of "v0.21.3".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 20:26:17 +01:00
admin 7953f657cc v0.21.2: Fix config apply on Docker bind mounts
os.Rename() fails with "device or resource busy" on bind-mounted files.
Fall back to direct os.WriteFile when rename fails.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 20:11:33 +01:00
admin e9dcba2473 v0.21.1: Add GET /api/config endpoint for live config content
New endpoint returns raw controller.yaml content (text/yaml) for Hub
live diff and pull operations. Same auth as other config endpoints.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 19:26:47 +01:00
admin 8aebbb8902 feat: Hub monitoring takeover — event push system + config cleanup (v0.21.0)
Replace external Healthchecks.io with Hub-native event system. Controller
now pushes structured events via POST /api/v1/event with typed detail
structs. Hub handles dead man's switch, notification dispatch, and cooldowns.

Phase 5: PushEvent() core method, 21 event types, expanded notification
settings (11 toggles), Hub connection monitoring on dashboard, alerts.
Phase 6: Deprecation log for ping UUIDs, pinger kept for transition.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 18:53:21 +01:00
admin 85d1f2f673 feat: add config apply endpoint and config hash in reports
- POST /api/config/apply: accepts YAML body from Hub, validates and
  writes controller.yaml atomically (tmp+rename)
- GET /api/config/hash: returns SHA256 hash of current config file
- Report payload now includes config_hash field for Hub comparison
- Config endpoints use same dual auth as self-update (session OR Bearer)
- config.LoadFromBytes() for validation without file I/O
- config.FileHash() helper for SHA256 computation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 16:13:35 +01:00
admin 8130c344cc feat: deployed app removal + missing field injection (v0.19.0)
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>
2026-02-20 11:01:21 +01:00
admin 99bf3ca7a8 feat: drive migration & Tier 2 restic deprecation (v0.18.0)
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>
2026-02-19 21:49:14 +01:00
admin bdbe170a54 feat: storage watchdog — USB disconnect detection, auto-stop, safe eject, auto-reconnect (v0.17.0)
New storage watchdog monitors registered storage paths every 5s. On disconnect
(3 consecutive probe failures), auto-stops affected apps, lazy-unmounts stale
VFS entries, fires alerts/notifications/hub report. On reconnect (UUID detected),
auto-remounts via fstab, cleans stale restic locks, offers app restart.

Safe disconnect UI for USB drives: confirmation dialog, stop apps, sync, unmount.
Disconnected state visible across all pages (dashboard, settings, backups, monitoring)
with hatched red bars and badges. Backup guards skip disconnected drives.

22 files changed (1 new: monitor/watchdog.go), ~1500 lines added.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 19:42:26 +01:00
admin 80f5cbaa28 fix: move selfupdate routes before hasSuffix stack cases in router
The selfupdate routes were placed after the generic hasSuffix(path, "/update")
stack case, which was catching /selfupdate/update before the specific case
could match it. Moving the selfupdate cases to before all hasSuffix-based
cases fixes the routing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 18:20:52 +01:00
admin 2687506b08 feat: add controller_url to hub reports (v0.16.1)
Controller now includes its external URL in periodic hub reports so the
hub can trigger self-updates remotely via the /api/selfupdate/update endpoint.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 18:16:32 +01:00
admin c9a88afcef feat: add controller self-update mechanism (v0.16.0)
New selfupdate package: version parsing, audit state file, updater with
Gitea registry V2 check, docker pull + compose rewrite + compose up flow.

- API: /api/selfupdate/{status,check,update} with session+bearer auth
- UI: Settings "Verzió és frissítés" card with check/install buttons + JS polling
- Scheduler: periodic check (6h default) + optional daily auto-update
- Notifications: success/failure on post-update startup verification
- Alert: info banner when update available
- docker-compose.yml: add directory bind mount for compose file access

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 17:33:40 +01:00
admin 4923afa6a7 v0.15.7: Fix backup page storage display & rename system drive label
- 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>
2026-02-19 16:04:36 +01:00
admin 75ea9d73f0 Fix bugs from BUGHUNT.md: restore race conditions, infra backup, DR wiring, docker-setup.sh, restore.html 2026-02-19 14:06:42 +01:00
admin 6713df2186 v0.15.5: Disaster recovery — Hub-based infra backup, auto-mount, restore UI
Complete DR implementation (TASK2.md Phases 1-4):
- Hub infra-backup push/pull endpoints (controller.yaml, disk layout, stacks)
- Fresh-deployment detection pulls config from Hub, auto-mounts drives by UUID
- Full-page restore UI with drive status, app table, sequential restore
- docker-setup.sh shows DR instructions when customer_id is configured

New files: disk_layout.go, restore_scan.go, restore_app_linux.go,
restore_drives_linux.go, infra_backup.go, infra_pull.go,
handler_restore.go, restore.html

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 13:16:46 +01:00
admin 00c668fc92 v0.15.5: Fix startup hub report — Push() returns real errors, startup retries 3x with 15s delay 2026-02-19 10:08:43 +01:00
admin f54d1a23de v0.15.4: Hub disabled notification, PushOnce, ReportingDisabled field 2026-02-19 09:45:40 +01:00
admin 215ba8a83d v0.15.3: Show all storage paths on dashboard/monitoring + fix hub report 2026-02-19 09:06:59 +01:00
admin d372454c18 v0.15.2: Fix snapshot stats and DB validation loss on restart 2026-02-19 08:45:37 +01:00
admin 2befa6877b v0.15.1: Backup page Részletek overhaul with per-drive tier sections
Replace Tároló section with collapsible Részletek containing 3 tiers:
- Tier 1: per-drive restic repo stats with storage labels
- Tier 2: cross-drive items grouped by destination, split by method
- Tier 3: remote backup placeholder
Restore UI now shows tier + drive labels in snapshot dropdown.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 08:23:33 +01:00
admin 0c0cacbe7c fix: handle oversized lines in DB dump validation
Replace bufio.Scanner with bufio.Reader.ReadLine() which gracefully
skips lines exceeding the buffer (isPrefix=true) instead of failing.
Fixes validation of Immich's PostgreSQL dump which contains COPY lines
with binary-encoded image data exceeding the 256KB scanner limit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 07:58:31 +01:00
admin debab0f38b fix: mount config.yaml at correct path for FileBrowser Quantum
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>
2026-02-18 22:21:48 +01:00
admin b06e9bb368 fix: persist FileBrowser database + sync on manual storage add
- 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>
2026-02-18 22:19:26 +01:00
admin 91c12c4b8b feat: sync FileBrowser config on startup
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>
2026-02-18 21:56:14 +01:00
admin b88c9c76e6 feat: auto-configure FileBrowser sidebar with per-drive sources
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>
2026-02-18 21:53:30 +01:00
admin 30110d3fca fix: show error for duplicate folder name + add client-side validation
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>
2026-02-18 21:37:54 +01:00
admin 6b7ca566df fix: clean up stale raw mounts before scanning in attach wizard
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>
2026-02-18 21:30:32 +01:00
admin 1d394e32ad fix: fstab write fails on bind-mounted /host-fstab (EBUSY)
rename() fails with EBUSY on Docker bind-mounted files. Add safeWriteFile()
helper that tries atomic rename first, falls back to direct write. Fixes
both init wizard and attach wizard fstab operations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 21:19:30 +01:00
admin 98834dd7e8 v0.15.0: Attach existing drive wizard (bind mount, no format)
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>
2026-02-18 21:12:02 +01:00
admin 70d503a902 fix(backup): 4 bug fixes from v0.14.1 code review (v0.14.2)
Bug 1 (HIGH): add --exclude _* to rsync --delete so _db/ and _config/
  directories are never deleted between backup runs (crossdrive.go)

Bug 2 (MEDIUM): refactor RunDBDumps/RunBackup/RunFullBackup to use
  acquireRunning/releaseRunning helpers; extract runDBDumpsInternal and
  runBackupInternal so all three public entry points set m.running and
  RunFullBackup no longer deadlocks calling the public methods (backup.go)

Bug 3 (MEDIUM): log [WARN] when GetDiskUsage returns nil in
  ValidateDestination instead of silently skipping space checks (crossdrive.go)

Bug 4 (MEDIUM): add [WARN] on empty SystemDataPath in NewManager; add
  [ERROR] in GetAppDrivePath; guard DumpStackDB against empty/relative paths
  (backup.go)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 19:46:16 +01:00