ccnet-homepage-swarm: internal-only Homepage dashboard (Phase 1) #67

Merged
copper merged 3 commits from ccnet-homepage-swarm into main 2026-09-17 20:58:23 +00:00
Collaborator

What

New Swarm stack for dash.coppercore.net — a Homepage
launcher + status board for the whole homelab: grouped links to every service
plus API-backed health widgets for the ~13 that ship one. Seeded from
docs/ccnet-infra-snapshot-2026-09-10.md (PR #66). Plan:
~/.claude/plans/now-with-that-set-cryptic-milner.md.

Docs + stack only — the deploy is the user's to run (every credential is
theirs to mint). This PR is the authoring half.

Contents

  • homepage-swarm-stack.yml — image pinned v2.3.0; 14 Docker secrets
    surfaced via Homepage's native HOMEPAGE_FILE_* mechanism (no entrypoint
    wrapper, unlike SearXNG); port 8092→3000; replicas: 2,
    max_replicas_per_node: 1, no role constraint (stateless web tier).
  • config/ — settings / services (grouped tiles + widgets) /
    widgets / bookmarks, checked in with {{HOMEPAGE_FILE_*}} placeholders
    and non-sensitive identifiers only, no secret values.
  • README.md — full runbook: mint 13 dedicated least-privilege credential
    identities, create the secrets, CephFS dir, deploy, onboard + hand-issue the
    cert (per ccnet-swarmpit-swarm/README.md §5), verify. Plus a Phase 2
    appendix (manager-pinned docker-socket-proxy for live container/Swarm
    discovery — a deliberate separate follow-up).
  • CLAUDE.md — design deviations.

Repo-wide

  • Root CLAUDE.md: stack map entry + a new cross-cutting convention —
    every service onboarded from now on gets a Homepage tile in
    config/services.yaml, same step as the service_onboard.py DNS/Caddy
    wiring. dash.coppercore.net is the canonical index of running services.
  • ccnet-service-onboard/README.md + docs/homelab-architecture.md note the
    same.

Not in this PR / follow-ups

  • Phase 2 (live Docker/Swarm discovery) — separate PR once Phase 1 is proven.
  • <viewer-username> / <site-name> placeholders in services.yaml are
    filled in by hand during Step 1 (identifiers, not secrets).
  • Home Assistant / Omada / UniFi widget URLs use resolved IPs; HA is at
    10.10.10.150 per ccnet-mosquitto-swarm/README.md.

Side change (user-requested, already applied live)

Added Unbound overrides node07.pve.coppercore.net → 10.10.10.207 and
node07-ceph.pve.coppercore.net → 10.10.35.207 (the one cluster node with
no DNS entry). bookmarks.yaml uses the hostname.

🤖 Generated with Claude Code

## What New Swarm stack for **`dash.coppercore.net`** — a [Homepage](https://gethomepage.dev) launcher + status board for the whole homelab: grouped links to every service plus API-backed health widgets for the ~13 that ship one. Seeded from `docs/ccnet-infra-snapshot-2026-09-10.md` (PR #66). Plan: `~/.claude/plans/now-with-that-set-cryptic-milner.md`. **Docs + stack only — the deploy is the user's to run** (every credential is theirs to mint). This PR is the authoring half. ## Contents - **`homepage-swarm-stack.yml`** — image pinned `v2.3.0`; 14 Docker secrets surfaced via Homepage's native `HOMEPAGE_FILE_*` mechanism (no entrypoint wrapper, unlike SearXNG); port `8092`→`3000`; `replicas: 2`, `max_replicas_per_node: 1`, no role constraint (stateless web tier). - **`config/`** — `settings` / `services` (grouped tiles + widgets) / `widgets` / `bookmarks`, checked in with `{{HOMEPAGE_FILE_*}}` placeholders and non-sensitive identifiers only, **no secret values**. - **`README.md`** — full runbook: mint 13 dedicated least-privilege credential identities, create the secrets, CephFS dir, deploy, onboard + hand-issue the cert (per `ccnet-swarmpit-swarm/README.md` §5), verify. Plus a Phase 2 appendix (manager-pinned `docker-socket-proxy` for live container/Swarm discovery — a deliberate separate follow-up). - **`CLAUDE.md`** — design deviations. ## Repo-wide - Root `CLAUDE.md`: stack map entry **+ a new cross-cutting convention** — every service onboarded from now on gets a Homepage tile in `config/services.yaml`, same step as the `service_onboard.py` DNS/Caddy wiring. `dash.coppercore.net` is the canonical index of running services. - `ccnet-service-onboard/README.md` + `docs/homelab-architecture.md` note the same. ## Not in this PR / follow-ups - Phase 2 (live Docker/Swarm discovery) — separate PR once Phase 1 is proven. - `<viewer-username>` / `<site-name>` placeholders in `services.yaml` are filled in by hand during Step 1 (identifiers, not secrets). - Home Assistant / Omada / UniFi widget URLs use resolved IPs; HA is at `10.10.10.150` per `ccnet-mosquitto-swarm/README.md`. ## Side change (user-requested, already applied live) Added Unbound overrides `node07.pve.coppercore.net` → `10.10.10.207` and `node07-ceph.pve.coppercore.net` → `10.10.35.207` (the one cluster node with no DNS entry). `bookmarks.yaml` uses the hostname. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
New Swarm stack for dash.coppercore.net — a launcher + status board for
the whole homelab: grouped links to every service plus API-backed health
widgets for the ~13 that ship one. Seeded from the 2026-09-10 infra
snapshot. Pattern follows ccnet-searxng-swarm/ (stateless web tier,
replicas 2, CephFS config bind-mount, internal-only via OPNsense Caddy +
hand-issued cert).

- homepage-swarm-stack.yml: image pinned v2.3.0, 14 Docker secrets via
  Homepage's native HOMEPAGE_FILE_* mechanism (no entrypoint wrapper),
  port 8092 -> 3000, replicas 2 / max 1 per node, no role constraint.
- config/: settings, services (grouped tiles + widgets), widgets, bookmarks
  — checked in with {{HOMEPAGE_FILE_*}} placeholders, no secret values.
- README.md: full runbook (mint 13 credential identities, create secrets,
  CephFS dir, deploy, onboard + ACME cert per swarmpit runbook, verify)
  plus a Phase 2 appendix (docker-socket-proxy for live discovery).
- CLAUDE.md: design deviations.
- Live Docker/Swarm discovery is a deliberate Phase 2 follow-up PR.

Repo-wide: root CLAUDE.md gains the stack entry and a new cross-cutting
convention — every service onboarded from now on gets a Homepage tile,
same step as the service_onboard.py DNS/Caddy wiring. Noted in
ccnet-service-onboard/README.md and docs/homelab-architecture.md.

Deploy is the user's to run (all credentials are theirs to mint).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011Z5XpoqyYLm8W8DXKmskcU
copper requested review from copper 2026-09-12 13:06:37 +00:00
copper changed title from ccnet-homepage-swarm: internal-only Homepage dashboard (Phase 1) to WIP: ccnet-homepage-swarm: internal-only Homepage dashboard (Phase 1) 2026-09-12 13:06:38 +00:00
Owner

I will be re-revewing this and deploying this today,

I will be re-revewing this and deploying this today,
claude-bot changed title from WIP: ccnet-homepage-swarm: internal-only Homepage dashboard (Phase 1) to ccnet-homepage-swarm: internal-only Homepage dashboard (Phase 1) 2026-09-17 20:15:29 +00:00
Author
Collaborator

Rebased onto current main (was 7 days behind — commits #73–#83) and pushed. Only real conflict was CLAUDE.md's conventions list (adjacent edits: this PR's "every service gets a Homepage tile" bullet vs. main's "never push through Swarmpit's update_stack" bullet + dvr cert-list entry) — resolved keeping both sides, nothing dropped. mergeable should recompute to true now that merge_base == main tip.

Pre-flight checks run live before re-review, per the plan's Step 6/7b:

  • Port 8092 — confirmed free on all 5 swarm nodes (.211/.212/.213/.221/.222).
  • Image tag v2.3.0 — still fine to ship; v2.4.0 released today (2026-09-17), too fresh to jump on same-day.
  • Mailcow reachability (Step 7b / issue #68) — checked from a manager: 10.10.50.10:443 resets the TLS handshake (Connection reset by peer), not a timeout. This is an active reject, not silent drop — a firewall pass rule will be needed for the mailcow widget to work, contrary to the "probably not needed" guess in the plan. Left as-is per the plan (user decision, tracked in #68) — no OPNsense change made.
  • Flagging for the actual deploy: the plan calls out an unresolved {{HOMEPAGE_FILE_x}} vs {{HOMEPAGE_VAR_x}} token form in Step 8 — settle it on the first widget before wiring all 14, since a mismatch there reads as "Unauthorized" everywhere and is easy to chase in the wrong place.

No stack/config edits made — Steps 1–8 (mint 14 credentials → secrets → CephFS dir → deploy → onboard/cert → verify) are unchanged from README.md and still yours to run.

Rebased onto current `main` (was 7 days behind — commits #73–#83) and pushed. Only real conflict was `CLAUDE.md`'s conventions list (adjacent edits: this PR's "every service gets a Homepage tile" bullet vs. main's "never push through Swarmpit's `update_stack`" bullet + `dvr` cert-list entry) — resolved keeping both sides, nothing dropped. `mergeable` should recompute to `true` now that `merge_base` == `main` tip. Pre-flight checks run live before re-review, per the plan's Step 6/7b: - **Port `8092`** — confirmed free on all 5 swarm nodes (.211/.212/.213/.221/.222). - **Image tag `v2.3.0`** — still fine to ship; `v2.4.0` released today (2026-09-17), too fresh to jump on same-day. - **Mailcow reachability (Step 7b / issue #68)** — checked from a manager: `10.10.50.10:443` resets the TLS handshake (`Connection reset by peer`), not a timeout. This is an active reject, not silent drop — a firewall pass rule **will** be needed for the `mailcow` widget to work, contrary to the "probably not needed" guess in the plan. Left as-is per the plan (user decision, tracked in #68) — no OPNsense change made. - **Flagging for the actual deploy**: the plan calls out an unresolved `{{HOMEPAGE_FILE_x}}` vs `{{HOMEPAGE_VAR_x}}` token form in Step 8 — settle it on the first widget before wiring all 14, since a mismatch there reads as "Unauthorized" everywhere and is easy to chase in the wrong place. No stack/config edits made — Steps 1–8 (mint 14 credentials → secrets → CephFS dir → deploy → onboard/cert → verify) are unchanged from `README.md` and still yours to run.
copper merged commit cc60e38f68 into main 2026-09-17 20:58:23 +00:00
Sign in to join this conversation.
No description provided.