> For the complete documentation index, see [llms.txt](https://docs.konvu.com/konvu/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.konvu.com/konvu/get-started/connect-your-environment/source-code/self-hosted-analysis/installing-the-broker-and-controller.md).

# Installing the Broker and Controller

Deploy Konvu controller and broker on any Kubernetes cluster using Helm

This guide shows how to deploy Konvu components via Helm on any Kubernetes cluster.

## Prerequisites Check

Before installing, verify:

* `kubectl cluster-info` succeeds
* You have cluster admin permissions
* You have your Konvu company token
* You have GitHub App credentials (see [Connecting GitHub](/konvu/get-started/connect-your-environment/source-code/self-hosted-analysis/connecting-github.md))
* You have an OpenAI or Anthropic API key

## Step 1: Add Konvu Helm Repository

```bash
helm repo add konvu https://download.konvu.com/helm/ \
  --username konvu \
  --password YOUR_COMPANY_TOKEN

helm repo update
```

Replace `YOUR_COMPANY_TOKEN` with your actual token.

***

## Step 2: Choose Your Secret Management Approach

You have two options for managing secrets:

### Approach A: Inline Secrets (Recommended for Getting Started)

**Secrets are embedded directly in your Helm values file**. Helm creates Kubernetes secrets automatically.

**Best for**: Quick deployments, testing, getting started

**Pros**:

* Simple - no additional steps
* Works on any Kubernetes cluster
* No additional tools required

**Cons**:

* Secrets stored in values files
* Use secure storage (git-crypt, SOPS, Vault) if committing to version control

### Approach B: Pre-created Secrets (Production)

**Create secrets manually with kubectl before Helm deployment**.

**Best for**: Production environments, teams with existing secret management, compliance requirements

**Pros**:

* Secrets never in version control
* Works with any secret management tool
* Separates secrets from configuration

**Cons**:

* Requires additional setup step

### Encryption Keypair (Both Approaches)

Konvu provides you an encryption keypair. Credentials exchanged between Konvu and your cluster are encrypted with it — the private key never leaves your cluster, so Konvu cannot read what it relays.

Create the Secret in both namespaces (create the namespaces first if they don't exist yet):

```bash
kubectl create secret generic konvu-encryption-keypair \
  --from-file=private-key=/path/to/konvu-encryption-private-key.pem \
  --namespace konvu-controller   # repeat for konvu-broker
```

The values examples below enable encryption with:

```yaml
encryption:
  enabled: true
  existingSecret: konvu-encryption-keypair
```

***

## Step 3: Deploy the Controller

Choose your secret management approach:

### Approach A: Inline Secrets

Create `controller-values.yaml`:

```yaml
# Global settings
global:
  # Helm will create secret from this value
  companyToken: "YOUR_COMPANY_TOKEN"

# Namespace configuration
namespace:
  name: konvu-controller

# RBAC configuration
rbac:
  create: true

# Controller configuration
controller:
  image:
    repository: registry.konvu.com/konvu-controller
    tag: latest
    pullPolicy: Always

  replicaCount: 1

  resources:
    requests:
      cpu: 25m
      memory: 256Mi
    limits:
      cpu: 500m
      memory: 512Mi

# Backend URL
backend:
  url: https://sensors.konvu.com

# SCA worker image configuration
sca:
  image:
    repository: registry.konvu.com/konvu-sca
    tag: latest
    pullPolicy: Always

# LLM configuration
llm:
  openai:
    apiKey: "YOUR_OPENAI_API_KEY"

# Encryption keypair (see Step 2)
encryption:
  enabled: true
  existingSecret: konvu-encryption-keypair

# Image pull credentials
imageCredentials:
  create: true
  registry: registry.konvu.com
  username: konvu
  password: "YOUR_COMPANY_TOKEN"

# ResourceQuota preset - also derives the max number of concurrent analysis jobs:
#   small=8, medium=20, large=30, xlarge=50
# Set controller.maxConcurrentJobs only to throttle below the preset.
# preset: custom (for small clusters) requires setting controller.maxConcurrentJobs explicitly.
resourceQuota:
  enabled: true
  preset: medium

# Advanced configuration
advanced:
  verbose: false  # Set true for detailed logs
```

Deploy:

```bash
helm upgrade --install konvu-controller konvu/konvu-controller \
  --namespace konvu-controller \
  --create-namespace \
  --values controller-values.yaml \
  --wait
```

This installs the latest chart version. To pin a specific version, pass `--version X.Y.Z` (list available versions with `helm search repo konvu -l`).

### Approach B: Pre-created Secrets

Create secrets first:

```bash
# Create namespace
kubectl create namespace konvu-controller

# Create company token secret
kubectl create secret generic konvu-company-token \
  --from-literal=company-token=YOUR_COMPANY_TOKEN \
  --namespace konvu-controller

# Create LLM key secret (use anthropic-api-key instead for Anthropic)
kubectl create secret generic konvu-ai-credentials \
  --from-literal=openai-api-key=YOUR_OPENAI_API_KEY \
  --namespace konvu-controller
```

The LLM secret must be named exactly `konvu-ai-credentials` with the key `openai-api-key` — other names are not picked up.

Create `controller-values.yaml`:

```yaml
# Global settings
global:
  existingCompanyTokenSecret: konvu-company-token

# Namespace configuration
namespace:
  create: false  # Already created manually
  name: konvu-controller

# RBAC configuration
rbac:
  create: true

# Controller configuration
controller:
  image:
    repository: registry.konvu.com/konvu-controller
    tag: latest
    pullPolicy: Always

  resources:
    requests:
      cpu: 25m
      memory: 256Mi
    limits:
      cpu: 500m
      memory: 512Mi

# Backend URL
backend:
  url: https://sensors.konvu.com

# SCA worker image configuration
sca:
  image:
    repository: registry.konvu.com/konvu-sca
    tag: latest
    pullPolicy: Always

# LLM configuration
llm:
  existingSecret: konvu-ai-credentials

# Encryption keypair (see Step 2)
encryption:
  enabled: true
  existingSecret: konvu-encryption-keypair

# Image pull credentials
imageCredentials:
  create: true
  registry: registry.konvu.com
  username: konvu
  password: "YOUR_COMPANY_TOKEN"

# Advanced configuration
advanced:
  verbose: false
```

Deploy:

```bash
helm upgrade --install konvu-controller konvu/konvu-controller \
  --namespace konvu-controller \
  --values controller-values.yaml \
  --wait
```

### Verify Controller Deployment

```bash
# Check pod status
kubectl get pods -n konvu-controller -l app.kubernetes.io/name=konvu-controller

# Check logs (should show "Session established with backend")
kubectl logs -n konvu-controller -l app.kubernetes.io/name=konvu-controller --tail=50
```

***

## Step 4: Deploy the Broker

Choose your secret management approach:

### Approach A: Inline Secrets

Create `broker-values.yaml`:

```yaml
# Global settings
global:
  companyToken: "YOUR_COMPANY_TOKEN"

# Namespace configuration
namespace:
  name: konvu-broker

# RBAC configuration
rbac:
  create: true

# Broker configuration
broker:
  image:
    repository: registry.konvu.com/konvu-broker
    tag: latest
    pullPolicy: Always

  replicaCount: 1

  resources:
    requests:
      cpu: 25m
      memory: 256Mi
    limits:
      cpu: 500m
      memory: 512Mi

# Backend URL
backend:
  url: https://sensors.konvu.com

# Encryption keypair (see Step 2)
encryption:
  enabled: true
  existingSecret: konvu-encryption-keypair

# Image pull credentials
imageCredentials:
  create: true
  registry: registry.konvu.com
  username: konvu
  password: "YOUR_COMPANY_TOKEN"

# Advanced configuration
advanced:
  verbose: false
```

Deploy:

```bash
helm upgrade --install konvu-broker konvu/konvu-broker \
  --namespace konvu-broker \
  --create-namespace \
  --values broker-values.yaml \
  --wait
```

### Approach B: Pre-created Secrets

Create secrets first:

```bash
# Create namespace
kubectl create namespace konvu-broker

# Create company token secret
kubectl create secret generic konvu-company-token \
  --from-literal=company-token=YOUR_COMPANY_TOKEN \
  --namespace konvu-broker
```

Git credentials are not part of the broker values — you'll register them per integration in [Step 5](#step-5-connect-github).

Create `broker-values.yaml`:

```yaml
# Global settings
global:
  existingCompanyTokenSecret: konvu-company-token

# Namespace configuration
namespace:
  create: false  # Already created manually
  name: konvu-broker

# RBAC configuration
rbac:
  create: true

# Broker configuration
broker:
  image:
    repository: registry.konvu.com/konvu-broker
    tag: latest
    pullPolicy: Always

  resources:
    requests:
      cpu: 25m
      memory: 256Mi
    limits:
      cpu: 500m
      memory: 512Mi

# Backend URL
backend:
  url: https://sensors.konvu.com

# Encryption keypair (see Step 2)
encryption:
  enabled: true
  existingSecret: konvu-encryption-keypair

# Image pull credentials
imageCredentials:
  create: true
  registry: registry.konvu.com
  username: konvu
  password: "YOUR_COMPANY_TOKEN"

# Advanced configuration
advanced:
  verbose: false
```

Deploy:

```bash
helm upgrade --install konvu-broker konvu/konvu-broker \
  --namespace konvu-broker \
  --values broker-values.yaml \
  --wait
```

### Verify Broker Deployment

```bash
# Check pod status
kubectl get pods -n konvu-broker -l app.kubernetes.io/name=konvu-broker

# Check logs (should show "Session established with backend")
kubectl logs -n konvu-broker -l app.kubernetes.io/name=konvu-broker --tail=50
```

***

## Step 5: Connect GitHub

The broker routes work by integration and reads Git credentials from per-integration Kubernetes Secrets registered in a `konvu-integrations` ConfigMap — not from Helm values.

1. Create your GitHub App and install it on your organization (see [Connecting GitHub](/konvu/get-started/connect-your-environment/source-code/self-hosted-analysis/connecting-github.md)).
2. In Konvu, go to **Integrations** > **GitHub Self Hosted** and enter a name and the App's installation ID. The dialog then shows two commands pre-filled for your integration.
3. Run them against your cluster. They look like this:

```bash
kubectl create secret generic konvu-integration-<INTEGRATION_ID> \
  --from-literal=github-app-id='YOUR_APP_ID' \
  --from-literal=github-app-installation-id='YOUR_INSTALLATION_ID' \
  --from-literal=github-app-private-key="$(cat /path/to/your-github-app.pem)" \
  --namespace konvu-broker

kubectl create configmap konvu-integrations --namespace konvu-broker 2>/dev/null; \
kubectl patch configmap konvu-integrations --namespace konvu-broker --type merge \
  -p '{"data":{"github-<INTEGRATION_ID>":"{\"id\":\"<INTEGRATION_ID>\",\"protocol\":\"github\",\"type\":\"github\",\"url\":\"https://github.com\",\"secretName\":\"konvu-integration-<INTEGRATION_ID>\"}"}}'
```

The `<INTEGRATION_ID>` is generated when you create the integration and pre-filled in the dialog's commands, so create the integration first. The private key is read from the `.pem` file by your own shell — it never leaves your terminal.

If the broker was installed before the `konvu-integrations` ConfigMap existed, it restarts until the ConfigMap appears — this is expected and resolves on its own.

GitLab follows the same pattern, with a `gitlab-pat-token` Secret key and `"protocol":"gitlab"` in the ConfigMap entry.

***

## Step 6: Verify Complete Deployment

Test connectivity from both components:

```bash
# Test controller connectivity
kubectl exec -n konvu-controller deployment/konvu-controller -- \
  wget -qO- https://sensors.konvu.com/health

# Test broker connectivity
kubectl exec -n konvu-broker deployment/konvu-broker -- \
  wget -qO- https://sensors.konvu.com/health

# Check that both components have active sessions
kubectl logs -n konvu-controller -l app.kubernetes.io/name=konvu-controller | grep -i "session"
kubectl logs -n konvu-broker -l app.kubernetes.io/name=konvu-broker | grep -i "session"
```

Expected: Both should show active sessions with the backend.

***

## Optional: AWS-Specific Enhancements

If you're running on AWS EKS and want to use AWS services:

### Use External Secrets Operator with AWS Secrets Manager

If you deployed via Terraform (Path 2), External Secrets Operator is already configured. Otherwise:

1. Install External Secrets Operator:

   ```bash
   helm repo add external-secrets https://charts.external-secrets.io
   helm install external-secrets external-secrets/external-secrets \
     --namespace konvu-controller \
     --set installCRDs=true
   ```
2. Create IAM role with IRSA for service accounts
3. Store secrets in AWS Secrets Manager
4. Create SecretStore and ExternalSecret resources

See [External Secrets Operator documentation](https://external-secrets.io/) for details.

### Use IRSA for AWS Service Access

Add IAM role annotations to service accounts in your values files:

```yaml
serviceAccount:
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::YOUR_ACCOUNT:role/konvu-controller-sa
```

This eliminates long-lived AWS credentials from the cluster.

***

## Next Steps

Your deployment is complete! Continue to [Verification & Next Steps](/konvu/get-started/connect-your-environment/source-code/self-hosted-analysis/verification-and-next-steps.md) to:

1. Monitor your deployment
2. Configure scanner integrations


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.konvu.com/konvu/get-started/connect-your-environment/source-code/self-hosted-analysis/installing-the-broker-and-controller.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
