docs(vibe): add tools/ and cms/ guidebooks
Two code-grounded tree-docs guidebooks under vibe/guidebooks/, drilling into the lab-ecosystem 02-tools and 03-cms pages (bidirectional): - tools/ : hub + components.md (Vault+VSO, Prometheus, Grafana, CrowdSec, pgbouncer, Redis/KeyDB, Plausible, ClickHouse; pgcat/tool as Tier-2) + secrets-and-vso.md (Vault engines/auth, the app_roles/app_policy modules = the <app> join-key machinery, VSO CRDs, secret-paths inventory). - cms/ : hub + site.md (Nuxt + dual Pages/k3s deploy) + cloudflare.md (zone via OVH->CF, Pages, cloudflared tunnel, Turnstile, R2 state) + zoho-email.md (OAuth, MX/SPF/DKIM/DMARC/BIMI, the 7 aliases). Sibling-repo code linked via full gitea URLs; vibe-internal links bidirectional. Reconciled the cloudflared tunnel token path to kvv2 cms/cloudflared (the chart VaultStaticSecret is kv-v2; the kvv1 tofu reference is a commented-out stub). 6 mermaid diagrams MCP-validated; zero dead links. Lab Cartographer cohort. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
114
vibe/guidebooks/tools/README.md
Normal file
114
vibe/guidebooks/tools/README.md
Normal file
@@ -0,0 +1,114 @@
|
||||
[vibe](../../README.md) > [Guidebooks](../README.md) > **Tools**
|
||||
|
||||
# Tools
|
||||
|
||||
> **Status:** ✅ Active
|
||||
> **Last Updated:** 2026-06-23
|
||||
> **Upstream:** [Guidebooks index](../README.md) · [lab-ecosystem 02 · tools](../lab-ecosystem/02-tools.md)
|
||||
> **Downstream:** [Components](components.md) · [Secrets & VSO](secrets-and-vso.md)
|
||||
> **Related:** [secrets-and-vault concept](../lab-ecosystem/secrets-and-vault.md) · [tofu CI apply flow](../factory-provisioning/opentofu/ci-apply-flow.md) · [safe-env ADR](../../ADR/0001-safe-prod-like-environment.md)
|
||||
|
||||
The [`tools` repo](https://gitea.arcodange.lab/arcodange-org/tools) is the lab's **platform layer**: the cluster-wide services every app namespace leans on — secrets (Vault + VSO), observability (Prometheus + Grafana), edge security (CrowdSec), database pooling (pgbouncer), caching (Redis/KeyDB), and analytics (Plausible + ClickHouse). Everything in this repo lands in the single **`tools` namespace**.
|
||||
|
||||
This hub explains the **deploy model** — how one factory-owned ArgoCD Application fans out into one Application per component — and gives a **component inventory**. For per-component internals see [Components](components.md); for how secrets reach the pods see [Secrets & VSO](secrets-and-vso.md).
|
||||
|
||||
## Deploy model
|
||||
|
||||
The whole repo is wired into the cluster through a single **meta-chart** that factory's ArgoCD points at:
|
||||
|
||||
1. Factory's ArgoCD declares **one** Application named `tools` whose source is this repo's [`chart/`](https://gitea.arcodange.lab/arcodange-org/tools/src/branch/main/chart) meta-chart.
|
||||
2. That meta-chart renders two kinds of object from [`chart/values.yaml`](https://gitea.arcodange.lab/arcodange-org/tools/src/branch/main/chart/values.yaml):
|
||||
- an **AppProject** named `tools` ([`chart/templates/project.yaml`](https://gitea.arcodange.lab/arcodange-org/tools/src/branch/main/chart/templates/project.yaml)) that pins every child Application to `sourceRepos: tools` and `destinations: tools` namespace only;
|
||||
- one ArgoCD **Application per component** ([`chart/templates/apps.yaml`](https://gitea.arcodange.lab/arcodange-org/tools/src/branch/main/chart/templates/apps.yaml) — a `range` over `.Values.tools`), each pointing `path:` at the matching **top-level directory** of the repo (`path: pgbouncer`, `path: grafana`, …).
|
||||
3. Each child Application targets `namespace: tools`, with `automated` sync (`prune: true`, `selfHeal: true`) and `CreateNamespace=true`.
|
||||
4. A component directory is **either** a Helm chart (`Chart.yaml` whose `dependencies:` pull the upstream chart + the `tool` library) **or** a Kustomize overlay (`kustomization.yaml` using a `helmCharts:` inflation generator).
|
||||
5. [`tool/`](https://gitea.arcodange.lab/arcodange-org/tools/src/branch/main/tool) is a Helm **library chart** (`type: library`): it ships shared templates/helpers consumed by the component charts via `dependencies:` and is **not deployable** on its own.
|
||||
|
||||
> [!NOTE]
|
||||
> A component is deployed **only if it appears as a key under `tools:` in [`chart/values.yaml`](https://gitea.arcodange.lab/arcodange-org/tools/src/branch/main/chart/values.yaml)**. `pgcat` is present in the repo but commented out there, so no Application is rendered for it.
|
||||
|
||||
## Component inventory
|
||||
|
||||
| Component | How declared (chart + version OR Kustomize) | Ingress host | Persistence | Purpose |
|
||||
|---|---|---|---|---|
|
||||
| **hashicorp-vault** | Helm — `hashicorp/vault` `0.28.1` (+ `tool` lib) | `vault.arcodange.lab` (Traefik, Let's Encrypt) | `storage "file"` at `/vault/data` + audit storage (PVC) | Secrets engine: KV, transit, PostgreSQL dynamic creds; auth `kubernetes` + Gitea OIDC/JWT |
|
||||
| **vault-secrets-operator (VSO)** | Helm — `hashicorp/vault-secrets-operator` `0.9.0`, a dependency of the `hashicorp-vault` chart | — | — | Injects Vault secrets into pods via `VaultAuth` / `VaultDynamicSecret` CRDs; client-cache `direct-encrypted` via transit |
|
||||
| **prometheus** | Helm — `prometheus-community/prometheus` `28.13.0` (app `v3.10.0`) | none (in-cluster) | `persistentVolume` enabled, `8Gi` | Metrics scraping + TSDB storage |
|
||||
| **grafana** | Helm — `grafana/grafana` `10.3.0` (+ `tool` lib) | `grafana.arcodange.lab` (Traefik, Let's Encrypt) | `persistence.enabled: false` (ephemeral; dashboards provisioned) | Dashboards; datasources Prometheus + ClickHouse |
|
||||
| **crowdsec** | Helm — `crowdsecurity/crowdsec` `0.20.1` (+ `tool` lib) | none (Traefik bouncer + AppSec on the edge) | LAPI state in external PostgreSQL (via pgbouncer) | Behavioural detection; agent parses Traefik logs, AppSec virtual-patching |
|
||||
| **pgbouncer** | Helm — `icoretech/pgbouncer` `2.3.1` (+ `tool` lib) | none (cluster service `pgbouncer.tools`) | stateless (config only) | Connection pooler to the **external** PostgreSQL on `pi2` (`192.168.1.202`), pinned via `kubernetes.io/hostname: pi2` |
|
||||
| **redis / KeyDB** | Helm — `pascaliske/redis` `2.1.0` (+ `tool` lib) | none (cluster service) | PVC `create: true`, `1Gi` at `/data` | In-memory cache; KeyDB master + replica, Redis-compatible |
|
||||
| **plausible** | **Kustomize** — inflates `pascaliske/plausible` `2.0.0` | `analytics.arcodange.lab` (Traefik `IngressRoute`, Let's Encrypt) | stateless app; data lives in ClickHouse | Privacy-friendly web analytics; `DB_HOST: pgbouncer.tools` |
|
||||
| **clickhouse** | **Kustomize** — inflates `pascaliske/clickhouse` `0.4.0` + local `databases` chart | none (cluster service) | PVC `16Gi` (StatefulSet) | OLAP column store backing Plausible |
|
||||
| **pgcat** *(disabled)* | Helm — `improwised/pgcat` `0.1.0` — **commented out** in `chart/values.yaml` | — | — | Alternative pooler; not rendered (too constraining: must list every db/user, md5-only auth) |
|
||||
| **tool** *(library)* | Helm **library chart** (`type: library`), not deployable | — | — | Shared templates/helpers consumed by the component charts |
|
||||
|
||||
## How tools fit together
|
||||
|
||||
```mermaid
|
||||
%%{init: {'theme': 'base'}}%%
|
||||
flowchart TB
|
||||
classDef ext fill:#7c3aed,stroke:#6d28d9,color:#fff
|
||||
classDef proc fill:#059669,stroke:#047857,color:#fff
|
||||
classDef edge fill:#d97706,stroke:#b45309,color:#fff
|
||||
classDef meta fill:#2563eb,stroke:#1e40af,color:#fff
|
||||
|
||||
ARGOCD["factory ArgoCD<br>Application: tools"]:::meta
|
||||
META["tools meta-chart<br>chart/ (apps.yaml + project.yaml)"]:::meta
|
||||
PROJ["AppProject: tools"]:::meta
|
||||
|
||||
subgraph NS["tools namespace"]
|
||||
VAULT[("hashicorp-vault<br>+ VSO")]:::ext
|
||||
PROM["prometheus"]:::proc
|
||||
GRAF["grafana"]:::proc
|
||||
CS["crowdsec<br>Traefik bouncer + AppSec"]:::edge
|
||||
PGB["pgbouncer"]:::proc
|
||||
REDIS[("redis / KeyDB")]:::ext
|
||||
PLA["plausible"]:::proc
|
||||
CH[("clickhouse")]:::ext
|
||||
PODS["app + tool pods"]:::proc
|
||||
end
|
||||
|
||||
PG[("external PostgreSQL<br>pi2 · 192.168.1.202")]:::ext
|
||||
TRAEFIK["Traefik ingress<br>vault / grafana / analytics .arcodange.lab"]:::edge
|
||||
|
||||
ARGOCD --> META
|
||||
META --> PROJ
|
||||
META -- "one Application per component" --> NS
|
||||
VAULT -- "inject secrets (VSO)" --> PODS
|
||||
PGB -- "pools to" --> PG
|
||||
PLA -- "writes analytics" --> CH
|
||||
PROM --> GRAF
|
||||
CH --> GRAF
|
||||
TRAEFIK --> VAULT
|
||||
TRAEFIK --> GRAF
|
||||
TRAEFIK --> PLA
|
||||
CS -- "fronts the edge" --> TRAEFIK
|
||||
```
|
||||
|
||||
1. **Factory's ArgoCD** owns a single Application named `tools` pointed at this repo's `chart/` meta-chart.
|
||||
2. The **meta-chart** renders the `tools` **AppProject** (which scopes every child to the `tools` repo + `tools` namespace) and **one Application per component** listed under `tools:` in `chart/values.yaml`.
|
||||
3. Every child Application deploys into the **`tools` namespace** — Vault+VSO, Prometheus, Grafana, CrowdSec, pgbouncer, Redis/KeyDB, Plausible, ClickHouse.
|
||||
4. **Vault + VSO** inject secrets into app and tool pods via the `VaultAuth` / `VaultDynamicSecret` CRDs.
|
||||
5. **pgbouncer** pools connections out to the **external PostgreSQL** on `pi2` (`192.168.1.202`), the same database CrowdSec's LAPI and Plausible use through it.
|
||||
6. **Plausible** writes analytics into **ClickHouse**; both **Prometheus** and **ClickHouse** are wired as **Grafana** datasources.
|
||||
7. **Traefik** publishes `vault.arcodange.lab`, `grafana.arcodange.lab`, and `analytics.arcodange.lab` over Let's Encrypt, with **CrowdSec** running as the bouncer/AppSec layer fronting that edge.
|
||||
|
||||
## Pages in this guidebook
|
||||
|
||||
| Page | What it covers | Status |
|
||||
|---|---|---|
|
||||
| [Components](components.md) | Per-component internals: chart values, ingress, persistence, how each gets its secrets | ✅ Active |
|
||||
| [Secrets & VSO](secrets-and-vso.md) | How Vault + the Vault Secrets Operator deliver static and dynamic secrets into `tools` pods | ✅ Active |
|
||||
|
||||
## Maintenance rule
|
||||
|
||||
> [!IMPORTANT]
|
||||
> **If a component in the `tools` repo changes, update this guidebook in the same change.** Adding or removing a key under `tools:` in `chart/values.yaml`, bumping an upstream chart version, switching a component between Helm and Kustomize, or changing an ingress host or persistence size all alter the inventory above — keep the table and the diagram in sync as part of the same PR. A reference map that drifts from reality sends readers (and agents) confidently down dead paths.
|
||||
|
||||
## Cross-references
|
||||
|
||||
- [lab-ecosystem 02 · tools](../lab-ecosystem/02-tools.md) — the parent whole-lab view of this namespace.
|
||||
- [secrets-and-vault concept](../lab-ecosystem/secrets-and-vault.md) — the lab-wide Vault model these services depend on.
|
||||
- [tofu CI apply flow](../factory-provisioning/opentofu/ci-apply-flow.md) — how each component's `iac/` (Vault config) is applied.
|
||||
- [safe-env ADR](../../ADR/0001-safe-prod-like-environment.md) — why a safe, prod-like environment shapes how these platform services are run.
|
||||
Reference in New Issue
Block a user