Prerequisites
From CostGraph, one thing: a deployment API key, created in the dashboard under Settings > API keys. It is the only credential you need. The image registry authenticates with the same key, and the chart wires that up for you. Self-hosting still starts with an account on app.costgraph.ai. Sign up there, and that account is where you create the deployment API key, pick your plan, and manage your subscription and billing. The account is for provisioning only: your cost data never leaves the deployment you run. From your side:- Kubernetes and Helm 3+
- Postgres 14+, with
citextandpg_trgm - Redis
- VictoriaMetrics
- The URL your users will reach the dashboard on
Install
1
Add the Helm repository
2
Write a values file
global.appBaseURL must be the address people actually open in a browser, not an
internal Service DNS name. It shapes the links in invitation email.3
Install
Evaluating without a database
To try it before standing up Postgres, Redis and VictoriaMetrics, replace those three blocks withbundled.enabled: true on each and the chart runs them
in-cluster:
Keeping credentials out of values
For production, put credentials in Secrets you manage and reference them withexistingSecret rather than inline values, so nothing sensitive is written into
Helm release history:
When you use Then name it on each component too. See using your own registry credentials.
global.controlPlane.existingSecret, create the image pull
secret yourself as well and set global.imagePullSecrets:global.imagePullSecrets does not reach
the components rendered by the shared application chart, so it has to be
repeated; the render fails with a message naming the component if you miss
one.Network access it needs
Outbound HTTPS (443) to these hosts:
Nothing needs to reach the deployment from outside your network, unless you connect Slack in webhook mode.
Connecting your spend
Installing the chart gives you CostGraph. It does not give it anything to report on yet. That comes from the same sources as hosted CostGraph:
Connect whichever apply to you. Provider integrations need only a read-only
credential and nothing deployed.
Pointing them at your install
Everything you deploy defaults to hosted CostGraph, so on a self-hosted install you redirect it at your own address. For the operator, in every cluster you want costs for, including the one running CostGraph:
The agent and the API take the same treatment: give them your own address in
place of
api.costgraph.ai, and your deployment API key.
Connect with OAuth
Hosted CostGraph signs in to DigitalOcean, Akamai Cloud (Linode), Convex, and PlanetScale through its own registered apps. On a self-hosted install, you register your own app with each vendor you want a Connect with button for.- In the vendor’s developer settings, create an OAuth app.
- Set its redirect URL to
{APP_BASE_URL}/integrations/oauth/callback, using the value ofglobal.appBaseURL. - Set the app’s client ID and secret as
OAUTH_<SLUG>_CLIENT_IDandOAUTH_<SLUG>_CLIENT_SECRET, where<SLUG>isDIGITALOCEAN,LINODE,CONVEX, orPLANETSCALE. - Set
OAUTH_STATE_SECRETto a base64 string that decodes to at least 32 bytes.
read_organizations,
read_invoices, read_databases, read_branches, and read_metrics_endpoints.
PlanetScale applies scopes from the app, so after changing them, reconnect existing
PlanetScale connections.
Store the credentials in a Secret you manage, then reference them from
backend.deployment.env. The --namespace must match the namespace of your Helm
release:
Pricing hardware that is not in a cloud
A resource in a public cloud is priced from that provider’s published rates, matched on its instance type and region. Hardware you own has no published rate, so you register what it costs you and tag the resources that bill at it. This applies whether you measure them with the operator or the agent. Register the rate once, then tag everything that bills at it:What is a pricing ID and why would I need it?
What is a pricing ID and why would I need it?
A pricing ID is a rate you register once: what a piece of hardware you own
actually costs you. You then tag it onto the resources that bill at it.
Without one, hardware you own is measured but has nothing to price against.
Pricing IDs
Registering rates, the label spellings each platform accepts, and how a rate
is inherited from a node to the volumes on it.
Labels are inherited: tagging a node prices the volumes attached to it, so you
rarely need to label every object. A node is in no namespace, so labelling a
namespace never changes a node’s own rate.
Operating
Resources are namedcostgraph-selfhosted, independent of the release name.
helm status costgraph prints them.
Check health at any time. This reads the database and makes no outbound call:
If the deployment can’t bootstrap
On startup the backend registers with CostGraph and receives a signed configuration document. That document requires an active license on your organization, so bootstrap fails while your plan is still being set up:Auth UserPool not configured on the sign-up form. That message means
the configuration hasn’t arrived yet, not that you’re missing a setting: there
is no Cognito value for you to fill in. Fix the bootstrap and sign-in works.
The one thing you must not delete
On first install the chart generates encryption keys into a Secret namedcostgraph-selfhosted-generated. Everything you have saved is tied to them.
Helm keeps this Secret across upgrades and uninstalls, so normally you need do
nothing. But it cannot be regenerated.
If that Secret is deleted, every API key your team issued stops working and
every connected cloud account has to be reconnected, because the stored
credentials can no longer be decrypted.
Back it up alongside the database, and keep the two together. A database
restored next to a different Secret is a database whose credentials cannot be
read.
Upgrades
Upgrade in place. Pending migrations are applied on start:Every setting
values.yaml documents each setting inline, next to the value it controls:
Values reference
The component pattern, the three value tiers, and how to enable or size a
single component.