Skip to content

Split Grafana into public and private instances - #190

Merged
kondratyevd merged 3 commits into
mainfrom
grafana-private-split
Sep 7, 2026
Merged

Split Grafana into public and private instances#190
kondratyevd merged 3 commits into
mainfrom
grafana-private-split

Conversation

@kondratyevd

Copy link
Copy Markdown
Collaborator

Summary

Replaces the single Grafana instance (which mixed public and private dashboards) with two instances:

  • grafana (unchanged URL, /grafana) — anonymous viewer access, now serves only the public dashboards. The private dashboard provider and ConfigMap mount were removed from its values.
  • grafana-private (new, /grafana-private) — serves the private dashboards (users-overview, pyroscope); anonymous auth is disabled, so nothing is visible without logging in. Admin credentials come from the chart-generated grafana-private Secret (admin-user / admin-password keys).

Implementation

Kept as close to the existing pattern as possible:

  • New helmrelease-private.yaml — identical to the public one except for the name and its values ConfigMap (grafana-private-config).
  • New values-private.yaml — a trimmed copy of values.yaml: same chart version, persistence (own RWO PVC + SQLite + Recreate strategy), security context, and datasources. Differences: ingress path /grafana-private, auth.anonymous.enabled: false, only the private dashboard provider/ConfigMap, home dashboard set to users-overview, and it drops the public-only pieces (announcements nginx sidecar, /work mount, Infinity datasource, dynamictext plugin).
  • Both overlays (core-production, core-geddes2) gain the HelmRelease resource and a grafana-private-config generator; the existing grafana-private-dashboards ConfigMap is reused as-is.

Resources for the private instance are set to 1 CPU / 2Gi (vs 4 CPU / 8Gi for the public one) since it only serves logged-in admins — easy to bump if that proves too small.

Validation

./.github/workflows/validate-manifests.sh passes (kustomize + envsubst + kubeconform + helm template of both Grafana releases). Also rendered grafana-private manually and confirmed: own PVC, ingress at /grafana-private (Prefix matching does not overlap with /grafana), [auth.anonymous] enabled = false, and only grafana-private-dashboards mounted.

🤖 Generated with Claude Code

Deploy a second HelmRelease, grafana-private, that serves the private
dashboards behind admin login only (anonymous auth disabled), reachable
at /grafana-private. The existing grafana instance keeps anonymous
viewer access but now serves only the public dashboards.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@codecov

codecov Bot commented Sep 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 10be167863

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/monitoring/grafana/values-private.yaml Outdated
kondratyevd and others added 2 commits September 1, 2026 14:52
- Transitional cleanup: keep the "private" dashboard provider on the
  public instance pointed at an empty dir so Grafana deletes the
  previously provisioned private dashboards from its database (dropping
  the provider alone would have left them visible to anonymous users).
  Remove the provider and its emptyDir after one deploy.
- Deduplicate datasources into a shared datasources.yaml merged into
  both instances via a second valuesFrom entry on each HelmRelease.
- Pin the pyroscope datasource uid and reference it from pyroscope.json
  (was hard-coded to an auto-generated uid that only exists in the old
  database) — flagged by Codex review.
- Remove grafana-llm-app and the plugins-provisioning ConfigMap
  entirely (unused; also fixes the missing-ConfigMap mount on geddes2),
  drop grafana-pyroscope-app, and trim public plugins to the two that
  phys390.json actually uses. The private instance needs no plugins.
- Drop the dead commented-out OPENAI_API_KEY env block.

Verified against the live public instance that the provisioned private
dashboards carry no UI edits beyond git (only Flux $$-escaping differs),
so nothing needs migrating before cleanup.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Add announcements-nginx-conf.yaml to core-geddes2 resources: the
  shared public values mount that ConfigMap (grafana container and
  announcements sidecar), but the overlay never created it — the same
  missing-ConfigMap gap fixed earlier for plugins-provisioning.
- Add a transitional init container on the public instance that deletes
  grafana-llm-app and grafana-pyroscope-app from the plugins PVC;
  GF_INSTALL_PLUGINS only installs, so the removed plugins would keep
  loading on every restart otherwise. Remove together with the
  private-dashboards cleanup provider.
- Drop the stale commented-out init-chmod-data example block.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kondratyevd
kondratyevd merged commit 48bcd7b into main Sep 7, 2026
18 checks passed
kondratyevd added a commit that referenced this pull request Sep 7, 2026
…236)

PR #190 pinned uid: pyroscope on the shared pyroscope datasource, but
Grafana (12.3.1) cannot change an existing datasource's uid via
provisioning: UpdateDataSource looks the row up by id AND the new uid,
gets "data source not found", and the failed provisioning module
crash-loops the instance. The public instance's database still had the
old auto-generated uid, so its pod went down after the merge;
grafana-private survived because its fresh database inserted the
datasource with the pinned uid.

Add deleteDatasources for pyroscope in the same provisioning file:
Grafana deletes any pre-existing row (skipping the delete event when
the datasource is re-created in the same pass, and skipping rows that
do not exist) and re-creates it with the pinned uid, converging every
instance — including a future rebuilt one — to uid pyroscope.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant