Split Grafana into public and private instances - #190
Merged
Conversation
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 Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
💡 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".
- 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>
This was referenced Sep 7, 2026
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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-generatedgrafana-privateSecret (admin-user/admin-passwordkeys).Implementation
Kept as close to the existing pattern as possible:
helmrelease-private.yaml— identical to the public one except for the name and its values ConfigMap (grafana-private-config).values-private.yaml— a trimmed copy ofvalues.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 theprivatedashboard provider/ConfigMap, home dashboard set tousers-overview, and it drops the public-only pieces (announcements nginx sidecar,/workmount, Infinity datasource, dynamictext plugin).core-production,core-geddes2) gain the HelmRelease resource and agrafana-private-configgenerator; the existinggrafana-private-dashboardsConfigMap 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.shpasses (kustomize + envsubst + kubeconform +helm templateof both Grafana releases). Also renderedgrafana-privatemanually and confirmed: own PVC, ingress at/grafana-private(Prefix matching does not overlap with/grafana),[auth.anonymous] enabled = false, and onlygrafana-private-dashboardsmounted.🤖 Generated with Claude Code