Content
# Cletrics — Real-Time Cloud Cost Metrics
Source-available, self-hosted cloud cost observability for Azure, AWS, and GCP.
Collects usage metrics via OpenTelemetry, joins them with real pricing data, and surfaces cost estimates, anomalies, and budget alerts through Grafana dashboards and a REST API.

**Source-available under Elastic License 2.0 (ELv2). No paywalled self-hosted features.**
Self-host Cletrics yourself and get every feature: multi-cloud cost ingestion (AWS, Azure, GCP), full dashboards, 365-day retention, ML anomaly detection, LLM-cost tracking, FOCUS-spec export, forecasting, audit logs, custom chargeback, REST API + webhooks, SSO/SAML, RBAC + multi-user. No runtime license key is required for self-hosted use.
Don't want to operate it? **Cletrics Cloud** (hosted) runs the same code for you and bills 1% of monitored cloud spend — includes managed SSO operations, a 99.9% SLA, and a named technical contact. Email `jeff@runaipilot.com`.
## Quick Start
```bash
# 1. Clone (always use an explicit dir name — repo dir name affects the
# Docker Compose project name that owns volumes/networks)
git clone https://github.com/Cletrics/Cletrics.git rtccm
cd rtccm
# 2. Install — unattended, no prompts: generates secrets, installs Docker if
# missing, starts the stack, runs a smoke test, prints the external URL +
# cloud-appropriate firewall rule. Safe to re-run; idempotent
# (a second concurrent run is refused, not deadlocked).
sudo ./scripts/rtccm-install.sh --yes
# Advanced: pick a single provider non-interactively
./scripts/rtccm-install.sh --provider azure --yes
# Manual compose-only path (skip the installer):
docker compose --project-directory . \
-f deploy/compose/docker-compose.yml \
-f deploy/compose/docker-compose.customer.yml \
--profile azure up -d
docker compose --project-directory . \
-f deploy/compose/docker-compose.yml \
-f deploy/compose/docker-compose.customer.yml \
--profile azure --profile aws --profile gcp up -d
```
Open **http://localhost:5173** (Web UI, Grafana at `/grafana/`, and proxied API at `/api`). Direct API access is **http://localhost:8000/health** only when port 8000 is exposed.
## Manual Install Files
The public repo keeps only this README at the top level. Deployment files live under:
| Path | Purpose |
|------|---------|
| `deploy/compose/docker-compose.yml` | Base self-hosted stack |
| `deploy/compose/docker-compose.customer.yml` | Customer-safe source-available overlay |
| `deploy/templates/env-template.txt` | Default environment template |
| `deploy/templates/env-template.customer.txt` | Customer-safe environment template |
| `deploy/templates/secrets-template.env` | Secret env-file template |
| `release/VERSION` | Current release version |
| `release/version-manifest.json` | Release metadata |
For a manual install, create runtime files in the repo root:
```bash
cp deploy/templates/env-template.customer.txt .env
cp deploy/templates/secrets-template.env .secrets.env
mkdir -p secrets
openssl rand -base64 32 > secrets/postgres_password.txt
openssl rand -base64 32 > secrets/grafana_admin_password.txt
docker compose --project-directory . \
-f deploy/compose/docker-compose.yml \
-f deploy/compose/docker-compose.customer.yml \
--profile azure --profile aws --profile gcp up -d
```
Full deployment, upgrade, and troubleshooting details are in [`docs/INSTALL.md`](docs/INSTALL.md).
## Architecture
```
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Azure OTel │ │ AWS OTel │ │ GCP OTel │ Cloud collectors
│ + Cost API │ │ + Cost API │ │ + Cost API │ (profile-gated)
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
└────────┬────────┴────────┬────────┘
│ │
┌──────▼──────┐ ┌──────▼──────┐
│ OTel Gateway│ │VictoriaMetrics│ Time-series storage
└──────┬──────┘ └──────┬──────┘
│ │
┌────────┴────────────────┤
│ │
│ ┌────────────────────▼────────────────────┐
│ │ Analytics Service │
│ │ (cost-engine + pricing + anomaly) │
│ └────────────────────┬────────────────────┘
│ │
└────────┬────────────────┘
│ │
┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐
│ PostgreSQL │ │ ClickHouse │ │ Grafana │ Storage + dashboards
└─────────────┘ └─────────────┘ └─────────────┘
│
┌──────▼──────┐
│ REST API │ ← FastAPI (port 8000)
└──────┬──────┘
┌──────▼──────┐
│ Web UI │ ← React + nginx (port 5173)
└─────────────┘
```
### Services
| Service | Image | Description |
|---------|-------|-------------|
| **api** | `cletrics/rtccm-unified` | FastAPI REST API — cost queries, config, alerts |
| **web** | `cletrics/rtccm-web` | React dashboard served via nginx |
| **analytics-service** | `cletrics/rtccm-unified` | Consolidated service: cost engine + pricing sidecar + anomaly detector |
| **k8s-cost-allocator** | `cletrics/rtccm-unified` | Kubernetes namespace/label cost allocation |
| **reconciliation-engine** | `cletrics/rtccm-unified` | Billing reconciliation (estimates vs. actual bills) + pricing calibration (T+24h / T+72h) |
| **cert-manager** | `cletrics/rtccm-api` | Auto-managed mTLS cert generation + rotation. Only consumer of `rtccm-api` image. |
| **postgres** | `cletrics/rtccm-postgres` | PostgreSQL 16 with 53 init scripts baked in (FOCUS schema, migrations) |
| **clickhouse** | `cletrics/rtccm-clickhouse` | ClickHouse OLAP store for FOCUS billing rows + LLM cost ingest |
| **grafana** | `cletrics/rtccm-grafana` | Grafana with dashboards + datasources baked in |
| **otel-gateway** | `cletrics/rtccm-otel-gateway` | OTel collector gateway with config baked in |
| **azure-collector** | `cletrics/rtccm-azure-collector` | Azure Cost Management API collector |
| **aws-collector** | `cletrics/rtccm-aws-collector` | AWS Cost Explorer collector |
| **gcp-collector** | `cletrics/rtccm-gcp-collector` | GCP BigQuery billing export collector |
| **rtccm-mcp** | `cletrics/rtccm-unified` | MCP server exposing RTCCM cost endpoints to Claude Desktop / Gemini / custom agents. Profile-gated (`--profile mcp`). |
| **recon-research-worker** | `cletrics/rtccm-unified` | Strategy-optimization research worker (experimental). Profile-gated (`--profile research`). |
| **change-event-collector** | `cletrics/rtccm-unified` | Polls AWS CloudTrail / Azure Activity Log / GCP Audit Logs for cost-change RCA. Profile-gated (`--profile change-events`). |
Cletrics ships config-baked images on Docker Hub for `postgres`, `clickhouse`, `grafana`, and `otel-gateway` (rows above) so a fresh install lands with schema, dashboards, datasources, and OTel routing already wired. The compose stack also pulls these third-party upstream images directly:
- `victoriametrics/victoria-metrics:v1.109.0` — Time-series storage
- `infracost/cloud-pricing-api:latest` — 3M+ cloud prices (self-hosted pricing sidecar)
Per-cloud OTel sidecars use `otel/opentelemetry-collector-contrib:0.120.0` directly when not routed through `cletrics/rtccm-otel-gateway`.
## Configuration
Copy `deploy/templates/env-template.customer.txt` to `.env` and fill in values. Key settings:
| Variable | Required | Description |
|----------|----------|-------------|
| `POSTGRES_PASSWORD` | Yes | PostgreSQL password |
| `RTCCM_AZURE_*` | For Azure | Azure SP credentials (Subscription, Tenant, Client ID/Secret) |
| `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` | For AWS | AWS IAM credentials |
| `GCP_*` | For GCP | GCP project, billing dataset, and account ID |
| `CLETRICS_ENCRYPTION_KEY` | Recommended | Fernet key for credential encryption at rest |
| `TLS_ENABLED` | No | Enable mTLS between services (default: true). Set to `false` for local dev without certs. |
### Cloud Credentials
**Azure** — Service Principal with "Cost Management Reader" + "Monitoring Reader" roles.
**AWS** — IAM user/role with `ce:GetCostAndUsage`, `cloudwatch:GetMetricData`, `s3:GetObject` (for CUR).
**GCP** — Service account JSON with BigQuery read access to billing export dataset.
#### GCP Provider Prerequisites
Before connectivity tests pass, the target GCP project must have:
- **APIs enabled:** Cloud Resource Manager API, BigQuery API. Enable both at:
`https://console.developers.google.com/apis/api/cloudresourcemanager.googleapis.com/overview?project=<PROJECT_ID>`
and
`https://console.developers.google.com/apis/api/bigquery.googleapis.com/overview?project=<PROJECT_ID>`
- **Service account IAM roles:** `roles/browser` (or `roles/resourcemanager.projectViewer`) on the project, plus `roles/bigquery.dataViewer` on the billing-export dataset.
- **Propagation delay:** API enablement takes ~2 minutes to propagate. Re-run the connectivity test if the first attempt returns `PERMISSION_DENIED — Cloud Resource Manager API has not been used`.
Place credential files in `secrets/`:
```
secrets/
├── postgres_password.txt
├── grafana_admin_password.txt
├── azure_credentials.json
├── aws_credentials.json
├── gcp_credentials.json
└── tls/ # generated by scripts/generate_certs.sh
```
## Docker Hub
All 10 custom images are published to [Docker Hub](https://hub.docker.com/u/cletrics) under the `cletrics/` organization. Multi-arch images support `linux/amd64` and `linux/arm64`. The `rtccm-unified` image bundles the API, analytics, reconciliation, k8s allocator, MCP server, research worker, and change-event collector — services differ only by `command:` in compose.
Canonical 10:
| Repo | Role |
|------|------|
| `cletrics/rtccm-unified` | Python service bundle (api, analytics, reconciliation, k8s allocator, MCP, research worker, change-event collector) |
| `cletrics/rtccm-api` | cert-manager only |
| `cletrics/rtccm-web` | React + nginx UI |
| `cletrics/rtccm-postgres` | Postgres 16 + 53 init scripts |
| `cletrics/rtccm-clickhouse` | ClickHouse OLAP store |
| `cletrics/rtccm-grafana` | Grafana + baked dashboards/datasources |
| `cletrics/rtccm-otel-gateway` | OTel gateway + baked config |
| `cletrics/rtccm-aws-collector` | AWS Cost Explorer collector |
| `cletrics/rtccm-azure-collector` | Azure Cost Management collector |
| `cletrics/rtccm-gcp-collector` | GCP BigQuery billing collector |
### Quick Start with Pre-built Images
No build step required — Docker Compose pulls images automatically:
```bash
# 1. Clone (always use an explicit `rtccm` dir name — affects Compose
# project name that owns volumes/networks across re-installs).
# Repo is private → token-authenticated clone (drop the token once public).
git clone https://x-access-token:<TOKEN>@github.com/Cletrics/Cletrics.git rtccm && cd rtccm
# 2. Configure
cp deploy/templates/env-template.customer.txt .env
cp deploy/templates/secrets-template.env .secrets.env
mkdir -p secrets
echo "changeme" > secrets/postgres_password.txt
echo "changeme" > secrets/grafana_admin_password.txt
# 3. Pin a version (optional — defaults to latest)
echo "RTCCM_VERSION=1.3.13" >> .env
# 4. Start (pulls pre-built images from Docker Hub)
docker compose --project-directory . \
-f deploy/compose/docker-compose.yml \
-f deploy/compose/docker-compose.customer.yml \
--profile azure up -d
```
For customer environments that must stay on the non-AI RTCCM baseline, use:
```bash
cp deploy/templates/env-template.customer.txt .env
docker compose --project-directory . \
-f deploy/compose/docker-compose.yml \
-f deploy/compose/docker-compose.customer.yml \
--profile azure up -d
```
For customer-safe deployments, set `RTCCM_VERSION` to an immutable release and do not use `latest`.
### Pull Individual Images
```bash
docker pull cletrics/rtccm-unified:1.3.13
docker pull cletrics/rtccm-web:1.3.13
docker pull cletrics/rtccm-azure-collector:1.3.13
docker pull cletrics/rtccm-aws-collector:1.3.13
docker pull cletrics/rtccm-gcp-collector:1.3.13
```
### Build from Source
To build locally instead of pulling from Docker Hub:
```bash
docker compose --project-directory . -f deploy/compose/docker-compose.yml --profile azure build
docker compose --project-directory . -f deploy/compose/docker-compose.yml --profile azure up -d
```
### Tags
| Tag Pattern | Example | Description |
|-------------|---------|-------------|
| `X.Y.Z` | `1.0.0` | Exact semver release |
| `X.Y` | `1.0` | Latest patch in minor series |
| `sha-<hash>` | `sha-abc1234` | Specific commit |
Images are published through the manual Docker Hub Publish Gate workflow, which
builds each image and scans the exported payload with gitleaks and TruffleHog
before pushing tags.
## API
```
GET /health → Service health check
GET /metrics/cost-rate → Current cost rates by service
GET /metrics/top-spenders → Top spending resources
GET /alerts → Active alerts
GET /source-freshness → Data freshness per provider
POST /config/save → Save cloud provider configuration
```
Full API docs are available through the web proxy at `http://localhost:5173/api/docs`, or directly at `http://localhost:8000/docs` when API port 8000 is exposed.
## Security
- All Cletrics-owned Python service containers run read-only with non-root users (UID 1000). The web container (nginx) and cert-manager run as their required default users. Third-party containers (PostgreSQL, Grafana, OTel, VictoriaMetrics) use their upstream default users.
- Internal services on isolated Docker network (no external exposure)
- API (port 8000) and Web (port 5173, including Grafana at `/grafana/`) expose ports on all interfaces by default — bind to `127.0.0.1` or use a reverse proxy in production. Grafana is not directly exposed; it is proxied through the web container's nginx.
- Credentials stored in `secrets/` files (Docker secrets) and `.secrets.env` (env-file) — both are required
- mTLS between services available via `TLS_ENABLED=true` (disabled by default in customer template)
- Fernet encryption for credentials at rest
- JWT authentication for API access
- Rate limiting on public endpoints
- MFA enforced by default (`CLETRICS_MFA_SKIP=false`)
## Scripts
| Script | Description |
|--------|-------------|
| `scripts/generate_certs.sh` | Generate TLS CA and service certificates |
| `scripts/validate-profiles.sh` | Validate Docker Compose profile combinations |
| `scripts/scan-containers.sh` | Trivy/Grype container security scanning |
| `scripts/update-customer.sh` | Apply version-pinned customer-safe Docker updates |
| `scripts/validate-customer-deployment.sh` | Validate the customer-safe compose path and runtime health |
| `scripts/seed-test-data.sh` | Seed sample data for testing |
| `scripts/harden_host.sh` | Host OS hardening recommendations |
| `scripts/setup_firewall.sh` | UFW firewall configuration |
See [`docs/customer-deployment-runbook.md`](docs/customer-deployment-runbook.md) for the full install, update, validation, and rollback flow for non-AI customer deployments.
## License
Cletrics is licensed under the **Elastic License 2.0 (ELv2)** — see [LICENSE](LICENSE). You can use, copy, modify, distribute, and self-host under that license, but you may not offer Cletrics as a hosted or managed service that exposes a substantial set of its features. Every self-hosted feature in this repository is available without a runtime license key. There is no Open Core split, no encrypted bundle, no `feature_locked` 403.
Commercial offerings (separate from self-hosted ELv2 use):
- **Cletrics Cloud** — fully managed hosted deployment operated by Cletrics,
billed at 1% of monitored cloud spend. Includes managed SSO
operations, 99.9% SLA, named technical contact, and bundled support.
- **Cletrics Optimize** (planned) — savings-share billing for
enterprises that want Cletrics' attribution engine to invoice on
measured savings instead of subscription. 12-month contract.
- **Cletrics Support** — vendor support contract for self-hosters who
want a response-time SLA without moving to Cloud. No code change,
service contract only.
Email `jeff@runaipilot.com` for any commercial offering.
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
markitdown
MarkItDown-MCP is a lightweight server for converting URIs to Markdown.
markitdown
Python tool for converting files and office documents to Markdown.
Filesystem
Node.js MCP Server for filesystem operations with dynamic access control.
TrendRadar
TrendRadar: Your hotspot assistant for real news in just 30 seconds.
mempalace
The highest-scoring AI memory system ever benchmarked. And it's free.
mempalace
The highest-scoring AI memory system ever benchmarked. And it's free.