Evidence
Evidence is a static-site BI tool that compiles SQL queries and Markdown into a fully static dashboard site. On this platform the queries run against ClickHouse at build time, the results are baked as Parquet into the image, and the runtime pod is just nginx serving the build output — it never opens a ClickHouse connection.
Deployment
Section titled “Deployment”| Field | Value |
|---|---|
| URL | https://evidence.internal.stefanzhelev.com (NetBird VPN only) |
| Flux path | flux-clusters/stefanzhelev/apps/evidence |
| Base path | flux-apps/evidence |
| Namespace | evidence |
| Sync wave | 7 |
| Depends on | clickhouse, data-workflows-database, forgejo, harbor, external-secrets-config, authentik-app-evidence |
Workflow phases
Section titled “Workflow phases”How a content change reaches the live site:
1. Local edit
Section titled “1. Local edit”Pages are SQL + Markdown under evidence/pages/. Sources (the queries that produce the Parquet files) live under evidence/sources/<source-name>/ — currently only clickhouse/.
cd evidenceyarn installyarn sources # run queries → write parquetyarn dev # local preview at http://localhost:3000yarn sources requires EVIDENCE_SOURCE__clickhouse__url, EVIDENCE_SOURCE__clickhouse__username, and EVIDENCE_SOURCE__clickhouse__password in the environment. The connector exposes only those three options — qualify queries with dev__mart.<table> instead of a separate database/schema arg, since dev__mart is the only DB the read-only evidence user has SELECT on.
Open a PR against stefanzhelev. There is no per-PR preview build — review locally with yarn dev.
3. Push to stefanzhelev
Section titled “3. Push to stefanzhelev”On any change under evidence/**, .forgejo/workflows/evidence-build.yml fires:
| Step | What happens |
|---|---|
yarn install --frozen-lockfile | Installs deps (yarn classic via corepack) |
yarn sources | Runs every SQL source against ClickHouse, writes Parquet into sources/<source>/.evidence/ |
yarn build | Packages the static site (HTML + JS + Parquet) into evidence/build/ |
docker build | evidence/Dockerfile copies build/ into nginx-unprivileged |
| Push to Harbor | Tags :latest and :<git-sha> for SHA rollback |
evidence builddoes not run sources — it only packages whatever Parquet is already on disk.yarn sourcesmust run first or the runtime DuckDB-WASM times out trying to load a missingmanifest.json.
4. Roll out
Section titled “4. Roll out”Flux’s image-update controllers (or a manual restart) cycle the Deployment to pick up the new :latest tag. Because the data is baked into the image, there is no runtime refresh — every dashboard update is a fresh image build.
Why build-time, not runtime
Section titled “Why build-time, not runtime”Two consequences of the build-time model worth keeping in mind:
- Data freshness = build time. The numbers shown on
evidence.internalare as fresh as the lastevidence-buildrun, not “live”. Trigger a rebuild (push orworkflow_dispatch) to refresh them. - No runtime credentials. The pod has no ClickHouse credentials and no network path to ClickHouse — only build-time CI does. This is also why the
evidence-configKustomization has noclickhouse-credentialsExternalSecret.
Pod shape
Section titled “Pod shape”- Single replica
nginxinc/nginx-unprivilegedon thestateful-single(cx43) node - Read-only rootfs with a writable
tmpvolume (nginx-unprivileged needs writable temp dirs even with read-only root) - No PVC, no DB connection — it’s just static files
Authentication
Section titled “Authentication”Evidence has no native auth. The ingress is on the internalsecure Traefik entrypoint — reachable only over the NetBird VPN — and the authentik-app-evidence Kustomization is launch-only: it provisions an Authentik tile pointing at the ingress so the app shows up on the user dashboard, but it does not gate access at the request layer. VPN membership is the access control.
Secrets
Section titled “Secrets”CI secrets are surfaced from Vault into Forgejo Actions by Tofu modules under flux-apps/evidence/:
| Secret | Source | Used by |
|---|---|---|
EVIDENCE_CLICKHOUSE_USERNAME, EVIDENCE_CLICKHOUSE_PASSWORD | evidence-database/tofu (read-only evidence user, SELECT on dev__mart only) | yarn sources step |
EVIDENCE_HARBOR_USERNAME, EVIDENCE_HARBOR_TOKEN | evidence-docker-registry/tofu (push robot for the Harbor evidence project) | docker login + docker push |
Integrations
Section titled “Integrations”- ClickHouse: queried at build time only — qualify with
dev__mart.<table> - dbt: Evidence reads the mart layer dbt produces; schema changes in dbt drive Evidence content
- Harbor: stores
evidence/evidence:latestand:<sha> - Forgejo: runs
evidence-build.yml - Authentik: dashboard tile only, not an auth gate
- NetBird: the actual access boundary