Commit Graph

82 Commits

Author SHA1 Message Date
admin 17db33e419 docs: update CHANGELOG and README for v0.30.5 health probe changes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 15:08:51 +01:00
admin db83db383c fix: deep bug hunt II — concurrency, security & optimization (25 files)
Critical: watchdog mutex panic safety, SetGeoAppOverride nil guard,
SSD-only app DB restore fallback.

High: double deploy race (atomic Deploying flag), delete/remove during
deploy guard, ScanStacks overwrite protection, FileBrowser mount mutex,
PushEvent history, PushOnce error handling, DB dump sync+close before
rename, restic retry fresh context, encrypt failure logging, cross-backup
path traversal validation, deepCopyStack completeness.

Security: constant-time API key comparison, login rate limiting (5/min),
git credential masking in logs, storage path prefix traversal fix.

Concurrency: MigrateEncryption lock ordering, SubdomainInUse I/O outside
lock, scheduler late-registered jobs, SQLite WAL verification, metrics
shutdown context, telemetry scan error logging, asset sync lock scope.

Optimization: streaming file copy for DB dumps, restic stats dedup,
atomic infra config copy.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 14:21:09 +01:00
admin 72ab145b41 docs: add v0.30.3 changelog entry for comprehensive bug hunt fixes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 13:48:47 +01:00
admin 2ad743b66f v0.30.2: Report geo-restriction + logo/favicon update + Hub geo auth
- Add GeoRestrictionReport to report types and builder, so Hub can
  display geo-blocking status on customer detail pages
- Update all 5 BuildReport() call sites with new geoRestriction param
- Add /api/geo/ to selfUpdateAuthMiddleware (Hub Bearer token auth)
- Replace embedded logo SVG with updated logo.svg (white text variant)
- Add FelhomFaviconSVG constant + /static/favicon.svg route
- Update layout.html and catchall.html favicon links

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 12:42:51 +01:00
admin 9ed5e78c45 fix: remove custom block response from WAF rules (CF free plan)
Cloudflare Free plan doesn't support custom response body in block
rules. Use plain block action which returns CF's default 403 page.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 12:03:01 +01:00
admin e1fb85240b feat: geo-restriction via Cloudflare WAF custom rules
Add country-based access control managed through the Settings page.
Global allow-list with per-app overrides, searchable country selector,
automatic sync to Cloudflare WAF on settings change / deploy / remove,
plus periodic 6-hour verification.

New package: internal/cloudflare/ (client, zone, waf, countries, geosync)
New API: /api/geo/* (6 endpoints) + /api/stacks/{name}/geo/override

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 11:58:22 +01:00
admin 4c5d430b1a feat: controller-side HTTP/TCP health probes
Add network-level health probing from the controller to deployed apps.
The controller probes containers over the shared Docker network and
overrides stack state to "unhealthy" if the service isn't responding.

Three probe types: http (any response = alive), api (validates status
code and body content), tcp (port reachability). Configured per-app
via healthcheck: section in .felhom.yml. Runs every minute, per-app
interval defaults to 5 minutes.

This replaces Docker-level healthchecks for distroless images (e.g.
Vikunja) that lack shell utilities, and complements existing Docker
healthchecks for other apps.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 11:11:21 +01:00
admin 077640d9bb feat: dynamic logo from synced assets + SVG favicon
Logo handler now checks Hub-synced assets first, falling back to
embedded SVG. Added SVG favicon to layout and catchall templates.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 09:34:38 +01:00
admin 0c687ae280 fix: remove stale git lock files before catalog sync
Catalog sync could fail permanently if the container was killed mid-fetch,
leaving behind .git/shallow.lock (or index.lock, HEAD.lock). Now cleaned
up automatically before each git fetch.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 20:09:38 +01:00
admin 44f7fd2f19 feat: encrypt sensitive values in app.yaml with AES-256-GCM
Passwords and secrets from deploy fields (type: password/secret) are now
encrypted at rest in app.yaml using a per-node 32-byte key. Values stored
as ENC:base64(nonce+ciphertext), decrypted transparently for docker-compose
and web UI. Key included in infra backup bundle for disaster recovery.
Existing plaintext values migrated automatically on startup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 19:12:24 +01:00
admin 703dee15ab docs: changelog for v0.28.8
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 18:42:03 +01:00
admin a61bf4bc18 docs: changelog for v0.28.7
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 16:34:53 +01:00
admin e3a54f2ff8 docs: changelog for post-deploy credential display
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 16:18:07 +01:00
admin c795b47856 docs: changelog update for log timestamp fix
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 16:02:50 +01:00
admin 1183a29d3e docs: changelog for v0.28.6
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 15:53:43 +01:00
admin a30f4c0234 feat: post-deploy info card with app link, first steps, and credentials
After successful deploy, shows a rich info card instead of auto-redirecting
to the apps list. Includes direct app link, first steps from catalog metadata,
default credentials info, and link to settings page for password reveal.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 15:27:33 +01:00
admin e737704e68 fix: skip stopped apps in telemetry to avoid zero-value averages on hub
Deployed-but-stopped apps were included in telemetry reports with all-zero
memory/CPU values, dragging down hub-side averages. Now isStackRunning()
filters to only running/starting/unhealthy/restarting states.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 15:05:39 +01:00
admin df165f7ef0 feat: catch-all page for stopped apps, deploy controls, dashboard open button
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>
2026-02-23 13:38:53 +01:00
admin aaf479356a fix(stacks): RestartStack now uses up -d with env vars
Previously used bare "docker compose restart" which doesn't inject
env vars or pick up template changes. Now matches StartStack behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 12:17:23 +01:00
admin 563cf07ec8 feat(deploy): async compose-up for instant UI feedback (v0.28.2)
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>
2026-02-23 12:08:08 +01:00
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 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 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 a2848f6d67 fix(felhom-wipe): nuclear wipe stops early due to set -e + missing state files
[ -f "$f" ] && rm -f "$f" && info "..." returns exit code 1 when the
file doesn't exist, triggering set -euo pipefail. Nuclear wipe was
silently stopping after settings.json and metrics.db (the only two
state files present), never reaching the controller/full/nuclear steps.

Fix: if [ -f "$f" ]; then rm -f "$f" && info "..."; fi

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 12:03:56 +01:00
admin 49b3611f39 scripts: FileBrowser volumes controller-managed, remove drive auto-discovery
- docker-setup.sh install_filebrowser(): removed /mnt/* auto-discovery;
  FileBrowser now installed with no drive volumes. Initial config.yaml
  written with /srv fallback. Controller's SyncFileBrowserMounts() takes
  over on first startup and manages volumes/config going forward.
- Added ./config.yaml bind mount to initial docker-compose.yml so
  FileBrowser starts correctly before controller syncs.
- Fixed ((step_num++)) → step_num=$(( step_num + 1 )) to prevent
  set -euo pipefail trap when var starts at 0 (same class of bug as
  the found_mounts fix in the previous commit).
- scripts/README.md: step 7 updated to reflect controller-managed volumes.
- CHANGELOG.md: added entry for all scripts changes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 11:53:46 +01:00
admin a5f8c7a76c docs: clarify felhom-wipe.sh full level preserves infra containers
'full' was ambiguously described as 'Controller + felhom-data/' making
it sound like the controller container is removed. Clarified that 'full'
runs controller-level cleanup (app containers only) and infra containers
(felhom-controller, traefik, etc.) are preserved throughout.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 10:25:19 +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 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 55abe401ee docs: update controller README and CHANGELOG for v0.20.0
Add config apply endpoint and config hash in reports to REST API
section, roadmap, and changelog.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 16:18:26 +01:00
admin ff8b42bfd8 docker-setup.sh: add --hub-customer/--hub-password flags for Hub config download
When both flags are provided, the wizard downloads a pre-configured
controller.yaml from the Hub API, extracts key variables for subsequent
setup steps, and skips the interactive wizard entirely. Falls back to
manual wizard on failure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 13:36:44 +01:00
admin 2eccac4b6d updated README and CHANGELOG 2026-02-20 11:20:13 +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 276be5a88e docs: update CHANGELOG.md and CONTEXT.md for v0.16.1 + hub v0.1.8
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 18:29:41 +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