Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 21 additions & 4 deletions k8s/homepage/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,13 @@ so forward-auth can't block the widget's API calls.
`homepage-secrets` is managed end-to-end by ESO + BWS as of #135 Task 8:

- Values live in BWS (Bitwarden Secrets Manager) → `homelab` project →
one entry per `homepage-secrets` key (`octoprint-api-key`,
`grafana-user`, `grafana-password`).
one entry per `homepage-secrets` key (currently just
`octoprint-api-key`).
- `external-secret.yaml` (Flux-owned via `clusters/gandalf/homepage.yaml`)
declares the keys + their BWS secret-IDs; ESO syncs the in-cluster
`homepage-secrets` Secret from BWS every `refreshInterval`.
- The Bitwarden password vault item (`Homelab OctoPrint`,
`Homelab Grafana`) stays populated as a DR mirror -- same pattern as
- The Bitwarden password vault item (`Homelab OctoPrint`) stays
populated as a DR mirror -- same pattern as
`Homelab Restic Repository`.
- No `kubectl create secret` step. Adding a new widget secret means:
(a) put the value in BWS in the `homelab` project, then
Expand Down Expand Up @@ -168,6 +168,23 @@ so forward-auth can't block the widget's API calls.
The widget points at `http://192.168.50.118:5000` directly (Homepage pod →
LAN), so it works regardless of the public Ingress.

**Grafana** is a **link tile, not a live widget** (#155).
Homepage's `grafana` widget makes a mandatory `GET /api/admin/stats` call,
and that endpoint is gated by Grafana *server admin*.
Grafana OSS can't grant server-admin to a service account:
the `isGrafanaAdmin` flag doesn't persist on a SA,
an org-`Admin` SA token still gets 403,
and the RBAC role-assignment API (`fixed:*:reader`) is Enterprise-only.
The only credential that satisfies the widget is a server-admin *user*,
which would put root-on-Grafana in the Homepage pod for a counts tile --
below the least-privilege bar we hold every other widget to.
A Viewer-scoped SA token *can* read the underlying counts via non-admin
endpoints (`/api/search?type=dash-db`, `/api/datasources`,
`/api/alertmanager/grafana/api/v2/alerts`),
but only Homepage's one-endpoint-per-tile `customapi` widget can consume them,
which doesn't reproduce the built-in 4-stat layout.
Not worth the complexity for low-value counts, so Grafana stays a plain href.

## External bookmarks

The `config.bookmarks` block in `values.yaml` is a quick-launch dashboard for
Expand Down
6 changes: 0 additions & 6 deletions k8s/homepage/external-secret.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,3 @@ spec:
- secretKey: octoprint-api-key
remoteRef:
key: 413ae347-cc2e-43c0-8964-b45a016c6463 # gitleaks:allow
- secretKey: grafana-user
remoteRef:
key: df2f3ffd-9ae9-4f2a-b2d0-b45a016c6909 # gitleaks:allow
- secretKey: grafana-password
remoteRef:
key: 36d29c85-7184-4cd8-9041-b45a016c6da8 # gitleaks:allow
10 changes: 3 additions & 7 deletions k8s/homepage/secret.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ stringData:
# Generated in OctoPrint: Settings -> Application Keys (or a user API key).
# Surfaced as HOMEPAGE_VAR_OCTOPRINT_API_KEY for the octoprint widget.
octoprint-api-key: REPLACE_WITH_OCTOPRINT_API_KEY

# Grafana widget basic-auth creds — a dedicated Viewer-role Grafana login
# (Homepage's grafana widget uses basic auth, not an API token). Bitwarden
# item 'Homelab Grafana', fields 'homepage-user' + 'homepage-password'.
# Surfaced as HOMEPAGE_VAR_GRAFANA_USER / HOMEPAGE_VAR_GRAFANA_PASSWORD.
grafana-user: REPLACE_WITH_GRAFANA_HOMEPAGE_USER
grafana-password: REPLACE_WITH_GRAFANA_HOMEPAGE_PASSWORD
# Grafana has no entry here: its Homepage tile is a plain link, not a live
# widget. The widget needs server-admin (GET /api/admin/stats), which Grafana
# OSS can't scope to a service account. See README "Service widgets" and #155.
29 changes: 8 additions & 21 deletions k8s/homepage/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -73,19 +73,6 @@ env:
secretKeyRef:
name: homepage-secrets
key: octoprint-api-key
# Grafana widget creds — a dedicated Viewer-role Grafana login (Homepage's
# grafana widget uses basic auth, not an API token). From homepage-secrets
# (Bitwarden 'Homelab Grafana' / homepage-user + homepage-password).
- name: HOMEPAGE_VAR_GRAFANA_USER
valueFrom:
secretKeyRef:
name: homepage-secrets
key: grafana-user
- name: HOMEPAGE_VAR_GRAFANA_PASSWORD
valueFrom:
secretKeyRef:
name: homepage-secrets
key: grafana-password

config:
# Hand-curated initial list pointing at current *.home services.
Expand Down Expand Up @@ -135,14 +122,14 @@ config:
href: https://grafana.vigihome.net
description: Dashboards & metrics
icon: grafana.png
# Live widget — hits Grafana's in-cluster Service directly (not the
# Authentik-gated Ingress) using a dedicated Viewer login. Creds via
# HOMEPAGE_VAR_GRAFANA_USER/PASSWORD (homepage-secrets). See README.
widget:
type: grafana
url: http://kps-grafana.monitoring.svc.cluster.local
username: "{{HOMEPAGE_VAR_GRAFANA_USER}}"
password: "{{HOMEPAGE_VAR_GRAFANA_PASSWORD}}"
# Link tile, not a live widget. Homepage's grafana widget requires
# GET /api/admin/stats, which is gated by Grafana *server admin*.
# Grafana OSS can't grant server-admin to a service account
# (isGrafanaAdmin doesn't persist on a SA; org-Admin still 403s; the
# RBAC role-assignment API is Enterprise-only). The only credential
# that satisfies the widget is a server-admin user — handing the
# Homepage pod root-on-Grafana for a counts tile, which fails the
# least-privilege bar. So Grafana stays a plain href here. See #155.

widgets:
- kubernetes:
Expand Down
27 changes: 6 additions & 21 deletions k8s/kube-prometheus-stack/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ Chart: `prometheus-community/kube-prometheus-stack` v`85.3.3`
- `oidc-client-secret` — `openssl rand -hex 64`
- `admin-user` — e.g. `admin-local` (the local-admin fallback)
- `admin-password` — a strong password
- `homepage-user` / `homepage-password` — added in step 7 for the widget

## One-time install

Expand Down Expand Up @@ -137,26 +136,12 @@ prerequisites (secrets, PV, blueprint, reflected SMTP) must exist **before**
minutes. If the exact Service/StatefulSet names differ by release, confirm
with `kubectl -n monitoring get svc,sts` and adjust the targets below.

7. **Add the Homepage Grafana widget creds.** Create a dedicated
**Viewer**-role Grafana login (Grafana UI → Administration → Users →
add `homepage`), store it in Bitwarden vault item `Homelab Grafana`
under custom fields `homepage-user` and `homepage-password`, then
put the same two values in BWS (Secrets Manager → `homelab` project,
secret names `grafana-user` and `grafana-password`). ESO + the
Homepage Flux Kustomization handle the in-cluster `homepage-secrets`
Secret from there -- no `kubectl create secret` step. See
`../homepage/README.md` for the BWS migration script.

Then `helm upgrade` so the new Grafana widget config in
`k8s/homepage/values.yaml` loads:

```sh
helm upgrade homepage jameswynn/homepage -n homepage --version 2.1.0 -f k8s/homepage/values.yaml
```

Issue #155 tracks switching this Grafana login to a service-account +
bearer-token model; once that lands, `grafana-user`/`grafana-password`
in BWS get replaced with a single `grafana-token` entry.
7. **No Homepage-widget step.** Grafana appears on Homepage as a **plain
link tile**, not a live widget. The widget needs `GET /api/admin/stats`,
which Grafana *server admin* gates, and Grafana OSS can't scope that to a
service account — handing the Homepage pod a server-admin user just for a
counts tile fails the least-privilege bar. Closed in #155; rationale in
`../homepage/README.md` "Service widgets".

## Verify

Expand Down
Loading