Installing the Grafbase Enterprise Platform

In this guide, we go through the steps on how to install the Grafbase Enterprise Platform on your Kubernetes cluster. For simplicity, in this guide we use kind to create a local Kubernetes cluster.

Before you start the installation, make sure you have the following prerequisites:

First, create a kind cluster. Use the following configuration for the cluster:

kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 nodes: - role: control-plane extraPortMappings: # api - containerPort: 30080 hostPort: 30080 protocol: TCP # dashboard - containerPort: 30081 hostPort: 30081 protocol: TCP # postgres - containerPort: 30432 hostPort: 30082 protocol: TCP # clickhouse - containerPort: 30900 hostPort: 30083 protocol: TCP # minio api - containerPort: 30801 hostPort: 30084 protocol: TCP # minio console - containerPort: 30800 hostPort: 30085 protocol: TCP # gateway - containerPort: 30500 hostPort: 30086 protocol: TCP # telemetry sink - containerPort: 30431 hostPort: 30087 protocol: TCP

Save the configuration to a file, for example kind-config.yaml, and create the cluster:

kind create cluster --name grafbase-enterprise-platform --config kind-config.yaml kubectl config use-context kind-grafbase-enterprise-platform

Before you start the installation, log in to the grafbase enterprise repository:

helm registry login helm.grafbase.com --username me@company.com --password changeme

When done, download the Grafbase Enterprise Platform Helm chart:

helm pull oci://helm.grafbase.com/enterprise-platform/stable/enterprise-platform

Create a new file values.yaml.gotmpl with the following values:

global: zitadel: enabled: true postgres: enabled: true clickhouse: enabled: false minio: enabled: true wreplicated: enabled: true kafka: enabled: false telemetrySink: enabled: false otelCollector: enabled: false dashboard: enabled: true api: configmap: values: AWS_ACCESS_KEY_ID: changeme service: type: NodePort nodePort: 30080 secrets: values: AWS_SECRET_ACCESS_KEY: changeme dashboard: service: type: NodePort nodePort: 30081 minio: service: type: NodePort nodePorts: api: 30800 console: 30801

Install the helm chart with the following command:

helm install grafbase-enterprise-platform enterprise-platform-*.tgz -f values.yaml

Wait a bit for the cluster to get ready, and you can see the API web worker crashing due to not being able to access the AWS S3 bucket:

> kubectl logs grafbase-enterprise-platform-api-web-69644fb98b-djgt2 {"timestamp":"2025-01-20T18:14:10.955429888+00:00","level":"INFO","fields":{"message":"API running at 0.0.0.0:8080"},"target":"api::runtime::std::serve","service":"grafbase-api","branch":"","environment":"local"} {"timestamp":"2025-01-20T18:14:17.681903592+00:00","level":"ERROR","fields":{"message":"storage error: service error"},"target":"api::runtime::http::handlers","service":"grafbase-api","branch":"","environment":"local"}

In this example, use MiniIO as the S3 bucket, and create and set the access key and secret key to the secrets. Start first by opening MinIO console and log in with user grafbase and password grafbase. Click on "Access Keys" and create a new access key. Copy the access key and secret key to the values:

api: configmap: values: AWS_ACCESS_KEY_ID: ACCESS KEY FROM MINIO secrets: values: AWS_SECRET_ACCESS_KEY: SECRET KEY FROM MINIO

Upgrade the helm chart:

helmfile apply --environment=local -f helmfile/enterprise-platform.yaml

The environment variables are not reloaded automatically, so you need to restart the API pods:

kubectl rollout restart deployment grafbase-enterprise-platform-api-web

After waiting a few seconds, check if the API is running:

> curl localhost:30080/health "Healthy"

In a real scenario, use a real S3 bucket. Create a bucket grafbase in your storage provider, and set the access key and secret key with read and write access to the bucket. You can set the RUNTIME_ASSETS_STORAGE configmap value to point to the bucket URL.

The next step involves creating a new Zitadel organization. The official Zitadel chart does not yet support creating a nodePort, so do a trick to be able to access the Zitadel UI from our kind cluster. These steps do not apply to a real cluster, where you have an ingress setup for Zitadel and can access it with a domain name.

Add the following line to your /etc/hosts file:

127.0.0.1 grafbase-enterprise-platform-zitadel

Then, add port forwarding to the Zitadel service:

kubectl port-forward service/grafbase-enterprise-platform-zitadel 30550:8080

Open the first-time admin UI by visiting http://localhost:30081/admin. Click "Run script" followed by "Manage single sign-on".

Log in to Zitadel with the username zitadel-admin@zitadel.grafbase-enterprise-platform-zitadel and password Password1!. Skip the 2-factor setup for now and enter a new password for the default user.

Change the organization to "Grafbase" from the top navigation.

Navigate to "Settings", click "Identity Providers", then "GitHub". To use GitHub as an authentication provider, create a new OAuth application in GitHub. Go to GitHub OAuth Apps, give the app a name and URL, and set the callback URL with the value from Zitadel. Now copy the client ID and the secret created in GitHub to the corresponding fields in Zitadel. Open optional settings, add the scope user:email, and check all the checkboxes. Click "Save", scroll up, and click "Activate".

To fetch the user email via GitHub, navigate to "Actions" and click "New". Name the action as "backfillEmail" and fill it with the following snippet:

let http = require("zitadel/http") function backfillEmail(ctx, api) { const { human } = ctx.v1.externalUser // This is an example of how email is added with GitHub auth if (!human.email?.length) { const emails = http.fetch('https://api.github.com/user/emails', { method: 'GET', headers: { "Authorization": `Bearer ${ctx.accessToken}` } }).json() const primaryEmailAddress = emails.find(email => email.primary) if (primaryEmailAddress) { api.setEmail(primaryEmailAddress.email) } } }

Click "Add", then click the "Add trigger" button. Set the trigger type to "Post Authentication" and actions to "backfillEmail" and "backfillName". Click "Save".

Now navigate to the Grafbase Dashboard and log in with your GitHub credentials. The dashboard should prompt you to create a new organization.

The Grafbase Enterprise Platform processes telemetry events from the Grafbase Gateway using a service called telemetry sink. To enable this service in your local installation, set the global values to true for both the sink and the opentelemetry collector in the values.yaml.gotmpl file:

global: telemetrySink: enabled: true otelCollector: enabled: true

Add a node port for the sink to access the sink locally:

telemetry-sink: service: type: NodePort nodePort: 30431 configmap: values: GRAFBASE_KAFKA_BOOTSTRAP_SERVERS: "list_your_kafka_servers_here" GRAFBASE_KAFKA_USERNAME: "change me" GRAFBASE_KAFKA_MECHANISM: "SCRAM-SHA-256" GRAFBASE_KAFKA_SECURITY_PROTOCOL: "sasl_ssl" secrets: values: SYMMETRIC_ENCRYPTION_SECRET: "must be the same as in the API chart" PG_CONNECTION_STRING: "if not set, uses the local postgres" GRAFBASE_KAFKA_PASSWORD: "change me" CLICKHOUSE_CONNECTION_STRING: "if not set, uses the local clickhouse"

For the opentelemetry collector:

opentelemetry-collector: extraEnvs: - name: KAFKA_BROKER value: "address of the broker" - name: KAFKA_USER value: "change me" - name: KAFKA_PASSWORD value: "change me" - name: KAFKA_SASL_MECHANISM value: SCRAM-SHA-256 - name: KAFKA_TLS_INSECURE value: "false" - name: CLICKHOUSE_ENDPOINT value: "must be the same as in the telemetry-sink" - name: CLICKHOUSE_DB value: "must be the same as in the telemetry-sink" - name: CLICKHOUSE_USER value: "change me" - name: CLICKHOUSE_PASSWORD value: "change me"

Ensure your Kafka server has a user with the corresponding password having access to the topics: otlp_metrics, otlp_spans, and otlp_logs. After updating these values with Helm, perform a rolling restart of both the opentelemetry collector and the telemetry sink. Finally, verify the logs for both pods to ensure there are no Kafka errors in the output.

You can define your instance using the Grafbase CLI by setting the URL to your local installation in the CLI login command:

grafbase login --url http://localhost:30081/

Now, you are ready to use the CLI with your local Grafbase Enterprise Platform installation.

To connect the Grafbase Gateway with the Grafbase Enterprise Platform, set the GRAFBASE_OTEL_URL environment variable to point to the telemetry sink URL.