Setup Qodo Merge
Follow this guide to setup, install, and begin using Qodo Merge in On Prem environments.
Prerequisites
Before deploying, ensure the following are in place:
- Access to a Kubernetes cluster that can reach - artif-reg-self-hosted.codium.ai
- A node with at least - 1 CPUand- 10Gimemory
- Helm v3 installed 
- kubectlCLI installed
Each provider (GitHub, Bitbucket, GitLab) requires:
- A tailored - values.yaml
- Proper secrets configuration ( - .secrets.toml)
- External or locally created Kubernetes secrets 
Github
- Create a - values.yamlfile: This example is using GKE(GCP k8s), ALB as ingress and GCP managed certificate.
image:
  repository: artif-reg-self-hosted.codium.ai/proxy/codium-stack/us-central1-docker.pkg.dev/codium-production/codium-repo-self-hosted/pr-agent
  tag: replicated_b53
  
configMaps:
  main:
    CONFIG.IDENTITY_PROVIDER: ""
    CONFIG.ANALYTICS_FOLDER: "/logs"
envFrom:
  configMapRefs:
    - name: main
      useShortName: true
deployments:
  enabled: true
  ports:
    - containerPort: 3000
      name: http
  resources:
    requests:
      cpu: '1'
      memory: '10Gi'
  command:
    - "python"
  args:
    - "-m"
    - "gunicorn"
    - "-k"
    - "uvicorn.workers.UvicornWorker"
    - "-c"
    - "pr_agent/servers/gunicorn_config.py"
    - "--forwarded-allow-ips"
    - "*"
    - "pr_agent.servers.github_app:app"
  probes:
    startup:
      httpGet:
        path: /self_test
        port: 3000
      failureThreshold: 3
      initialDelaySeconds: 20
      periodSeconds: 45
      successThreshold: 1
      timeoutSeconds: 45
  sidecars:
    analytics:
      image:
        repository: artif-reg-self-hosted.codium.ai/proxy/codium-stack/us-central1-docker.pkg.dev/codium-production/codium-repo-self-hosted/pr-agent-sidecar
        tag: replicated_b53
      command:
        - "python"
        - "main.py"
      args:
        - "--sink"
        - "mixpanel"
        - "--sink"
        - "stdout"
        - "--log_directory"
        - "/logs"
      ports: []
      envFrom:
        configMapRefs:
          - name: main
            useShortName: true
        secretRefs:
          - name: mixpanel
            useShortName: true
volumes:
  settings-volume:
    secret:
      secretName: settings
      useShortName: true
  logs-volume:
    emptyDir: {}
volumeMounts:
  settings-volume:
    mountPath: /app/pr_agent/settings_prod 
  logs-volume:
    mountPath: /logs
ingress:
  enabled: true
  host: example.company.com
  #annotations:
    # Custom annotations goes here
  hosts:
    - paths:
        - path: /
          pathType: Exact
        - path: /api/v1
          pathType: Prefix
        - path: /webhook
          pathType: Prefix
        - path: /installed
          pathType: Prefix
        - path: /uninstalled
          pathType: Prefix
service:
  enabled: true
  port: 3000
  type: NodePort
  ports:
    http:
      targetPort: "http" # named or numeric port in a pod
externalSecrets:
  enabled: true
  clusterSecretStore: true
  secretStoreName: "gcp-backend"
  secrets:
    - targetSecretName: settings
      remoteSecretName: qodo-merge-settings #create this on your secret backend
      data:
        - secretKey: .secrets.toml2. Configure Qodo Merge secrets: You can define either an external or local secret.
To define a local secret, run:
kubectl create secret generic qodo-merge-settings --from-file=.secrets.toml -n $namespaceTo define a .secret.toml file, check out the example below.
- There's a section in the file for each LLM engine. 
- The Github section sets the app installment. 
- Config section: this config depends on what LLMs are available. You can reach Qodo Support to ensure you're configuring this section correctly. 
[anthropic]
key = ""
[aws]
AWS_ACCESS_KEY_ID = ""
AWS_SECRET_ACCESS_KEY = ""
AWS_REGION_NAME = ""
[openai]
key = ""
org = ""
[vertexai]
credentials = ""
[github]
deployment_type = ""
private_key = ""
webhook_secret = ""
app_id = ""
[config]
model_reasoning="claude-sonnet-4-20250514_thinking"
model="claude-3-7-sonnet-20250219"
model_turbo = "gpt-4.1-2025-04-14"
fallback_models=["gpt-4.1-2025-04-14"]- Deploy: Once the - values.yamlfile and the secrets are in place, you need to:
- Login to artifacts-self-hosted.qodo.ai: 
helm registry login artifacts-self-hosted.qodo.ai --username $provided_user --password $provided_password- Pull the latest helm chart: 
helm pull oci://artifacts-self-hosted.qodo.ai/codium-stack/stable/module- Deploy Qodo Merge: 
helm upgrade --install qodo-merge ./module-0.4.4.tgz -f ./values.yaml  -n qodo-merge --create-namespaceBitbucket
- Create a - values.yamlfile: This example is using GKE(GCP k8s), ALB as ingress and GCP managed certificate.- The Ingress section must be updated with proper domain and certificate. 
- When using other cloud providers or native K8s, make sure to update Ingress values and External secrets or mount volumes. 
 
image:
  repository: artif-reg-self-hosted.codium.ai/proxy/codium-stack/us-central1-docker.pkg.dev/codium-production/codium-repo-self-hosted/pr-agent
  tag: replicated_b53
configMaps:
  main:
    CONFIG.IDENTITY_PROVIDER: ""
    CONFIG.ANALYTICS_FOLDER: "/logs"
envFrom:
  configMapRefs:
    - name: main
      useShortName: true
deployments:
  enabled: true
  ports:
    - containerPort: 3000
      name: http
  resources:
    requests:
      cpu: '1'
      memory: '10Gi'
  command:
    - "python"
  args:
    - "-m"
    - "gunicorn"
    - "-k"
    - "uvicorn.workers.UvicornWorker"
    - "-c"
    - "pr_agent/servers/gunicorn_config.py"
    - "--forwarded-allow-ips"
    - "*"
    - "pr_agent.servers.bitbucket_server_webhook:app"
  probes:
    startup:
      httpGet:
        path: /self_test
        port: 3000
      failureThreshold: 3
      initialDelaySeconds: 20
      periodSeconds: 45
      successThreshold: 1
      timeoutSeconds: 45
  sidecars:
    analytics:
      image:
        repository: artif-reg-self-hosted.codium.ai/proxy/codium-stack/us-central1-docker.pkg.dev/codium-production/codium-repo-self-hosted/pr-agent-sidecar
        tag: replicated_b53
      command:
        - "python"
        - "main.py"
      args:
        - "--sink"
        - "mixpanel"
        - "--sink"
        - "stdout"
        - "--log_directory"
        - "/logs"
      ports: []
      envFrom:
        configMapRefs:
          - name: main
            useShortName: true
        secretRefs:
          - name: mixpanel
            useShortName: true
volumes:
  settings-volume:
    secret:
      secretName: settings
      useShortName: true
  logs-volume:
    emptyDir: {}
volumeMounts:
  settings-volume:
    mountPath: /app/pr_agent/settings_prod 
  logs-volume:
    mountPath: /logs
ingress:
  enabled: true
  host: example.company.com
  #annotations:
     # Custom annotations goes here
  hosts:
    - paths:
        - path: /
          pathType: Exact
        - path: /api/v1
          pathType: Prefix
        - path: /webhook
          pathType: Prefix
        - path: /installed
          pathType: Prefix
        - path: /uninstalled
          pathType: Prefix
service:
  enabled: true
  port: 3000
  type: NodePort
  ports:
    http:
      targetPort: "http"
      
externalSecrets:
  enabled: true
  clusterSecretStore: true
  secretStoreName: "gcp-backend"
  secrets:
    - targetSecretName: settings
      remoteSecretName: qodo-merge-settings #create this on your secret backend
      data:
        - secretKey: .secrets.toml
2. Configure Qodo Merge secrets: You can define either an external or local secret.
To define a local secret, run:
kubectl create secret generic qodo-merge-settings --from-file=.secrets.toml -n $namespaceTo define a .secret.toml file, check out the example below.
- There's a section in the file for each LLM engine. 
- The Bitbucket section sets webhook secret, bearer token and Bitbucket URL. 
- Config section: this config depends on what LLMs are available. You can reach Qodo Support to ensure you're configuring this section correctly. 
[anthropic]
key = ""
[aws]
AWS_ACCESS_KEY_ID = ""
AWS_SECRET_ACCESS_KEY = ""
AWS_REGION_NAME = ""
[openai]
key = ""
org = ""
[vertexai]
credentials = ""
[bitbucket_server]
webhook_secret = ""
bearer_token = ""
url = ""
#this Filesystem it's only necessary for Bitbucket Datacenter
[file_system]
directory = "/pr-agent-secrets"
hash_file_names = true
encryption_key = "ia84cjHNYeCW9cyBr_8_XWZ9EMJr67lKsupG55RpXTM=" #this could be any random generate string
[config]
model_reasoning="claude-sonnet-4-20250514_thinking"
model="claude-3-7-sonnet-20250219"
model_turbo = "gpt-4.1-2025-04-14"
fallback_models=["gpt-4.1-2025-04-14"]- Deploy: Once the - values.yamlfile and the secrets are in place, you need to:
- Login to artifacts-self-hosted.qodo.ai: 
helm registry login artifacts-self-hosted.qodo.ai --username $provided_user --password $provided_password- Pull the latest helm chart: 
helm pull oci://artifacts-self-hosted.qodo.ai/codium-stack/stable/module- Deploy Qodo Merge: 
helm upgrade --install qodo-merge ./module-0.4.4.tgz -f ./values.yaml  -n qodo-merge --create-namespaceGitlab
- Create a - values.yamlfile: This example is using GKE(GCP k8s), ALB as ingress and GCP managed certificate.- The Ingress section must be updated with proper domain and certificate. 
- When using other cloud providers or native K8s, make sure to update Ingress values and External secrets or mount volumes. 
 
image:
  repository: artif-reg-self-hosted.codium.ai/proxy/codium-stack/us-central1-docker.pkg.dev/codium-production/codium-repo-self-hosted/pr-agent
  tag: replicated_b53
configMaps:
  main:
    CONFIG.IDENTITY_PROVIDER: ""
    CONFIG.ANALYTICS_FOLDER: "/logs"
    CONFIG.SECRET_PROVIDER: "configuration"
envFrom:
  configMapRefs:
    - name: main
      useShortName: true
deployments:
  enabled: true
  ports:
    - containerPort: 3000
      name: http
  resources:
    requests:
      cpu: '1'
      memory: '10Gi'
  command:
    - "python"
  args:
    - "-m"
    - "gunicorn"
    - "-k"
    - "uvicorn.workers.UvicornWorker"
    - "-c"
    - "pr_agent/servers/gunicorn_config.py"
    - "--forwarded-allow-ips"
    - "*"
    - "pr_agent.servers.gitlab_webhook:app"
  probes:
    startup:
      httpGet:
        path: /self_test
        port: 3000
      failureThreshold: 3
      initialDelaySeconds: 20
      periodSeconds: 45
      successThreshold: 1
      timeoutSeconds: 45
  sidecars:
    analytics:
      image:
        repository: artif-reg-self-hosted.codium.ai/proxy/codium-stack/us-central1-docker.pkg.dev/codium-production/codium-repo-self-hosted/pr-agent-sidecar
        tag: replicated_b53
      command:
        - "python"
        - "main.py"
      args:
        - "--sink"
        - "mixpanel"
        - "--sink"
        - "stdout"
        - "--log_directory"
        - "/logs"
      ports: []
      envFrom:
        configMapRefs:
          - name: main
            useShortName: true
        secretRefs:
          - name: mixpanel
            useShortName: true
volumes:
  settings-volume:
    secret:
      secretName: settings
      useShortName: true
  logs-volume:
    emptyDir: {}
volumeMounts:
  settings-volume:
    mountPath: /app/pr_agent/settings_prod 
  logs-volume:
    mountPath: /logs
ingress:
  enabled: true
  host: example.company.com
  annotations:
    kubernetes.io/ingress.class: "gce"
    kubernetes.io/ingress.allow-http: "true"
    networking.gke.io/v1beta1.FrontendConfig: qodo-merge-frontend-tls-config
    networking.gke.io/managed-certificates: '{{ .Release.Name | trunc 63 | trimSuffix "-" }}'
  hosts:
    - paths:
        - path: /
          pathType: Exact
        - path: /api/v1
          pathType: Prefix
        - path: /webhook
          pathType: Prefix
        - path: /installed
          pathType: Prefix
        - path: /uninstalled
          pathType: Prefix
service:
  enabled: true
  port: 3000
  type: NodePort
  ports:
    http:
      targetPort: "http" # named or numeric port in a pod
externalSecrets:
  enabled: true
  clusterSecretStore: true
  secretStoreName: "gcp-backend"
  secrets:
    - targetSecretName: settings
      remoteSecretName: qodo-merge-settings # create this on your secret backend
      data:
        - secretKey: .secrets.toml- Configure Qodo Merge secrets: You can define either an external or local secret. 
To define a local secret, run:
kubectl create secret generic qodo-merge-settings --from-file=.secrets.toml -n $namespaceTo define a .secret.toml file, check out the example below.
- There's a section in the file for each LLM engine. 
- The GitLab section sets the GitLab secret. 
- Config section: this config depends on what LLMs are available. You can reach Qodo Support to ensure you're configuring this section correctly. 
[anthropic]
key = ""
[aws]
AWS_ACCESS_KEY_ID = ""
AWS_SECRET_ACCESS_KEY = ""
AWS_REGION_NAME = ""
[openai]
key = ""
org = ""
[vertexai]
credentials = ""
[secret_store.gitlab]
key = ""
value = ""
[config]
model_reasoning="claude-sonnet-4-20250514_thinking"
model="claude-3-7-sonnet-20250219"
model_turbo = "gpt-4.1-2025-04-14"
fallback_models=["gpt-4.1-2025-04-14"]- Deploy: Once the - values.yamlfile and the secrets are in place, you need to:
- Login to artifacts-self-hosted.qodo.ai: 
helm registry login artifacts-self-hosted.qodo.ai --username $provided_user --password $provided_password- Pull the latest helm chart: 
helm pull oci://artifacts-self-hosted.qodo.ai/codium-stack/stable/module- Deploy Qodo Merge: 
helm upgrade --install qodo-merge ./module-0.4.4.tgz -f ./values.yaml  -n qodo-merge --create-namespaceLast updated