160 Commits

Author SHA1 Message Date
admin 77c61ff494 deploy: hub image 0.22.1 -> 0.23.0 (host disk monitoring)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HxLA1mZurFq9kt8hneFeCs
2026-06-30 13:51:13 +02:00
admin 83ed127d53 hub-config: enable operator email alerts (operator_email + operator_enabled)
The dispatcher's operator path was gated off (processOperator returns
unless operatorOn && operatorEmail!=""), so the self-health pipeline
stopped one hop short of the inbox. Set the operator recipient
(admin@felhom.eu — the operator's own address, not a secret) and enable.
Config-only; no image bump.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0162BnMpUXscPsUB1cU8Tr6K
2026-06-30 09:10:10 +02:00
admin 8f3b247e6e manifest: hub 0.22.0 -> 0.22.1 (HostLeafChecker wiring)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pg8ANF97SEeKYSN5Jxw3qJ
2026-06-29 23:26:37 +02:00
admin 27aa15fb93 manifest: hub 0.21.0 -> 0.22.0 (HostLeafChecker)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pg8ANF97SEeKYSN5Jxw3qJ
2026-06-29 23:16:54 +02:00
admin 575f62ab7f manifest: hub 0.20.0 -> 0.21.0 (F2 born-degraded alert)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pg8ANF97SEeKYSN5Jxw3qJ
2026-06-29 21:49:48 +02:00
admin d3661319c8 manifest: hub 0.19.0 → 0.20.0 (accept agent_channel_* events)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pg8ANF97SEeKYSN5Jxw3qJ
2026-06-29 20:38:28 +02:00
admin 2312572411 manifest: hub 0.18.0 → 0.19.0 (agent capability-degraded alert)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EPZ4GJ8L5Jqf8UiPwbn1kt
2026-06-29 18:53:22 +02:00
admin 2e749741b8 deploy: hub 0.18.0 (app-email passthrough)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 08:48:08 +02:00
admin feea06062a secrets: rotate + de-git Resend key; source from out-of-band Secret/resend-api
Resend send-scoped key was committed in plaintext in manifests/hub.yaml (ConfigMap)
and manifests/felhom.secret.yaml. Rotated to a new key and removed from git.

- hub: new RESEND_API_KEY env override (cmd/hub/main.go), mirrors REGISTRY_TOKEN;
  ConfigMap resend_api_key now an empty placeholder; Deployment injects from
  Secret/resend-api. Image 0.17.0.
- contact-mailer: secretKeyRef repointed contact-mailer-config -> resend-api.
- felhom.secret.yaml: contact-mailer-config Secret removed; healthchecks
  EMAIL_HOST_PASSWORD blanked (workload not deployed).
- documentation/runbooks/secrets.md: out-of-band secret model + create/rotate steps.

Secret/resend-api is created imperatively out-of-band and is NOT committed.
No secret value appears in this repo.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 07:50:30 +02:00
admin d5266ca009 hub v0.16.0: seed artifact manifest from env; manifests image -> 0.16.0
- cmd/hub/main.go: seed the Day-0 artifact manifest from ARTIFACT_AGENT_VERSION/
  ARTIFACT_AGENT_SHA256/ARTIFACT_GOLDEN_VERSION/ARTIFACT_GOLDEN_SHA256 on startup
  (only empty fields, so UI edits stick) — same escape hatch the floor uses.
- manifests/hub.yaml: image 0.15.0 -> 0.16.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 08:46:17 +02:00
admin d65b2f74ea manifests: hub global controller-version floor → 0.87.0 (Phase 2 live)
Persists the global floor set live during the Phase 2 floor test so git matches
the running deploy. Only demo-felhom reports (peti-felhom is config-only).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FSZmmSFVzGwEzhYmxbkgBK
2026-06-27 12:20:29 +02:00
admin e6c8ddcf7f manifests: hub image → 0.15.0 (Phase 2 managed updates)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FSZmmSFVzGwEzhYmxbkgBK
2026-06-27 12:03:04 +02:00
admin 5f5e3c54a1 hub v0.13.0: DR recipe — assemble + store + view the secret-free reconstruction recipe
DR recipe slice (hub half), grounded in SPIKE-dr-recipe-2026-06-16. The hub
receives two additive dr_recipe halves on the existing report paths (agent
storage/guest/PBS on host-report; controller customer/apps on the controller
report), stores them PLAINTEXT in a DEDICATED dr_recipe table keyed by customer
(each half preserves the other), and AssembleDRRecipe stitches them into one
operator-readable recipe (ignore-unknown + version-skew tolerant).

View: a DR-recipe panel on the customer page + GET /customers/{id}/dr-recipe.json
download (operator-auth, no secrets to redact). Plaintext-at-rest is correct —
the recipe is the clean inverse of the retired infra-backup.

Tests: store round-trip (each half preserves the other), assemble-matches-golden,
ignore-unknown + version skew, partial halves, no-secrets sweep. Manifest tag
bumped to v0.13.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 18:49:45 +02:00
admin 0635640848 hub v0.12.0: retire Infra Backup, purge its plaintext secrets, fix backup-deadline email
Phase-1 of SPIKE-infra-backup-2026-06-15. The infra-backup mechanism was dead
since slice 8C yet stored plaintext customer secrets at rest (app-secret key,
restic password, Cloudflare tokens) — a zero-knowledge violation — and its
absence made the daily expected_backup_missed email fire for healthy customers.

- Repoint monitor.CheckBackupDeadlines backup half to the agent host-report's
  PBS snapshots (+vzdump): alarm only on no-backup / >26h stale / verify failed.
  Keep the db_dump half. No host-report → no backup alarm (liveness owns that).
  New store.GetLatestHostReportJSON. Tests incl. a companion that fails pre-fix.
- Remove the infra-backup endpoints, store methods/types, and operator panel;
  /recovery now returns config_yaml only.
- migrate(): DROP infra_backup_versions/infra_backups + VACUUM (+wal_checkpoint)
  to physically reclaim the plaintext pages, gated on table existence.

Flagged out-of-scope: exposed creds need operator rotation; legacy reports table
holds historical plaintext restic_password rows (separate leak, not purged here).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 11:08:06 +02:00
admin d59691dd82 deploy: hub v0.11.0 (slice 10D DR capstone)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 09:50:33 +02:00
admin 680b1592c5 deploy: hub v0.10.0 (slice 10B signed-op job completion)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 20:24:42 +02:00
admin 8c54775b6f deploy: hub v0.9.0 (slice 10A desired-state serving)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 19:07:49 +02:00
admin a500889b00 deploy: hub v0.8.0 (opaque escrow storage)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 07:47:59 +02:00
admin 464e324c3c deploy: hub v0.7.5 (restore-test passed-with-warnings visibility)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 19:42:56 +02:00
admin 5268411014 deploy(hub): bump manifests/hub.yaml image to v0.7.4 (ingest pbs_snapshots)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 17:20:16 +02:00
admin 8db15bac16 deploy(hub): bump manifests/hub.yaml image to v0.7.3 (ingest backups + restore_tests)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 16:35:21 +02:00
admin 7b5f860a70 deploy(hub): bump manifests/hub.yaml image to v0.7.2 (host-domain ingest + storage_targets)
Live hub was v0.6.3 (pre host-report endpoint); v0.7.0-v0.7.2 were changelogged but
the manifest was never bumped. This deploys the host-domain ingest (slice 3) +
storage_targets (slice 5 Phase A). Additive/idempotent migrate(); controller path untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 10:23:08 +02:00
admin ea66afa960 manifests: pass --config to filebrowser so it reads our ConfigMap
The previous PR pinned filebrowser to v2.63.13 + runAsUser:0 which
solved the PVC permission issue, but the pod was still 0/1 Ready
because v2.63.x changed the default config-file lookup path:

  Old (v2-alpine): /.filebrowser.json (matched our existing mount)
  New (v2.63.13) : /config/settings.json (NOT mounted in this pod)

So the new image ran with its built-in defaults (port 80, in-memory
db), and the readiness probe on 8080/health timed out.

Fix: pass `args: ["-c", "/.filebrowser.json"]` so filebrowser uses the
ConfigMap we already mount there. No volumeMount changes needed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-06 14:22:04 +02:00
admin bd0531e4a8 manifests: umami -> 3.1.0 (v3 line) + filebrowser v2.63.13 with runAsUser:0
umami:
  Switch from SHA-pinned v3.0.3 to the tagged v3.1.0 release (the v3
  line proper -- same schema lineage, normal Prisma minor-version
  migration). This is the documented forward path that the version-
  checker hint `postgresql-latest -> 3.1` indicated. The v1.x
  postgresql-vX.Y.Z line we briefly tried earlier today is a
  DIFFERENT image lineage with incompatible migrations -- avoid.

filebrowser:
  Re-pin to v2.63.13 (debian-based default) so Renovate can track
  future bumps. The non-root UID in that image can't write to the
  existing PVC contents (chowned to root by the previous v2-alpine
  image), so set pod-level securityContext runAsUser:0 + runAsGroup:0
  to keep using the same volume layout without a chown initContainer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-06 14:17:20 +02:00
admin 7e6ea9d66c manifests: pin umami to exact image SHA (schema mismatch with v1.38.0)
Previous PR pinned `ghcr.io/umami-software/umami:postgresql-v1.38.0`.
The new pod crashlooped on Prisma:

  ERROR: relation "event" does not exist
  Migration name: 02_add_event_data
  Database error code: 42P01

The 120-day-old working pod's actual image is:
  ghcr.io/umami-software/umami@sha256:28f263fe06f79ebffa5a6a6e9b...

It runs an older umami build whose schema doesn't have the `event`
table that the v1 migration `02_add_event_data` operates on. The DB
has migrations 10-14 applied (newer than 02 by name) but 02 isn't in
its applied set -- likely a schema fork between the line our 120d pod
runs and the postgresql-vX.Y.Z line that v1.38.0 advances toward.

Pin to the exact SHA that the working pod uses, so pod restarts +
ArgoCD syncs both keep producing pods on the same known-good image
(cached on the node, no registry pull needed). Renovate also stops
chasing the broken upgrade path.

Proper fix (deferred): plan a v3.x migration. The version-checker
dashboard hint `postgresql-latest → 3.1` suggests umami v3.x dropped
the `postgresql-` prefix and is what we'd want long-term. That needs
a real DB migration plan since the schema lineage is genuinely
different from this image.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-06 13:53:54 +02:00
admin df2a1259d9 manifests: revert filebrowser v2.63.13 -> v2-alpine (PVC permission issue)
The previous PR pinned `filebrowser/filebrowser:v2-alpine` to v2.63.13
but it crashlooped on:

  Error: open /database/filebrowser.db: permission denied

The v2.63.13 image (debian-based default) runs as a non-root UID and
can't write to files on the PVC that were created by the v2-alpine
image (which ran as root). No `v2.63.13-alpine` tag exists upstream
(filebrowser stopped publishing per-version alpine variants), so we
can't trivially preserve the same runtime.

Quick recovery: revert to v2-alpine so filebrowser is usable again.
Proper fix (deferred): either an initContainer that `chown -R 1000:1000
/database /srv` or a `securityContext.fsGroup: 1000` on the pod spec
to let the non-root UID write to the existing PVC. Both require some
care since the chown is destructive if the UID is wrong.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-06 13:45:18 +02:00
admin ce80dce497 manifests: re-pin moving tags so Renovate can track them
- umami       postgresql-latest  -> postgresql-v1.38.0
  - filebrowser v2-alpine          -> v2.63.13

These two were "latest"-style moving tags that Renovate physically
cannot propose updates for. Pinning to current upstream versions so
future bumps go through the normal Renovate PR flow.

Note: Renovate operates from the homelab-manifests repo, not this one
yet — but felhom-system/* copies exist in homelab-manifests for
discoverability, and Renovate already tracks the pinned forms via a
new customManager for the umami `postgresql-vX.Y.Z` pattern (added in
homelab-manifests admin-system/renovate.yaml). For now, future bumps
will need to be applied to both repos until we consolidate the source
of truth.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-06 13:41:50 +02:00
admin 8aa4104586 6.3 2026-06-06 10:29:41 +02:00
admin ac43d0cbf5 deploy: hub v0.6.2
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 14:50:15 +01:00
admin 2a83a4e96c deploy: hub v0.6.1
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 16:04:12 +01:00
admin 23cb487348 deploy: hub v0.6.0 2026-02-25 12:45:02 +01:00
admin d94ac7b65d deploy: hub v0.5.1
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 12:00:48 +01:00
admin 61ef1a3952 removed healthchecks page 2026-02-25 10:25:07 +01:00
admin bc23141879 deploy: hub v0.5.0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 09:37:34 +01:00
admin a7acae11fe fix: hub manifest image tag needs v prefix
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 15:09:08 +01:00
admin 4636991fcd deploy: hub v0.4.1
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 15:08:14 +01:00
admin 09ad08d511 deploy: hub v0.4.0 — app telemetry analytics dashboard
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 10:49:29 +01:00
admin af601a1297 deploy hub v0.3.8
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-21 16:43:54 +01:00
admin 3690c5028e feat(hub): asset management API with PVC storage and image seed
Add internal/assets package that manages app assets (logos, screenshots)
on Hub PVC with automatic seeding from baked-in image copy on first run.
Two new API endpoints: GET /assets/manifest (JSON with SHA-256 checksums)
and GET /assets/file/{name} for controllers to sync assets.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 15:22:45 +01:00
admin df4d0a2255 manifests: bump hub to v0.3.6
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 14:32:55 +01:00
admin 165c59e84b Update hub manifest to v0.3.5
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 12:40:19 +01:00
admin 9048e1adad hub v0.3.4: Rename version labels for clarity
"Current version" → "Controller version", "Latest version" → "Registry latest"
to avoid confusion when running version is ahead of registry cache.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 21:29:04 +01:00
admin 6dd72f1408 hub v0.3.3: Fix version double-v prefix, skip deprecated ping_uuids in diff
- Remove extra "v" prefix from ControllerVersion display (was "vv0.21.1")
- Add monitoring.ping_uuids.* to volatile keys — skipped in config diff
- Update manifest to v0.3.3

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 19:57:01 +01:00
admin 20cd7960bd Update hub manifest to v0.3.2
ArgoCD syncs from this manifest — must update here for deployments
to stick.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 19:41:55 +01:00
admin 7859e1182e deploy: bump hub to v0.2.2
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 16:15:56 +01:00
admin dec8b19ac2 manifests: bump hub image to v0.2.1
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 15:58:52 +01:00
admin b07132f617 secret updated 2026-02-20 14:13:27 +01:00
admin 95bb261fa8 feat: registry credentials from k8s Secret via env vars
- main.go: REGISTRY_USERNAME / REGISTRY_TOKEN env vars override config file
- manifests/hub.yaml: reference Secret/gitea-creds, remove plaintext creds from ConfigMap

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 14:11:10 +01:00
admin 0fcc7d8e6f docs: add hub CHANGELOG.md, update ConfigMap with registry section
- hub/CHANGELOG.md: new file with v0.2.0 and prior version history
- manifests/hub.yaml: add registry config (version checker + template fetcher),
  pin image to v0.2.0, remove stale /healthz TODO comment

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 14:03:39 +01:00
admin c9abc6bb9e added resend api key 2026-02-16 19:45:09 +01:00