Skip to content

Latest commit

 

History

History
1488 lines (1240 loc) · 247 KB

File metadata and controls

1488 lines (1240 loc) · 247 KB

Pre-requisite

  • A working Kubernetes cluster
  • kubectl and helm on the client system that you will use to install our Helm charts

Installing Traefik Ingress Controller (optional)

If you plan to use Traefik as your ingress controller, install it before deploying Plane.

  1. Add the Traefik Helm chart repo and update it.

    helm repo add traefik https://traefik.github.io/charts
    helm repo update
  2. Install Traefik into your cluster.

    helm upgrade --install traefik traefik/traefik \
        --create-namespace \
        --namespace traefik \
        --wait

    Once installed, set ingress.ingressClass=traefik when deploying Plane.

Migrating the Ingress Controller

The chart renders one of three ingress templates — nginx, Traefik or OpenShift. Which one is chosen by the controller type, kept separate from the class name, so a class name your controller happens to use (e.g. nginx-new) no longer has to double as the template selector.

ingress.controller selects the resource kind:

ingress.controller value Template rendered Resource kind
traefik (or starts with it) templates/ingress-traefik.yaml traefik.io/v1alpha1 IngressRoute
openshift templates/ingress-openshift.yaml route.openshift.io/v1 Route (one per path)
nginx templates/ingress-nginx.yaml networking.k8s.io/v1 Ingress

nginx, Traefik and OpenShift are the supported configurations. The value is only a selector and is never written into a manifest; the class name comes from ingress.ingressClass (spec.ingressClassName), which can be any string your controller exposes. Any controller value other than traefik*/openshift renders the same standard Ingress as nginx — that is how a class name like nginx-new is served — but only the three above are tested.

No body-size limit on Routes. ingress.traefik.maxRequestBodyBytes has no OpenShift equivalent; HAProxy Routes cannot cap request bodies. Enforce upload limits in the application or at a WAF/CDN in front of the router.

If you leave ingress.controller empty

The selection falls back to ingress.ingressClass, and is exactly what it was before this value existed:

ingressClass with no controller Renders
traefik, or anything starting with it Traefik IngressRoute
openshift OpenShift Routes
nginx Standard Ingress
anything else nothing at all, silently

⚠️ Any class other than nginx, openshift or traefik* renders no ingress while ingress.controller is empty — nginx-new, openshift-default, a custom IngressClass name or an empty string included. helm install succeeds and nothing is reachable. Set ingress.controller: nginx to get a standard Ingress carrying your class name, or ingress.enabled: false if you manage the ingress yourself.

This no-op is kept on purpose rather than widened: an operator on such a class today gets no ingress from the chart and will have their own in place, so making the fallback render one would create a second, conflicting <release>-ingress on upgrade — or fail the upgrade outright if theirs shares that name. Opting in via ingress.controller keeps upgrades inert until you ask for the change.

The default is a Traefik IngressRoute (ingressClass: traefik, no controller). If you are switching to a standard ingress controller, follow the migration steps below.

Configuration snippets

Every snippet below is the ingress block of your values.yaml. All of them also need license.licenseDomain set — no ingress of any kind renders without it:

license:
  licenseDomain: plane.example.com

Already supported — no ingress.controller needed

These four worked before ingress.controller existed and are unchanged. Leave controller out entirely.

1. Traefik IngressRoute — the chart default

ingress:
  enabled: true
  ingressClass: 'traefik'
  traefik:
    maxRequestBodyBytes: 20971520   # 20 MiB upload cap
    entryPoints: []                 # empty = derive from your ssl.* settings

Renders IngressRoute + Middleware. Requires the Traefik CRDs. Any class starting with traefik works here (traefik-v2, traefikee, ...).

2. Standard Ingress with ingress-nginx

ingress:
  enabled: true
  ingressClass: 'nginx'
  ingress_annotations:
    nginx.ingress.kubernetes.io/proxy-body-size: '20m'
    nginx.ingress.kubernetes.io/proxy-buffer-size: '16k'   # avoids 502 "too big header"

Renders one Ingress with ingressClassName: nginx. The class must be exactly nginx for this to work without controller.

3. OpenShift Route's

ingress:
  enabled: true
  ingressClass: 'openshift'
  openshift:
    timeout: '300s'      # router default is 30s and severs /live/ WebSockets
    termination: 'edge'  # edge | reencrypt (passthrough cannot do path routing)
    insecureEdgeTerminationPolicy: 'Redirect'

Renders one Route per path. See examples/values-openshift.yaml for a complete OpenShift values file.

4. No chart-managed ingress — bring your own

ingress:
  enabled: false

Renders nothing at all. Use this when you expose Plane through your own Ingress, HTTPRoute, LoadBalancer Service, Cloudflare Tunnel or service mesh. This is the right setting if you are managing the ingress yourself — do not rely on an unrecognised ingressClass to suppress it.

Newly possible — set ingress.controller

Each of these rendered no ingress at all before this change, because the class name was not one of the three the chart recognised. controller picks the resource kind; ingressClass is then used verbatim as spec.ingressClassName.

5. Standard Ingress with a class name that is not nginx — e.g. a second ingress-nginx install, or an nginx build that exposes its own IngressClass

ingress:
  enabled: true
  controller: 'nginx'        # any value but traefik*/openshift selects the Ingress
  ingressClass: 'nginx-new'  # whatever your controller actually exposes
  ingress_annotations:
    nginx.ingress.kubernetes.io/proxy-body-size: '20m'

Renders one Ingress with ingressClassName: nginx-new.

6. Traefik IngressRoute with a class name that is not traefik*

ingress:
  enabled: true
  controller: 'traefik'
  ingressClass: 'internal-lb'   # unused by the IngressRoute; kept for your own bookkeeping

Renders IngressRoute + Middleware. Useful when your platform's naming convention does not allow a class called traefik.

7. OpenShift Route's with a class name that is not openshift

ingress:
  enabled: true
  controller: 'openshift'
  ingressClass: 'ocp-internal'   # unused by Routes
  openshift:
    timeout: '300s'

Renders one Route per path.

8. OpenShift, letting the ingress-to-route controller convert a plain Ingress

ingress:
  enabled: true
  controller: 'nginx'                 # emit a standard Ingress...
  ingressClass: 'openshift-default'   # ...for OpenShift's router to convert

Renders one Ingress with ingressClassName: openshift-default. Note this path gets no per-route HAProxy timeout, so /live/ WebSockets are subject to the router's 30s default — prefer snippet 3 or 9 unless you specifically need the conversion.

Switching from Traefik to a standard Ingress controller (e.g. nginx)

  1. Install your target ingress controller if it is not already running.

  2. Set ingress.controller and ingress.ingressClass in your values.yaml:

    ingress:
      controller: "nginx"      # selects templates/ingress-nginx.yaml
      ingressClass: "nginx"    # spec.ingressClassName — whichever class your controller exposes (e.g. "nginx-new")
  3. Run helm upgrade:

    helm upgrade plane-app plane/plane-enterprise \
      --namespace plane-ns \
      -f values.yaml \
      --wait

    After the upgrade the IngressRoute and Middleware resources are no longer rendered and will be orphaned — delete them manually:

    kubectl delete ingressroute -n plane-ns -l app.kubernetes.io/instance=plane-app
    kubectl delete middleware    -n plane-ns -l app.kubernetes.io/instance=plane-app
  4. Verify that the new Ingress is admitted and routes traffic before removing the old Traefik resources.

Switching from a standard Ingress controller to Traefik

  1. Install Traefik with CRD support enabled (see Installing Traefik Ingress Controller above).

  2. Set ingress.controller:

    ingress:
      controller: "traefik"
      ingressClass: "traefik"   # unused by the IngressRoute, kept for clarity
  3. Run helm upgrade. The old Ingress resource is orphaned — delete it:

    kubectl delete ingress -n plane-ns plane-app-ingress

Key values controlling template selection

Value Default Effect
ingress.enabled true Master switch — set to false to render no ingress at all.
ingress.controller '' Selects the resource kind: traefik → IngressRoute, openshift → Routes, nginx → standard Ingress with your class name. Empty = legacy selection from ingressClass, where only nginx/openshift/traefik* render anything.
ingress.ingressClass traefik Free-form spec.ingressClassName on the standard Ingress. Also drives the legacy selection while controller is empty. Unused by Traefik and OpenShift.
ingress.traefik.maxRequestBodyBytes 20971520 Max request body size for Traefik's buffering middleware. Ignored when not using Traefik.
ingress.traefik.entryPoints [] Traefik entrypoints for the IngressRoute. Empty means derive from your SSL settings — see below. Ignored when not using Traefik.
ingress.ingress_annotations {} Standard Ingress annotations (e.g. cert-manager). Rendered only on the standard Ingress; the openshift path uses ingress.openshift.route_annotations and Traefik ignores them.
ingress.openshift.timeout 300s HAProxy per-route timeout. The router default of 30s severs /live/ WebSockets and /pi/ streaming.
ingress.openshift.termination edge Route TLS termination (edge or reencrypt; passthrough cannot do path routing).
ingress.openshift.externalCertificate '' Name of a TLS Secret for the router to serve instead of its wildcard cert. OpenShift 4.16+.
ingress.openshift.route_annotations {} Extra annotations on every Route, e.g. haproxy.router.openshift.io/rewrite-target.

TLS options: choosing how HTTPS is handled

TLS is optional. Your ssl.* settings drive two separate derivations — separate because "users are on HTTPS" and "this chart holds the certificate" are different facts:

  1. whether a tls: block is emitted, and which Traefik entrypoint the IngressRoute binds to — both from whether this chart terminates TLS;
  2. the scheme of every URL Plane is told about itself — WEB_URL, APP_BASE_URL, PI_BASE_URL, PLANE_FRONTEND_URL, PLANE_API_HOST, PLANE_OAUTH_REDIRECT_URI, SILO_API_BASE_URL, EXPORT_DOWNLOAD_BASE_URL. (CORS_ALLOWED_ORIGINS always lists both schemes and is unaffected.)

Find the row that matches your environment:

Your setup Set Entrypoint tls: block App URLs
No certificate yet — trial, internal network nothing (default) web http://
You already hold a TLS Secret ssl.tls_secret_name websecure your Secret https://
Let cert-manager issue one ssl.createIssuer + ssl.generateCerts websecure <release>-ssl-cert https://
TLS terminated upstream (ALB, NLB TLS listener, Cloudflare) ssl.externalTermination: true web https://
TLS terminated by Traefik's own entrypoint ssl.externalTermination: true + ingress.traefik.entryPoints: ['websecure'] websecure https://

Only the tls: block requires a Secret this chart can actually see, which is why the last two rows emit none — the chart never names a Secret it does not create.

Note the last two rows share a scheme but need opposite entrypoints: an upstream terminator forwards cleartext, which arrives on web, whereas a Traefik entrypoint carrying its own certificate serves TLS on websecure. That is why ssl.externalTermination sets the URL scheme only and never moves the entrypoint.

Option 1 — No TLS, plain HTTP

The default. Nothing to set; leave the ssl block alone and Plane is reachable at http://<licenseDomain>:

license:
  licenseDomain: plane.example.com
ingress:
  ingressClass: traefik

Good for a quick trial, an air-gapped or internal network, or while you are still sorting out DNS and certificates. Read the entrypoint caveat below before relying on it — and terminate TLS somewhere before exposing Plane on the public internet.

Option 2 — Bring your own certificate

Create a kubernetes.io/tls Secret in the release namespace and name it:

kubectl create secret tls my-tls-secret \
  --cert=fullchain.pem --key=privkey.pem -n plane-ns
ssl:
  tls_secret_name: my-tls-secret

Option 3 — Let cert-manager issue the certificate

Requires cert-manager in the cluster. Both flags are needed — createIssuer alone creates an Issuer but no Certificate, and the chart then treats the install as having no certificate at all:

ssl:
  createIssuer: true
  generateCerts: true
  issuer: http          # or cloudflare / digitalocean
  email: you@example.com
  # token: <dns-provider-api-token>   # required for cloudflare / digitalocean

The Certificate is written to <release-name>-ssl-cert and the IngressRoute references it.

Option 4 — TLS terminated in front of Plane

Use this when something ahead of Plane already terminates TLS and this chart manages no certificate. ssl.externalTermination renders every app URL https:// and emits no tls: block. It does not move the entrypoint, so pick the sub-case that matches where TLS actually ends.

4a — an upstream terminator forwards cleartext (ALB with an ACM cert, NLB with a TLS listener, Cloudflare, most service meshes). Traffic reaches Traefik as plain HTTP, so the route stays on web — the default:

ssl:
  externalTermination: true

4b — Traefik's own entrypoint terminates TLS (websecure.http.tls=true, an ACME certResolver, or a default TLSStore). Traffic reaches Traefik as TLS, so the route must bind websecure as well:

ssl:
  externalTermination: true
ingress:
  traefik:
    entryPoints: ['websecure']

Getting the sub-case wrong is a routing failure, not a certificate failure: a route bound only to websecure never matches cleartext arriving on web, so requests 404 instead of reaching Plane.

Leave externalTermination false if you set ssl.tls_secret_name or ssl.generateCerts; those already imply HTTPS. Use it only for TLS this chart cannot see. Without it, such an install would advertise http:// URLs to itself while being served over HTTPS, breaking OAuth callbacks and export download links.

Overriding the entrypoint names

Only needed if your Traefik installation renamed the default web / websecure entrypoints, or you want to serve both schemes at once:

ingress:
  traefik:
    entryPoints: ['websecure', 'web']   # a bare string also works

Leave it empty (the default) to derive the entrypoint from the table above. This setting controls the entrypoint only — whether a tls: block is emitted still follows your ssl.* configuration. It is also how you select websecure for option 4b, where TLS ends at Traefik itself.

Caveat: check your Traefik entrypoints before relying on plain HTTP

Many Traefik installations redirect web to HTTPS in Traefik's own static configuration:

--entryPoints.web.http.redirections.entryPoint.to=:443
--entryPoints.web.http.redirections.entryPoint.scheme=https
--entryPoints.websecure.http.tls=true

Check yours with:

kubectl get deploy -n traefik <traefik-deployment> \
  -o jsonpath='{.spec.template.spec.containers[0].args}' | tr ',' '\n' | grep -i redirect

If the redirection is present, every plain-HTTP request is answered with a permanent redirect before it reaches a route, so Option 1 cannot serve Plane on that cluster. Either drop the redirection, or use Option 2/3/4.

A note on the standard Ingress path (ingress.controller: nginx)

The ssl.* settings above drive the standard Ingress path too — everything in the table applies except the Entrypoint column, which is Traefik-only:

  • Options 2 and 3 emit the Ingress tls: block, exactly as before.
  • Option 4 (ssl.externalTermination) emits no tls: block and only sets the URL scheme — which is what you want when an ALB, an NLB TLS listener, or nginx-ingress in front of Plane holds the certificate.
ingress:
  controller: nginx
  ingressClass: nginx
  ingress_annotations: { "nginx.ingress.kubernetes.io/proxy-body-size": "5m" }
ssl:
  externalTermination: true    # ALB/NLB/Cloudflare terminates; no Secret here

ingress.ingress_annotations is optional here — earlier releases called len on it and failed to render with error calling len: len of nil pointer when it was left commented out, so ingressClass: nginx needed at least one annotation to work at all. That is fixed; the annotation above is shown because it is useful, not because it is required.

Upgrading from 3.3.0 or earlier

If you configure TLS through ssl.tls_secret_name or ssl.generateCerts + ssl.createIssuer, the rendered ingress is unchanged and no action is needed.

One case needs a value added. Earlier releases always bound the Traefik IngressRoute to websecure and always emitted a tls: block, even when no certificate was configured — pointing at a <release>-ssl-cert Secret that was never created, so Traefik fell back to its built-in self-signed certificate. If you relied on that, or on TLS terminated at Traefik itself, adopt Option 4b — both settings, since externalTermination alone leaves the route on web:

ssl:
  externalTermination: true
ingress:
  traefik:
    entryPoints: ['websecure']

Upgrading RabbitMQ from 3.13 to 4.2

This chart now ships rabbitmq:4.2.9-management-alpine. RabbitMQ 3.x is end-of-life and no longer receives security updates.

If you are upgrading an existing install with services.rabbitmq.local_setup: true, do this first. The chart upgrade restarts the broker StatefulSet against the same volume, and RabbitMQ requires all stable feature flags to be enabled before a major upgrade — otherwise the 4.2 node refuses to start and your queues are unreachable until you roll back.

# 1. While still on 3.13, enable every stable feature flag.
kubectl -n <namespace> exec <release>-rabbitmq-wl-0 -- rabbitmqctl enable_feature_flag all

# 2. Confirm nothing stable is left disabled. Only `khepri_db` should remain,
#    and it MUST stay disabled -- a 3.13 node with Khepri enabled cannot be
#    upgraded to 4.x at all and needs a blue-green migration instead.
kubectl -n <namespace> exec <release>-rabbitmq-wl-0 -- rabbitmqctl list_feature_flags

# 3. Now run the chart upgrade, then confirm the broker came back.
kubectl -n <namespace> exec <release>-rabbitmq-wl-0 -- rabbitmqctl status | grep 'RabbitMQ version'

Notes:

  • Do not jump straight to 4.3. RabbitMQ does not support a direct 3.13 → 4.3 upgrade (version upgradability); 4.2 is the supported hop, and a later chart release will move to 4.3. Two further things break on 4.3 but not on 4.2: Celery's control/event queues (fixed in the application by CELERY_CONTROL_QUEUE_EXCLUSIVE / CELERY_EVENT_QUEUE_EXCLUSIVE), and x-consumer-timeout on classic queues.
  • Downgrades do not work. A 4.x node will not start on a data directory it has already upgraded, so keep a volume snapshot if you need a way back.
  • No queue changes are required. Existing queues keep their arguments and are re-declared as-is by the application; durable messages survive the restart. Verified end to end on a 3.13.6 → 4.2.9 in-place upgrade with pre-existing queues.
  • Using an external broker? If services.rabbitmq.local_setup: false and you point external_rabbitmq_url at a managed broker (Amazon MQ, CloudAMQP), this chart does not manage its version — upgrade it on the provider side, following the same feature-flag prerequisite.

Installing Plane

  1. Open Terminal or any other command-line app that has access to Kubernetes tools on your local system.

  2. Set the following environment variables.

    Copy the format of constants below, paste it on Terminal to start setting environment variables, set values for each variable, and hit ENTER or RETURN.

    PLANE_VERSION=v3.1.4 # or the last released version
    DOMAIN_NAME=<subdomain.domain.tld or domain.tld>
  3. Add Plane helm chart repo

    Continue to be on the same Terminal window as with the previous steps, copy the code below, paste it on Terminal, and hit ENTER or RETURN.

    helm repo add plane https://helm.plane.so/
  4. Set-up and customization

    • Quick set-up

      This is the fastest way to deploy Plane with default settings. This will create stateful deployments for Postgres, Rabbitmq, Redis/Valkey, and Minio with a persistent volume claim using the default storage class. This also sets up the ingress routes for you using traefik ingress class.

      To customize this, see Custom ingress routes below.

      Continue to be on the same Terminal window as you have so far, copy the code below, and paste it on your Terminal screen.

      helm upgrade --install plane-app plane/plane-enterprise \
          --create-namespace \
          --namespace plane \
          --set license.licenseDomain=${DOMAIN_NAME} \
          --set planeVersion=${PLANE_VERSION} \
          --set ingress.enabled=true \
          --set ingress.ingressClass=traefik \
          --timeout 10m \
          --wait \
          --wait-for-jobs

      This is the basic setup required for Plane-EE. You can customize the default values for namespace and appname as needed. Additional settings can be configured by referring to the Configuration Settings section.

      Using a Custom StorageClass

      To specify a custom StorageClass for Plane-Enterprise components, add the following options to the above helm upgrade --install command:

      --set env.storageClass=<your-storageclass-name>
    • Advance set-up

      For more control over your set-up, run the script below to download the values.yaml file and and edit using any editor like Vim or Nano.

      helm  show values plane/plane-enterprise > values.yaml
      vi values.yaml

      Make sure you set the minimum required values as below.

      • planeVersion: v3.1.4 <or the last released version>

      • license.licenseDomain: <The domain you have specified to host Plane>

      • ingress.enabled: <true | false>

      • ingress.controller: <traefik | openshift | nginx — required unless ingressClass is exactly nginx/openshift/traefik*>

      • ingress.ingressClass: <traefik or any other ingress class configured in your cluster>

      • env.storageClass: <default storage class configured in your cluster>

        See Available customizations for more details.

      After saving the values.yaml file, continue to be on the same Terminal window as on the previous steps, copy the code below, and paste it on your Terminal screen.

      helm upgrade --install plane-app plane/plane-enterprise \
          --create-namespace \
          --namespace plane \
          -f values.yaml \
          --timeout 10m \
          --wait \
          --wait-for-jobs

Available customizations

License

Setting Default Required Description
planeVersion v3.1.4 Yes Specifies the version of Plane to be deployed. Copy this from prime.plane.so.
license.licenseDomain plane.example.com Yes The fully-qualified domain name (FQDN) in the format sudomain.domain.tld or domain.tld that the license is bound to. It is also attached to your ingress host to access Plane.

Air-gapped Settings

Setting Default Required Description
airgapped.enabled false No Specifies the airgapped mode the Plane API runs in.
airgapped.s3Secrets [] No List of Kubernetes Secrets containing CA certificates to install. Each item must have name (Secret name) and key (file key in the Secret). Example: kubectl -n plane create secret generic plane-s3-ca --from-file=s3-custom-ca.crt=/path/to/ca.crt. Supports multiple certs (e.g. S3 + internal CA).
airgapped.s3SecretName "" No (Deprecated, backward compatibility) Name of a single Kubernetes Secret containing the S3 CA cert. Used only when s3Secrets is empty. Prefer migrating to s3Secrets.
airgapped.s3SecretKey "" No (Deprecated, backward compatibility) Key (filename) of the cert file inside the Secret. Used only when s3Secrets is empty. Set together with airgapped.s3SecretName.

Backward compatibility: custom S3 CA (upgrading from older charts)

If you previously used the single-secret custom CA configuration (airgapped.s3SecretName and airgapped.s3SecretKey), it continues to work. No change is required when upgrading.

  • Old configuration (still supported): Set airgapped.s3SecretName to your Secret name and airgapped.s3SecretKey to the key (e.g. s3-custom-ca.crt). The chart mounts that single cert, runs update-ca-certificates, and sets AWS_CA_BUNDLE to the system bundle path.
  • New configuration (recommended): Use airgapped.s3Secrets with a list of { name, key } entries. This allows multiple CA certificates (e.g. S3 endpoint CA and internal PKI) and matches the same runtime behavior.

Migration (optional): To move from the deprecated keys to s3Secrets, set for example:

airgapped:
  enabled: true
  s3Secrets:
    - name: plane-s3-ca      # same as your previous s3SecretName
      key: s3-custom-ca.crt  # same as your previous s3SecretKey
  # s3SecretName and s3SecretKey can be removed after migration

Pod Security (PSA restricted)

Plane's first-party images run as non-root, so the chart can render a hardened pod- and container-level securityContext that satisfies the Kubernetes Pod Security Admission restricted profile. This is the Helm equivalent of the kustomize nonroot-security-context component, and is opt-in (securityContext.enabled=false by default) so existing installs are unchanged.

When enabled, the context is applied to all first-party Plane workloads (api, web, space, admin, live, worker, beat-worker, automation-consumer, outbox-poller, silo, monitor, iframely, runner, pi-api/beat/worker, and the migration Jobs — including their busybox init containers).

It is not applied to the bundled local infrastructure (postgres, redis, rabbitmq, minio, opensearch), which use third-party images with their own UID/GID requirements and are intended for local/dev use — run those externally in hardened clusters and leave local_setup off. The email service also keeps its own securityContext (its image pins UID 100).

Setting Default Required Description
securityContext.enabled false No Master switch. When true, renders the pod- and container-level securityContext blocks.
securityContext.podSecurityContext see values.yaml No Map rendered at spec.template.spec.securityContext. Defaults to PSA restricted settings.
securityContext.containerSecurityContext see values.yaml No Map rendered at each container's/initContainer's securityContext. PSA restricted defaults.

Enable with PSA-restricted defaults (UID/GID 1000):

helm upgrade --install plane-app plane/plane-enterprise \
    --namespace plane \
    --set securityContext.enabled=true

To pin a specific UID (e.g. 10001), override the relevant keys:

securityContext:
  enabled: true
  podSecurityContext:
    runAsUser: 10001
    runAsGroup: 10001
    fsGroup: 10001
  containerSecurityContext:
    runAsUser: 10001

OpenShift (restricted-v2 SCC)

OpenShift is the inverse case: it refuses to let you choose the UID at all. The restricted-v2 SCC ignores the image's USER, assigns an arbitrary UID from the namespace's range, and places the process in group 0. It also validates the pod's own request, using a different strategy for each field:

  • runAsUserMustRunAsRange. Must fall inside the namespace's openshift.io/sa.scc.uid-range annotation.
  • fsGroupMustRunAs. Must match the range or value derived from openshift.io/sa.scc.supplemental-groups, falling back to the UID range when that annotation is absent.

Either way, a manifest naming a specific runAsUser or fsGroup outside what the namespace allows is rejected at admission, so enabling the block above with its defaults means nothing schedules.

Keep the hardening and drop only the IDs. A null in a values file removes the key during Helm's coalescing, so the rendered securityContext keeps runAsNonRoot, seccompProfile and the dropped capabilities while carrying no UID:

helm upgrade --install plane-app plane/plane-enterprise \
    --namespace plane \
    -f my-values.yaml \
    -f examples/values-openshift.yaml

examples/values-openshift.yaml applies that, un-pins the email service's uid 100, selects the OpenShift ingress path, and forces the bundled datastores off. Three things to know before you use it:

  • Image requirement. The images must grant group 0 write access to the paths they write at runtime. Older images crash under an arbitrary UID — nginx exits with mkdir() "/var/cache/nginx/client_temp" failed (13: Permission denied).

  • Datastores must be external. postgres, redis, rabbitmq, minio and opensearch are third-party images with baked-in UID and data-directory ownership; they cannot run under an arbitrary UID and the chart deliberately does not apply the hardened context to them. Use managed services and leave local_setup off, or grant those ServiceAccounts a relaxed SCC.

  • Upgrading an existing deployment: verify before you rely on it. Moving a running install from the pinned-uid-1000 posture to this one often needs no data migration, because kubelet re-applies fsGroup to volume contents on mount — but that is not guaranteed, and a PVC left owned by uid/gid 1000 is unwritable by the SCC-assigned identity. Whether it happens depends on the CSI driver:

    • fsGroupPolicy: ReadWriteOnceWithFSType (the default) only relabels ReadWriteOnce volumes with a defined fsType — an RWX volume (NFS, EFS, Azure Files) gets nothing.
    • fsGroupPolicy: None disables it entirely.
    • A driver advertising VOLUME_MOUNT_GROUP takes ownership over itself, and both fsGroupPolicy and fsGroupChangePolicy are ignored.

    Check yours with kubectl get csidriver <driver> -o jsonpath='{.spec.fsGroupPolicy}', and rehearse the upgrade against a snapshot or clone of the real PVCs before doing it in production. If ownership is not relabelled, chown -R the volume to the namespace's assigned GID from a maintenance pod.

Docker Registry

Setting Default Required Description
dockerRegistry.enabled false No Enable to configure image pull secrets for pulling images from a private docker registry. When enabled, you can either provide credentials to create a new secret or use an existing Kubernetes secret.
dockerRegistry.existingSecret No Name of an existing Kubernetes secret containing docker registry credentials. When specified, the chart will use this secret for imagePullSecrets instead of creating a new one. The secret should be of type kubernetes.io/dockerconfigjson. If left empty, credentials below will be used to create a new secret.
dockerRegistry.registry index.docker.io/v1/ No Docker registry URL. Only used when dockerRegistry.existingSecret is empty.
dockerRegistry.loginid No Login ID / Username for the docker registry. Only used when dockerRegistry.existingSecret is empty.
dockerRegistry.password No Password or Token for the docker registry. Only used when dockerRegistry.existingSecret is empty.

Postgres

Setting Default Required Description
services.postgres.local_setup true Plane uses postgres as the primary database to store all the transactional data. This database can be hosted within kubernetes as part of helm chart deployment or can be used as hosted service remotely (e.g. aws rds or similar services). Set this to true when you choose to setup stateful deployment of postgres. Mark it as false when using a remotely hosted database
services.postgres.image postgres:15.7-alpine Using this key, user must provide the docker image name to setup the stateful deployment of postgres. (must be set when services.postgres.local_setup=true)
services.postgres.pullPolicy IfNotPresent Using this key, user can set the pull policy for the stateful deployment of postgres. (must be set when services.postgres.local_setup=true)
services.postgres.servicePort 5432 This key sets the default port number to be used while setting up stateful deployment of postgres.
services.postgres.volumeSize 2Gi While setting up the stateful deployment, while creating the persistant volume, volume allocation size need to be provided. This key helps you set the volume allocation size. Unit of this value must be in Mi (megabyte) or Gi (gigabyte)
env.default_cluster_domain cluster.local Kubernetes internal cluster domain used to build in-cluster service URLs (<service>.<namespace>.svc.<domain>). Override this if your cluster uses a non-default domain.
env.pgdb_username plane Database credentials are requried to access the hosted stateful deployment of postgres. Use this key to set the username for the stateful deployment.
env.pgdb_password plane Database credentials are requried to access the hosted stateful deployment of postgres. Use this key to set the password for the stateful deployment.
env.pgdb_name plane Database name to be used while setting up stateful deployment of Postgres
services.postgres.assign_cluster_ip false Set it to true if you want to assign ClusterIP to the service
services.postgres.nodeSelector {} This key allows you to set the node selector for the stateful deployment of postgres. This is useful when you want to run the deployment on specific nodes in your Kubernetes cluster.
services.postgres.tolerations [] This key allows you to set the tolerations for the stateful deployment of postgres. This is useful when you want to run the deployment on nodes with specific taints in your Kubernetes cluster.
services.postgres.affinity {} This key allows you to set the affinity rules for the stateful deployment of postgres. This is useful when you want to control how pods are scheduled on nodes in your Kubernetes cluster.
services.postgres.labels {} This key allows you to set custom labels for the stateful deployment of postgres. This is useful for organizing and selecting resources in your Kubernetes cluster.
services.postgres.annotations {} This key allows you to set custom annotations for the stateful deployment of postgres. This is useful for adding metadata or configuration hints to your resources.
env.pgdb_remote_url Users can also decide to use the remote hosted database and link to Plane deployment. Ignoring all the above keys, set services.postgres.local_setup to false and set this key with remote connection url.

Redis/Valkey Setup

Setting Default Required Description
services.redis.local_setup true Plane uses valkey to cache the session authentication and other static data. This database can be hosted within kubernetes as part of helm chart deployment or can be used as hosted service remotely (e.g. aws rds or similar services). Set this to true when you choose to setup stateful deployment of redis. Mark it as false when using a remotely hosted database
services.redis.image valkey/valkey:7.2.11-alpine Using this key, user must provide the docker image name to setup the stateful deployment of redis. (must be set when services.redis.local_setup=true)
services.redis.pullPolicy IfNotPresent Using this key, user can set the pull policy for the stateful deployment of redis. (must be set when services.redis.local_setup=true)
services.redis.servicePort 6379 This key sets the default port number to be used while setting up stateful deployment of redis.
services.redis.volumeSize 500Mi While setting up the stateful deployment, while creating the persistant volume, volume allocation size need to be provided. This key helps you set the volume allocation size. Unit of this value must be in Mi (megabyte) or Gi (gigabyte)
services.redis.assign_cluster_ip false Set it to true if you want to assign ClusterIP to the service
services.redis.nodeSelector {} This key allows you to set the node selector for the stateful deployment of redis. This is useful when you want to run the deployment on specific nodes in your Kubernetes cluster.
services.redis.tolerations [] This key allows you to set the tolerations for the stateful deployment of redis. This is useful when you want to run the deployment on nodes with specific taints in your Kubernetes cluster.
services.redis.affinity {} This key allows you to set the affinity rules for the stateful deployment of redis. This is useful when you want to control how pods are scheduled on nodes in your Kubernetes cluster.
services.redis.labels {} This key allows you to set custom labels for the stateful deployment of redis. This is useful for organizing and selecting resources in your Kubernetes cluster.
services.redis.annotations {} This key allows you to set custom annotations for the stateful deployment of redis. This is useful for adding metadata or configuration hints to your resources.
env.remote_redis_url Users can also decide to use the remote hosted database and link to Plane deployment. Ignoring all the above keys, set services.redis.local_setup to false and set this key with remote connection url.

RabbitMQ Setup

Setting Default Required Description
services.rabbitmq.local_setup true Plane uses rabbitmq as message queuing system. This can be hosted within kubernetes as part of helm chart deployment or can be used as hosted service remotely (e.g. aws mq or similar services). Set this to true when you choose to setup stateful deployment of rabbitmq. Mark it as false when using a remotely hosted service
services.rabbitmq.image rabbitmq:4.2.9-management-alpine Using this key, user must provide the docker image name to setup the stateful deployment of rabbitmq. (must be set when services.rabbitmq.local_setup=true)
services.rabbitmq.pullPolicy IfNotPresent Using this key, user can set the pull policy for the stateful deployment of rabbitmq. (must be set when services.rabbitmq.local_setup=true)
services.rabbitmq.servicePort 5672 This key sets the default port number to be used while setting up stateful deployment of rabbitmq.
services.rabbitmq.managementPort 15672 This key sets the default management port number to be used while setting up stateful deployment of rabbitmq.
services.rabbitmq.volumeSize 100Mi While setting up the stateful deployment, while creating the persistant volume, volume allocation size need to be provided. This key helps you set the volume allocation size. Unit of this value must be in Mi (megabyte) or Gi (gigabyte)
services.rabbitmq.default_user plane Credentials are requried to access the hosted stateful deployment of rabbitmq. Use this key to set the username for the stateful deployment.
services.rabbitmq.default_password plane Credentials are requried to access the hosted stateful deployment of rabbitmq. Use this key to set the password for the stateful deployment.
services.rabbitmq.assign_cluster_ip false Set it to true if you want to assign ClusterIP to the service
services.rabbitmq.nodeSelector {} This key allows you to set the node selector for the stateful deployment of rabbitmq. This is useful when you want to run the deployment on specific nodes in your Kubernetes cluster.
services.rabbitmq.tolerations [] This key allows you to set the tolerations for the stateful deployment of rabbitmq. This is useful when you want to run the deployment on nodes with specific taints in your Kubernetes cluster.
services.rabbitmq.affinity {} This key allows you to set the affinity rules for the stateful deployment of rabbitmq. This is useful when you want to control how pods are scheduled on nodes in your Kubernetes cluster.
services.rabbitmq.labels {} This key allows you to set custom labels for the stateful deployment of rabbitmq. This is useful for organizing and selecting resources in your Kubernetes cluster.
services.rabbitmq.annotations {} This key allows you to set custom annotations for the stateful deployment of rabbitmq. This is useful for adding metadata or configuration hints to your resources.
services.rabbitmq.external_rabbitmq_url Users can also decide to use the remote hosted service and link to Plane deployment. Ignoring all the above keys, set services.rabbitmq.local_setup to false and set this key with remote connection url.

OpenSearch Setup

Setting Default Required Description
services.opensearch.local_setup false Plane uses opensearch as the search and analytics engine. This can be hosted within kubernetes as part of helm chart deployment or can be used as hosted service remotely (e.g. AWS OpenSearch Service or similar services). Set this to true when you choose to setup stateful deployment of opensearch. Mark it as false when using a remotely hosted service
services.opensearch.image opensearchproject/opensearch:3.3.2 Using this key, user must provide the docker image name to setup the stateful deployment of opensearch. (must be set when services.opensearch.local_setup=true)
services.opensearch.pullPolicy IfNotPresent Using this key, user can set the pull policy for the stateful deployment of opensearch. (must be set when services.opensearch.local_setup=true)
services.opensearch.servicePort 9200 This key sets the default port number to be used while setting up stateful deployment of opensearch.
services.opensearch.volumeSize 5Gi While setting up the stateful deployment, while creating the persistant volume, volume allocation size need to be provided. This key helps you set the volume allocation size. Unit of this value must be in Mi (megabyte) or Gi (gigabyte)
services.opensearch.username plane Credentials are requried to access the hosted stateful deployment of opensearch. Use this key to set the username for the stateful deployment.
services.opensearch.password Secure@Pass#123!%^&* Credentials are requried to access the hosted stateful deployment of opensearch. Use this key to set the password for the stateful deployment. Password Complexity Requirements: Must be at least 8 characters long and contain at least one uppercase letter, one lowercase letter, one digit, and one special character (e.g., !@#$%^&*).
services.opensearch.memoryLimit 3Gi Every deployment in kubernetes can be set to use maximum memory they are allowed to use. This key sets the memory limit for this deployment to use.
services.opensearch.cpuLimit 750m Every deployment in kubernetes can be set to use maximum cpu they are allowed to use. This key sets the cpu limit for this deployment to use.
services.opensearch.memoryRequest 2Gi Every deployment in kubernetes can be set to use minimum memory they are allowed to use. This key sets the memory request for this deployment to use.
services.opensearch.cpuRequest 500m Every deployment in kubernetes can be set to use minimum cpu they are allowed to use. This key sets the cpu request for this deployment to use.
services.opensearch.assign_cluster_ip false Set it to true if you want to assign ClusterIP to the service
services.opensearch.nodeSelector {} This key allows you to set the node selector for the stateful deployment of opensearch. This is useful when you want to run the deployment on specific nodes in your Kubernetes cluster.
services.opensearch.tolerations [] This key allows you to set the tolerations for the stateful deployment of opensearch. This is useful when you want to run the deployment on nodes with specific taints in your Kubernetes cluster.
services.opensearch.affinity {} This key allows you to set the affinity rules for the stateful deployment of opensearch. This is useful when you want to control how pods are scheduled on nodes in your Kubernetes cluster.
services.opensearch.labels {} This key allows you to set custom labels for the stateful deployment of opensearch. This is useful for organizing and selecting resources in your Kubernetes cluster.
services.opensearch.annotations {} This key allows you to set custom annotations for the stateful deployment of opensearch. This is useful for adding metadata or configuration hints to your resources.
env.opensearch_remote_url Users can also decide to use the remote hosted service and link to Plane deployment. Ignoring all the above keys, set services.opensearch.local_setup to false and set this key with remote connection url.
env.opensearch_remote_username Username for remote OpenSearch service. Required when services.opensearch.local_setup=false and env.opensearch_remote_url is set. Note: This is not a secret and should be configured in values.yaml, not in external secrets.
env.opensearch_remote_password Password for remote OpenSearch service. Required when services.opensearch.local_setup=false and env.opensearch_remote_url is set. This can be configured in values.yaml or provided via external secrets (opensearch_existingSecret with OPENSEARCH_PASSWORD). Password Complexity Requirements: Must be at least 8 characters long and contain at least one uppercase letter, one lowercase letter, one digit, and one special character (e.g., !@#$%^&*).
env.opensearch_index_prefix plane_ Prefix to be used for OpenSearch indices. This helps organize indices in a multi-tenant or multi-environment setup.
env.opensearch_embedding_dimension 1536 Embedding vector dimension used for OpenSearch semantic/vector indexing.

Doc Store (Minio/S3/GCS) Setup

Setting Default Required Description
services.minio.local_setup true Plane uses minio as the default file storage drive. This storage can be hosted within kubernetes as part of helm chart deployment or can be used as hosted service remotely (e.g. aws S3 or similar services). Set this to true when you choose to setup stateful deployment of minio. Mark it as false when using a remotely hosted database
services.minio.image minio/minio:latest Using this key, user must provide the docker image name to setup the stateful deployment of minio. (must be set when services.minio.local_setup=true)
services.minio.image_mc minio/mc:latest Using this key, user must provide the docker image name to setup the job deployment of minio client. (must be set when services.minio.local_setup=true)
services.minio.init_image busybox Using this key, user must provide the docker image name used by the init container of the minio client job, which waits for minio to become resolvable. (must be set when services.minio.local_setup=true)
services.minio.pullPolicy IfNotPresent Using this key, user can set the pull policy for the stateful deployment of minio. (must be set when services.minio.local_setup=true)
services.minio.volumeSize 3Gi While setting up the stateful deployment, while creating the persistant volume, volume allocation size need to be provided. This key helps you set the volume allocation size. Unit of this value must be in Mi (megabyte) or Gi (gigabyte)
services.minio.root_user admin Storage credentials are requried to access the hosted stateful deployment of minio. Use this key to set the username for the stateful deployment.
services.minio.root_password password Storage credentials are requried to access the hosted stateful deployment of minio. Use this key to set the password for the stateful deployment.
services.minio.env.minio_endpoint_ssl false (Optional) Env to enforce HTTPS when connecting to minio uploads bucket
env.docstore_bucket uploads Yes Storage bucket name is required as part of configuration. This is where files will be uploaded irrespective of if you are using Minio or external S3 (or compatible) storage service
env.doc_upload_size_limit 5242880 Yes Document Upload Size Limit (default to 5Mb)
services.minio.assign_cluster_ip false Set it to true if you want to assign ClusterIP to the service
services.minio.nodeSelector {} This key allows you to set the node selector for the stateful deployment of minio. This is useful when you want to run the deployment on specific nodes in your Kubernetes cluster.
services.minio.tolerations [] This key allows you to set the tolerations for the stateful deployment of minio. This is useful when you want to run the deployment on nodes with specific taints in your Kubernetes cluster.
services.minio.affinity {} This key allows you to set the affinity rules for the stateful deployment of minio. This is useful when you want to control how pods are scheduled on nodes in your Kubernetes cluster.
services.minio.labels {} This key allows you to set custom labels for the stateful deployment of minio. This is useful for organizing and selecting resources in your Kubernetes cluster.
services.minio.annotations {} This key allows you to set custom annotations for the stateful deployment of minio. This is useful for adding metadata or configuration hints to your resources.
env.aws_access_key External S3 (or compatible) storage service provides access key for the application to connect and do the necessary upload/download operations. To be provided when services.minio.local_setup=false
env.aws_secret_access_key External S3 (or compatible) storage service provides secret access key for the application to connect and do the necessary upload/download operations. To be provided when services.minio.local_setup=false
env.aws_region External S3 (or compatible) storage service providers creates any buckets in user selected region. This is also shared with the user as region for the application to connect and do the necessary upload/download operations. To be provided when services.minio.local_setup=false
env.aws_s3_endpoint_url External S3 (or compatible) storage service providers shares a endpoint_url for the integration purpose for the application to connect and do the necessary upload/download operations. To be provided when services.minio.local_setup=false
env.use_storage_proxy false When set to true, all S3 (or compatible) file GET requests from the browser are proxied through Plane's API service instead of accessing the S3 endpoint directly. Enable this if your storage endpoint is not accessible publicly or you want to control/download access through the API. Default is false. Recommended true when storage_provider=GCS so browser uploads are proxied server-side and the GCS bucket needs no CORS configuration.
env.storage_provider S3 Storage backend selection. S3 (default) covers MinIO and any S3-compatible service. Set to GCS to use Google Cloud Storage native mode. When GCS, MinIO is disabled and the env.gcs_* settings below are used.
env.gcs_bucket_name GCS bucket name. Used only when storage_provider=GCS. Falls back to env.docstore_bucket when left empty.
env.gcs_project_id (Optional) GCP project ID for the GCS client. Used only when storage_provider=GCS.
env.gcs_credentials_json (Optional) Inline service-account JSON, stored in the doc-store Secret and passed as GCS_CREDENTIALS_JSON. Highest-priority credential source. Used only when storage_provider=GCS.
env.gcs_credentials_path (Optional) In-container path to a service-account file (e.g. /etc/gcs/service-account.json) that you mount yourself. Used when gcs_credentials_json is empty. If both are empty, Application Default Credentials (e.g. GKE Workload Identity) are used. Used only when storage_provider=GCS.
env.allow_all_attachment_types false When set to true, allows all file types as attachments. When false, only permitted types are allowed. Default is false.
env.enable_drf_spectacular false When set to true, enables drf-spectacular OpenAPI schema generation for the API (ENABLE_DRF_SPECTACULAR). Default is false.

Web Deployment

Setting Default Required Description
services.web.replicas 1 Yes Kubernetes helps you with scaling up/down the deployments. You can run 1 or more pods for each deployment. This key helps you setting up number of replicas you want to run for this deployment. It must be >=1
services.web.memoryLimit 1000Mi Every deployment in kubernetes can be set to use maximum memory they are allowed to use. This key sets the memory limit for this deployment to use.
services.web.cpuLimit 500m Every deployment in kubernetes can be set to use maximum cpu they are allowed to use. This key sets the cpu limit for this deployment to use.
services.web.memoryRequest 128Mi Every deployment in kubernetes can be set to use minimum memory they are allowed to use. This key sets the memory request for this deployment to use.
services.web.cpuRequest 100m Every deployment in kubernetes can be set to use minimum cpu they are allowed to use. This key sets the cpu request for this deployment to use.
services.web.image makeplane/web-commercial This deployment needs a preconfigured docker image to function. Docker image name is provided by the owner and must not be changed for this deployment
services.web.pullPolicy Always Using this key, user can set the pull policy for the deployment of web.
services.web.assign_cluster_ip false Set it to true if you want to assign ClusterIP to the service
services.web.nodeSelector {} This key allows you to set the node selector for the deployment of web. This is useful when you want to run the deployment on specific nodes in your Kubernetes cluster.
services.web.tolerations [] This key allows you to set the tolerations for the deployment of web. This is useful when you want to run the deployment on nodes with specific taints in your Kubernetes cluster.
services.web.affinity {} This key allows you to set the affinity rules for the deployment of web. This is useful when you want to control how pods are scheduled on nodes in your Kubernetes cluster.
services.web.labels {} Custom labels to add to the web deployment
services.web.annotations {} Custom annotations to add to the web deployment

Space Deployment

Setting Default Required Description
services.space.replicas 1 Yes Kubernetes helps you with scaling up/down the deployments. You can run 1 or more pods for each deployment. This key helps you setting up number of replicas you want to run for this deployment. It must be >=1
services.space.memoryLimit 1000Mi Every deployment in kubernetes can be set to use maximum memory they are allowed to use. This key sets the memory limit for this deployment to use.
services.space.cpuLimit 500m Every deployment in kubernetes can be set to use maximum cpu they are allowed to use. This key sets the cpu limit for this deployment to use.
services.space.memoryRequest 256Mi Every deployment in kubernetes can be set to use minimum memory they are allowed to use. This key sets the memory request for this deployment to use.
services.space.cpuRequest 100m Every deployment in kubernetes can be set to use minimum cpu they are allowed to use. This key sets the cpu request for this deployment to use.
services.space.image makeplane/space-commercial This deployment needs a preconfigured docker image to function. Docker image name is provided by the owner and must not be changed for this deployment
services.space.pullPolicy Always Using this key, user can set the pull policy for the deployment of space.
services.space.assign_cluster_ip false Set it to true if you want to assign ClusterIP to the service
services.space.nodeSelector {} This key allows you to set the node selector for the deployment of space. This is useful when you want to run the deployment on specific nodes in your Kubernetes cluster.
services.space.tolerations [] This key allows you to set the tolerations for the deployment of space. This is useful when you want to run the deployment on nodes with specific taints in your Kubernetes cluster.
services.space.affinity {} This key allows you to set the affinity rules for the deployment of space. This is useful when you want to control how pods are scheduled on nodes in your Kubernetes cluster.
services.space.labels {} Custom labels to add to the space deployment
services.space.annotations {} Custom annotations to add to the space deployment

Admin Deployment

Setting Default Required Description
services.admin.replicas 1 Yes Kubernetes helps you with scaling up/down the deployments. You can run 1 or more pods for each deployment. This key helps you setting up number of replicas you want to run for this deployment. It must be >=1
services.admin.memoryLimit 1000Mi Every deployment in kubernetes can be set to use maximum memory they are allowed to use. This key sets the memory limit for this deployment to use.
services.admin.cpuLimit 500m Every deployment in kubernetes can be set to use maximum cpu they are allowed to use. This key sets the cpu limit for this deployment to use.
services.admin.memoryRequest 128Mi Every deployment in kubernetes can be set to use minimum memory they are allowed to use. This key sets the memory request for this deployment to use.
services.admin.cpuRequest 100m Every deployment in kubernetes can be set to use minimum cpu they are allowed to use. This key sets the cpu request for this deployment to use.
services.admin.image makeplane/admin-commercial This deployment needs a preconfigured docker image to function. Docker image name is provided by the owner and must not be changed for this deployment
services.admin.pullPolicy Always Using this key, user can set the pull policy for the deployment of admin.
services.admin.assign_cluster_ip false Set it to true if you want to assign ClusterIP to the service
services.admin.nodeSelector {} This key allows you to set the node selector for the deployment of admin. This is useful when you want to run the deployment on specific nodes in your Kubernetes cluster.
services.admin.tolerations [] This key allows you to set the tolerations for the deployment of admin. This is useful when you want to run the deployment on nodes with specific taints in your Kubernetes cluster.
services.admin.affinity {} This key allows you to set the affinity rules for the deployment of admin. This is useful when you want to control how pods are scheduled on nodes in your Kubernetes cluster.
services.admin.labels {} Custom labels to add to the admin deployment
services.admin.annotations {} Custom annotations to add to the admin deployment

Live Service Deployment

Setting Default Required Description
services.live.replicas 1 Yes Kubernetes helps you with scaling up/down the deployments. You can run 1 or more pods for each deployment. This key helps you setting up number of replicas you want to run for this deployment. It must be >=1
services.live.memoryLimit 2000Mi Every deployment in kubernetes can be set to use maximum memory they are allowed to use. This key sets the memory limit for this deployment to use.
services.live.cpuLimit 500m Every deployment in kubernetes can be set to use maximum cpu they are allowed to use. This key sets the cpu limit for this deployment to use.
services.live.memoryRequest 512Mi Every deployment in kubernetes can be set to use minimum memory they are allowed to use. This key sets the memory request for this deployment to use.
services.live.cpuRequest 100m Every deployment in kubernetes can be set to use minimum cpu they are allowed to use. This key sets the cpu request for this deployment to use.
services.live.image makeplane/live-commercial This deployment needs a preconfigured docker image to function. Docker image name is provided by the owner and must not be changed for this deployment
services.live.init_image busybox Using this key, user can provide the docker image used by the live init container, which assembles the custom S3 CA bundle. Only rendered when a custom S3 CA is configured (airgapped.enabled with an S3 CA secret). An override must be BusyBox-compatible: the init script needs /bin/sh, ls, cat, and touch. If any is missing the init container fails and live never starts
services.live.pullPolicy Always Using this key, user can set the pull policy for the deployment of live.
env.live_sentry_dsn (optional) Live service deployment comes with some of the preconfigured integration. Sentry is one among those. Here user can set the Sentry provided DSN for this integration.
env.live_sentry_environment (optional) Live service deployment comes with some of the preconfigured integration. Sentry is one among those. Here user can set the Sentry environment name (as configured in Sentry) for this integration.
env.live_sentry_traces_sample_rate (optional) Live service deployment comes with some of the preconfigured integration. Sentry is one among those. Here user can set the Sentry trace sample rate (as configured in Sentry) for this integration.
env.live_server_secret_key htbqvBJAgpm9bzvf3r4urJer0ENReatceh Live Server Secret Key
env.export_queue_name plane-exports RabbitMQ queue name for background PDF/DOCX export jobs consumed by the live-exporter service.
env.external_iframely_url "" External Iframely service URL. If provided, the local Iframely deployment will be skipped and the live service will use this external URL
services.live.assign_cluster_ip false Set it to true if you want to assign ClusterIP to the service
services.live.nodeSelector {} This key allows you to set the node selector for the deployment of live. This is useful when you want to run the deployment on specific nodes in your Kubernetes cluster.
services.live.tolerations [] This key allows you to set the tolerations for the deployment of live. This is useful when you want to run the deployment on nodes with specific taints in your Kubernetes cluster.
services.live.affinity {} This key allows you to set the affinity rules for the deployment of live. This is useful when you want to control how pods are scheduled on nodes in your Kubernetes cluster.
services.live.labels {} Custom labels to add to the live deployment
services.live.annotations {} Custom annotations to add to the live deployment

Live Exporter Deployment

Setting Default Required Description
services.live_exporter.enabled true Enable or disable the background PDF/DOCX export worker. Reuses the live image but boots in exporter mode (pure queue consumer, no HTTP port).
services.live_exporter.replicas 1 Yes Number of exporter pods. PDF render footprint is 500MB–2GB per job; scale horizontally rather than increasing concurrency per pod.
services.live_exporter.memoryLimit 2000Mi Memory limit for the exporter pod. Set higher if rendering large documents.
services.live_exporter.cpuLimit 1000m CPU limit for the exporter pod.
services.live_exporter.memoryRequest 256Mi Memory request for the exporter pod.
services.live_exporter.cpuRequest 100m CPU request for the exporter pod.
services.live_exporter.image makeplane/live-commercial Docker image for the exporter. Must match the live service image.
services.live_exporter.nodeSelector {} Node selector for the exporter pod.
services.live_exporter.tolerations [] Tolerations for the exporter pod.
services.live_exporter.affinity {} Affinity rules for the exporter pod.

Monitor Deployment

Setting Default Required Description
services.monitor.memoryLimit 1000Mi Every deployment in kubernetes can be set to use maximum memory they are allowed to use. This key sets the memory limit for this deployment to use.
services.monitor.cpuLimit 500m Every deployment in kubernetes can be set to use maximum cpu they are allowed to use. This key sets the cpu limit for this deployment to use.
services.monitor.memoryRequest 128Mi Every deployment in kubernetes can be set to use minimum memory they are allowed to use. This key sets the memory request for this deployment to use.
services.monitor.cpuRequest 100m Every deployment in kubernetes can be set to use minimum cpu they are allowed to use. This key sets the cpu request for this deployment to use.
services.monitor.image makeplane/monitor-commercial This deployment needs a preconfigured docker image to function. Docker image name is provided by the owner and must not be changed for this deployment
services.monitor.pullPolicy Always Using this key, user can set the pull policy for the deployment of monitor.
services.monitor.volumeSize 100Mi While setting up the stateful deployment, while creating the persistant volume, volume allocation size need to be provided. This key helps you set the volume allocation size. Unit of this value must be in Mi (megabyte) or Gi (gigabyte)
services.monitor.assign_cluster_ip false Set it to true if you want to assign ClusterIP to the service
services.monitor.nodeSelector {} This key allows you to set the node selector for the stateful deployment of monitor. This is useful when you want to run the deployment on specific nodes in your Kubernetes cluster.
services.monitor.tolerations [] This key allows you to set the tolerations for the stateful deployment of monitor. This is useful when you want to run the deployment on nodes with specific taints in your Kubernetes cluster.
services.monitor.affinity {} This key allows you to set the affinity rules for the stateful deployment of monitor. This is useful when you want to control how pods are scheduled on nodes in your Kubernetes cluster.
services.monitor.labels {} Custom labels to add to the monitor deployment
services.monitor.annotations {} Custom annotations to add to the monitor deployment

API Deployment

Setting Default Required Description
services.api.replicas 1 Yes Kubernetes helps you with scaling up/down the deployments. You can run 1 or more pods for each deployment. This key helps you setting up number of replicas you want to run for this deployment. It must be >=1
services.api.memoryLimit 2Gi Every deployment in kubernetes can be set to use maximum memory they are allowed to use. This key sets the memory limit for this deployment to use.
services.api.cpuLimit 1000m Every deployment in kubernetes can be set to use maximum cpu they are allowed to use. This key sets the cpu limit for this deployment to use.
services.api.memoryRequest 512Mi Every deployment in kubernetes can be set to use minimum memory they are allowed to use. This key sets the memory request for this deployment to use.
services.api.cpuRequest 200m Every deployment in kubernetes can be set to use minimum cpu they are allowed to use. This key sets the cpu request for this deployment to use.
services.api.image makeplane/backend-commercial This deployment needs a preconfigured docker image to function. Docker image name is provided by the owner and must not be changed for this deployment
services.api.pullPolicy Always Using this key, user can set the pull policy for the deployment of api.
env.sentry_dsn (optional) API service deployment comes with some of the preconfigured integration. Sentry is one among those. Here user can set the Sentry provided DSN for this integration.
env.sentry_environment (optional) API service deployment comes with some of the preconfigured integration. Sentry is one among those. Here user can set the Sentry environment name (as configured in Sentry) for this integration.
env.api_key_rate_limit 60/minute (optional) User can set the maximum number of requests the API can handle in a given time frame.
env.web_url (optional) Custom Web URL for the application. If not set, it will be auto-generated based on the license domain and SSL settings
env.webhook_allowed_ips (optional) Comma-separated list of IPs/CIDRs that webhooks are allowed to target. Leave empty to allow all.
env.webhook_allowed_hosts (optional) Comma-separated list of hostnames that webhooks are allowed to target. Leave empty to allow all.
env.gunicorn_workers 1 Number of Gunicorn worker processes for the API server. Increase for higher concurrency (e.g. 2 * CPU cores + 1).
env.gunicorn_max_requests 1000 Maximum requests a gunicorn worker handles before restart. Set to 0 to disable rotation.
env.gunicorn_max_requests_jitter 150 Random jitter added to GUNICORN_MAX_REQUESTS to stagger worker restarts across replicas. Set to 0 when rotation is disabled.
env.celery_task_publish_retry true When true, Celery retries task publishing on transient AMQP failures instead of silently dropping tasks. Prevents stuck export/import records caused by brief broker reconnect windows.
env.celery_broker_pool_limit 10 Bounds the Celery broker connection pool. Prevents stale connections from accumulating without bound; tune relative to worker concurrency.
services.api.assign_cluster_ip false Set it to true if you want to assign ClusterIP to the service
services.api.nodeSelector {} This key allows you to set the node selector for the deployment of api. This is useful when you want to run the deployment on specific nodes in your Kubernetes cluster.
services.api.tolerations [] This key allows you to set the tolerations for the deployment of api. This is useful when you want to run the deployment on nodes with specific taints in your Kubernetes cluster.
services.api.affinity {} This key allows you to set the affinity rules for the deployment of api. This is useful when you want to control how pods are scheduled on nodes in your Kubernetes cluster.
services.api.labels {} Custom labels to add to the API deployment
services.api.annotations {} Custom annotations to add to the API deployment

External API Deployment

Setting Default Required Description
services.external_api.enabled false Set it to true to deploy a dedicated API workload (same backend image and entrypoint as api) for serving external/public API traffic.
services.external_api.replicas 1 Yes Kubernetes helps you with scaling up/down the deployments. You can run 1 or more pods for each deployment. This key helps you setting up number of replicas you want to run for this deployment. It must be >=1
services.external_api.memoryLimit 2Gi Every deployment in kubernetes can be set to use maximum memory they are allowed to use. This key sets the memory limit for this deployment to use.
services.external_api.cpuLimit 1000m Every deployment in kubernetes can be set to use maximum cpu they are allowed to use. This key sets the cpu limit for this deployment to use.
services.external_api.memoryRequest 512Mi Every deployment in kubernetes can be set to use minimum memory they are allowed to use. This key sets the memory request for this deployment to use.
services.external_api.cpuRequest 200m Every deployment in kubernetes can be set to use minimum cpu they are allowed to use. This key sets the cpu request for this deployment to use.
services.external_api.assign_cluster_ip false Set it to true if you want to assign ClusterIP to the service
services.external_api.nodeSelector {} This key allows you to set the node selector for the deployment of external_api. This is useful when you want to run the deployment on specific nodes in your Kubernetes cluster.
services.external_api.tolerations [] This key allows you to set the tolerations for the deployment of external_api. This is useful when you want to run the deployment on nodes with specific taints in your Kubernetes cluster.
services.external_api.affinity {} This key allows you to set the affinity rules for the deployment of external_api. This is useful when you want to control how pods are scheduled on nodes in your Kubernetes cluster.
services.external_api.labels {} Custom labels to add to the external API deployment
services.external_api.annotations {} Custom annotations to add to the external API deployment

Silo Deployment

Setting Default Required Description
services.silo.replicas 1 Yes Kubernetes helps you with scaling up/down the deployments. You can run 1 or more pods for each deployment. This key helps you setting up number of replicas you want to run for this deployment. It must be >=1
services.silo.memoryLimit 1000Mi Every deployment in kubernetes can be set to use maximum memory they are allowed to use. This key sets the memory limit for this deployment to use.
services.silo.cpuLimit 500m Every deployment in kubernetes can be set to use maximum cpu they are allowed to use. This key sets the cpu limit for this deployment to use.
services.silo.memoryRequest 256Mi Every deployment in kubernetes can be set to use minimum memory they are allowed to use. This key sets the memory request for this deployment to use.
services.silo.cpuRequest 100m Every deployment in kubernetes can be set to use minimum cpu they are allowed to use. This key sets the cpu request for this deployment to use.
services.silo.image makeplane/silo-commercial This deployment needs a preconfigured docker image to function. Docker image name is provided by the owner and must not be changed for this deployment
services.silo.init_image busybox Using this key, user can provide the docker image used by the silo init containers, which wait for RabbitMQ to become resolvable and (when a custom S3 CA is configured) assemble the CA bundle. An override must be BusyBox-compatible: the init scripts need /bin/sh, grep, nslookup, sleep, ls, cat, and touch. If any is missing the affected init container fails and silo never starts
services.silo.pullPolicy Always Using this key, user can set the pull policy for the deployment of silo.
services.silo.assign_cluster_ip false Set it to true if you want to assign ClusterIP to the service
services.silo.nodeSelector {} This key allows you to set the node selector for the deployment of silo. This is useful when you want to run the deployment on specific nodes in your Kubernetes cluster.
services.silo.tolerations [] This key allows you to set the tolerations for the deployment of silo. This is useful when you want to run the deployment on nodes with specific taints in your Kubernetes cluster.
services.silo.affinity {} This key allows you to set the affinity rules for the deployment of silo. This is useful when you want to control how pods are scheduled on nodes in your Kubernetes cluster.
services.silo.labels {} Custom labels to add to the silo deployment
services.silo.annotations {} Custom annotations to add to the silo deployment
services.silo.connectors.slack.enabled false Slack Integration
services.silo.connectors.slack.client_id "" required if services.silo.connectors.slack.enabled is true Slack Client ID
services.silo.connectors.slack.client_secret "" required if services.silo.connectors.slack.enabled is true Slack Client Secret
services.silo.connectors.slack.base_url "" Base URL for the Slack API (SLACK_BASE_URL, e.g. https://slack.com), stored in the silo Secret; used when the Slack connector is enabled
services.silo.connectors.slack.signing_secret "" Slack Signing Secret (SLACK_SIGNING_SECRET) used to verify webhook request authenticity; stored in the silo Secret
services.silo.connectors.github.enabled false Github App Integration
services.silo.connectors.github.client_id "" required if services.silo.connectors.github.enabled is true Github Client ID
services.silo.connectors.github.client_secret "" required if services.silo.connectors.github.enabled is true Github Client Secret
services.silo.connectors.github.app_name "" required if services.silo.connectors.github.enabled is true Github App Name
services.silo.connectors.github.app_id "" required if services.silo.connectors.github.enabled is true Github App ID
services.silo.connectors.github.private_key "" required if services.silo.connectors.github.enabled is true Github Private Key
services.silo.connectors.github.webhook_secret "" GitHub Webhook Secret (GITHUB_WEBHOOK_SECRET) used to verify webhook payload signatures; stored in the silo Secret
services.silo.connectors.gitlab.enabled false Gitlab App Integration
services.silo.connectors.gitlab.client_id "" required if services.silo.connectors.gitlab.enabled is true Gitlab Client ID
services.silo.connectors.gitlab.client_secret "" required if services.silo.connectors.gitlab.enabled is true Gitlab Client Secret
services.silo.connectors.sentry.enabled false Sentry App Integration
services.silo.connectors.sentry.base_url "" required if services.silo.connectors.sentry.enabled is true Sentry Base URL
services.silo.connectors.sentry.client_id "" required if services.silo.connectors.sentry.enabled is true Sentry Client ID
services.silo.connectors.sentry.client_secret "" required if services.silo.connectors.sentry.enabled is true Sentry Client Secret
services.silo.connectors.sentry.integration_slug "" required if services.silo.connectors.sentry.enabled is true Sentry Integration Slug
services.silo.connectors.bitbucket.enabled false Bitbucket Integration
services.silo.connectors.bitbucket.client_id "" required if services.silo.connectors.bitbucket.enabled is true Bitbucket OAuth Client ID
services.silo.connectors.bitbucket.client_secret "" required if services.silo.connectors.bitbucket.enabled is true Bitbucket OAuth Client Secret
services.silo.connectors.bitbucket.webhook_secret "" Bitbucket Webhook Secret (BITBUCKET_WEBHOOK_SECRET) for verifying incoming webhook payloads
services.silo.connectors.hubspot.enabled false HubSpot Integration
services.silo.connectors.hubspot.client_id "" required if services.silo.connectors.hubspot.enabled is true HubSpot OAuth Client ID
services.silo.connectors.hubspot.client_secret "" required if services.silo.connectors.hubspot.enabled is true HubSpot OAuth Client Secret
env.silo_envs.mq_prefetch_count 10 Prefetch count for RabbitMQ
env.silo_envs.batch_size 60 Batch size for Silo
env.silo_envs.request_interval 400 Request interval for Silo
env.silo_envs.importers_queue_name celery Celery queue name used for importer jobs (IMPORTERS_QUEUE_NAME)
env.silo_envs.sentry_dsn Sentry DSN
env.silo_envs.sentry_environment Sentry Environment
env.silo_envs.sentry_traces_sample_rate Sentry Traces Sample Rate
env.silo_envs.hmac_secret_key <random-32-bit-string> HMAC Secret Key
env.silo_envs.aes_secret_key "dsOdt7YrvxsTIFJ37pOaEVvLxN8KGBCr" AES Secret Key
env.silo_envs.jira_server_issues_page_size 50 Page size used when fetching issues from Jira Server during imports
env.silo_envs.jira_server_issues_parallel_pages 1 Number of Jira Server issue pages fetched in parallel during imports
env.silo_envs.cursor_webhook_secret "TTqazTcoBajYKzIAeIKFZeTX9czAoUsG" Webhook secret for the Cursor agent integration (CURSOR_WEBHOOK_SECRET), stored in the silo Secret

Plane AI (PI) Deployment

Setting Default Required Description
services.pi.enabled false No Set to true to enable the Plane AI service and its API, worker, beat, and migrator workloads.
services.pi.replicas 1 Yes Number of replicas for the Plane AI (PI) API deployment. It must be >=1.
services.pi.memoryLimit 2Gi Memory limit for the Plane AI (PI) API deployment.
services.pi.cpuLimit 1000m CPU limit for the Plane AI (PI) API deployment.
services.pi.memoryRequest 512Mi Memory request for the Plane AI (PI) API deployment.
services.pi.cpuRequest 200m CPU request for the Plane AI (PI) API deployment.
services.pi.image makeplane/plane-pi-commercial Docker image for the Plane AI (PI) service.
services.pi.pullPolicy Always Image pull policy for the Plane AI (PI) deployment.
services.pi.assign_cluster_ip false Set it to true if you want to assign ClusterIP to the Plane AI (PI) API service.
services.pi.nodeSelector {} Node selector for the Plane AI (PI) API deployment.
services.pi.tolerations [] Tolerations for the Plane AI (PI) API deployment.
services.pi.affinity {} Affinity rules for the Plane AI (PI) API deployment.
services.pi.labels {} Custom labels to add to the Plane AI (PI) API deployment.
services.pi.annotations {} Custom annotations to add to the Plane AI (PI) API deployment.
env.pg_pi_db_name plane_pi PostgreSQL database name used by Plane AI (PI) when postgres.local_setup=true.
env.pg_pi_db_remote_url "" PostgreSQL connection URL for Plane AI (PI) when using a remote database. Required when postgres.local_setup=false and Plane AI (PI) is enabled.
env.pi_envs.internal_secret tyfvfqvBJAgpm9bzvf3r4urJer0Ehfdubk Internal secret used by Plane AI (PI) for OAuth and internal APIs.
env.pi_envs.plane_api_host "" Override for the Plane API host URL used by Plane AI (PI). Defaults to the license domain.
env.pi_envs.cors_allowed_origins "" CORS allowed origins for Plane AI (PI) API. Defaults to the license domain.
env.pi_envs.log_level DEBUG Log level for Plane AI (PI) API (e.g. DEBUG, INFO, WARNING, ERROR).
services.pi.ai_providers.openai.enabled false Enable OpenAI as a Plane AI provider.
services.pi.ai_providers.openai.base_url "" OpenAI API base URL (optional override).
services.pi.ai_providers.openai.api_key "" required if services.pi.ai_providers.openai.enabled is true OpenAI API key.
services.pi.ai_providers.claude.enabled false Enable Anthropic Claude as a Plane AI provider.
services.pi.ai_providers.claude.base_url "" Claude API base URL (optional override).
services.pi.ai_providers.claude.api_key "" required if services.pi.ai_providers.claude.enabled is true Claude API key.
services.pi.ai_providers.groq.enabled false Enable Groq as a Plane AI provider.
services.pi.ai_providers.groq.base_url "" Groq API base URL (optional override).
services.pi.ai_providers.groq.api_key "" required if services.pi.ai_providers.groq.enabled is true Groq API key.
services.pi.ai_providers.cohere.enabled false Enable Cohere as a Plane AI provider.
services.pi.ai_providers.cohere.base_url "" Cohere API base URL (optional override).
services.pi.ai_providers.cohere.api_key "" Cohere API key (optional if Cohere is disabled).
services.pi.ai_providers.custom_llm.enabled false Enable a custom LLM backend for Plane AI.
services.pi.ai_providers.custom_llm.api_key "" required if services.pi.ai_providers.custom_llm.enabled is true Custom LLM API key.
services.pi.ai_providers.custom_llm.base_url "" Custom LLM base URL.
services.pi.ai_providers.custom_llm.model_key gpt-oss-120b Model identifier key for the custom LLM.
services.pi.ai_providers.custom_llm.name GPT-OSS-120B Display name for the custom LLM.
services.pi.ai_providers.custom_llm.max_tokens 128000 Maximum tokens for the custom LLM.
services.pi.ai_providers.custom_llm.provider "" Custom LLM provider identifier.
services.pi.ai_providers.custom_llm.aws_region "" AWS region when the custom LLM is hosted on AWS.
services.pi.ai_providers.embedding_model.enabled false Enable OpenSearch embedding model integration (AWS / OpenSearch ML).
services.pi.ai_providers.embedding_model.name "" required if services.pi.ai_providers.embedding_model.enabled is true Embedding model name.
services.pi.ai_providers.embedding_model.model_id "" required if services.pi.ai_providers.embedding_model.enabled is true OpenSearch ML model ID (OPENSEARCH_ML_MODEL_ID).
services.pi.ai_providers.embedding_model.embedding_dimension 1536 required if services.pi.ai_providers.embedding_model.enabled is true OpenSearch embedding vector dimension (must match the model).
services.pi.ai_providers.embedding_model.aws_access_key "" required if services.pi.ai_providers.embedding_model.enabled is true AWS access key ID for the embedding model (BR_AWS_ACCESS_KEY_ID).
services.pi.ai_providers.embedding_model.aws_secret_access_key "" required if services.pi.ai_providers.embedding_model.enabled is true AWS secret access key for the embedding model (also BR_AWS_SECRET_ACCESS_KEY in external secrets).
services.pi.ai_providers.embedding_model.aws_region us-east-1 AWS region for the embedding model (BR_AWS_REGION).
services.pi.ai_providers.embedding_model.aws_session_token "" AWS session token when using temporary credentials (BR_AWS_SESSION_TOKEN).

Plane AI (PI) Worker Deployment

Setting Default Required Description
services.pi_worker.replicas 1 Yes Kubernetes helps you with scaling up/down the deployments. You can run 1 or more pods for the Plane AI (PI) worker. This key helps you set the number of replicas. It must be >=1.
services.pi_worker.memoryLimit 1000Mi Every deployment in kubernetes can be set to use maximum memory they are allowed to use. This key sets the memory limit for the Plane AI (PI) worker deployment to use.
services.pi_worker.cpuLimit 500m Every deployment in kubernetes can be set to use maximum cpu they are allowed to use. This key sets the cpu limit for the Plane AI (PI) worker deployment to use.
services.pi_worker.memoryRequest 256Mi Every deployment in kubernetes can be set to use minimum memory they are allowed to use. This key sets the memory request for the Plane AI (PI) worker deployment to use.
services.pi_worker.cpuRequest 100m Every deployment in kubernetes can be set to use minimum cpu they are allowed to use. This key sets the cpu request for the Plane AI (PI) worker deployment to use.
services.pi_worker.nodeSelector {} This key allows you to set the node selector for the deployment of pi_worker. This is useful when you want to run the deployment on specific nodes in your Kubernetes cluster.
services.pi_worker.tolerations [] This key allows you to set the tolerations for the deployment of pi_worker. This is useful when you want to run the deployment on nodes with specific taints in your Kubernetes cluster.
services.pi_worker.affinity {} This key allows you to set the affinity rules for the deployment of pi_worker. This is useful when you want to control how pods are scheduled on nodes in your Kubernetes cluster.
services.pi_worker.labels {} Custom labels to add to the Plane AI (PI) worker deployment
services.pi_worker.annotations {} Custom annotations to add to the Plane AI (PI) worker deployment

Plane AI (PI) Beat-Worker Deployment

Setting Default Required Description
services.pi_beat_worker.replicas 1 Yes Kubernetes helps you with scaling up/down the deployments. You can run 1 or more pods for the Plane AI (PI) beat-worker. This key helps you set the number of replicas. It must be >=1.
services.pi_beat_worker.memoryLimit 1000Mi Every deployment in kubernetes can be set to use maximum memory they are allowed to use. This key sets the memory limit for the Plane AI (PI) beat-worker deployment to use.
services.pi_beat_worker.cpuLimit 500m Every deployment in kubernetes can be set to use maximum cpu they are allowed to use. This key sets the cpu limit for the Plane AI (PI) beat-worker deployment to use.
services.pi_beat_worker.memoryRequest 256Mi Every deployment in kubernetes can be set to use minimum memory they are allowed to use. This key sets the memory request for the Plane AI (PI) beat-worker deployment to use.
services.pi_beat_worker.cpuRequest 100m Every deployment in kubernetes can be set to use minimum cpu they are allowed to use. This key sets the cpu request for the Plane AI (PI) beat-worker deployment to use.
services.pi_beat_worker.nodeSelector {} This key allows you to set the node selector for the deployment of pi_beat_worker. This is useful when you want to run the deployment on specific nodes in your Kubernetes cluster.
services.pi_beat_worker.tolerations [] This key allows you to set the tolerations for the deployment of pi_beat_worker. This is useful when you want to run the deployment on nodes with specific taints in your Kubernetes cluster.
services.pi_beat_worker.affinity {} This key allows you to set the affinity rules for the deployment of pi_beat_worker. This is useful when you want to control how pods are scheduled on nodes in your Kubernetes cluster.
services.pi_beat_worker.labels {} Custom labels to add to the Plane AI (PI) beat-worker deployment
services.pi_beat_worker.annotations {} Custom annotations to add to the Plane AI (PI) beat-worker deployment

Worker Deployment

Setting Default Required Description
services.worker.replicas 1 Yes Kubernetes helps you with scaling up/down the deployments. You can run 1 or more pods for each deployment. This key helps you setting up number of replicas you want to run for this deployment. It must be >=1
services.worker.memoryLimit 2Gi Every deployment in kubernetes can be set to use maximum memory they are allowed to use. This key sets the memory limit for this deployment to use.
services.worker.cpuLimit 1000m Every deployment in kubernetes can be set to use maximum cpu they are allowed to use. This key sets the cpu limit for this deployment to use.
services.worker.memoryRequest 1Gi Every deployment in kubernetes can be set to use minimum memory they are allowed to use. This key sets the memory request for this deployment to use.
services.worker.cpuRequest 200m Every deployment in kubernetes can be set to use minimum cpu they are allowed to use. This key sets the cpu request for this deployment to use.
services.worker.nodeSelector {} This key allows you to set the node selector for the deployment of worker. This is useful when you want to run the deployment on specific nodes in your Kubernetes cluster.
services.worker.tolerations [] This key allows you to set the tolerations for the deployment of worker. This is useful when you want to run the deployment on nodes with specific taints in your Kubernetes cluster.
services.worker.affinity {} This key allows you to set the affinity rules for the deployment of worker. This is useful when you want to control how pods are scheduled on nodes in your Kubernetes cluster.
services.worker.labels {} Custom labels to add to the worker deployment
services.worker.annotations {} Custom annotations to add to the worker deployment

Importer Worker Deployment

Setting Default Required Description
services.worker_importers.enabled false Set it to true to deploy a dedicated celery worker for the celery.importer queue, so imports run on their own worker instead of the default one.
services.worker_importers.replicas 1 Yes Kubernetes helps you with scaling up/down the deployments. You can run 1 or more pods for each deployment. This key helps you setting up number of replicas you want to run for this deployment. It must be >=1
services.worker_importers.memoryLimit 2Gi Every deployment in kubernetes can be set to use maximum memory they are allowed to use. This key sets the memory limit for this deployment to use.
services.worker_importers.cpuLimit 1000m Every deployment in kubernetes can be set to use maximum cpu they are allowed to use. This key sets the cpu limit for this deployment to use.
services.worker_importers.memoryRequest 512Mi Every deployment in kubernetes can be set to use minimum memory they are allowed to use. This key sets the memory request for this deployment to use.
services.worker_importers.cpuRequest 200m Every deployment in kubernetes can be set to use minimum cpu they are allowed to use. This key sets the cpu request for this deployment to use.
services.worker_importers.nodeSelector {} This key allows you to set the node selector for the deployment of worker_importers. This is useful when you want to run the deployment on specific nodes in your Kubernetes cluster.
services.worker_importers.tolerations [] This key allows you to set the tolerations for the deployment of worker_importers. This is useful when you want to run the deployment on nodes with specific taints in your Kubernetes cluster.
services.worker_importers.affinity {} This key allows you to set the affinity rules for the deployment of worker_importers. This is useful when you want to control how pods are scheduled on nodes in your Kubernetes cluster.
services.worker_importers.labels {} Custom labels to add to the importer worker deployment
services.worker_importers.annotations {} Custom annotations to add to the importer worker deployment

Beat-Worker deployment

Setting Default Required Description
services.beatworker.replicas 1 Yes Kubernetes helps you with scaling up/down the deployments. You can run 1 or more pods for each deployment. This key helps you setting up number of replicas you want to run for this deployment. It must be >=1
services.beatworker.memoryLimit 2Gi Every deployment in kubernetes can be set to use maximum memory they are allowed to use. This key sets the memory limit for this deployment to use.
services.beatworker.cpuLimit 500m Every deployment in kubernetes can be set to use maximum cpu they are allowed to use. This key sets the cpu limit for this deployment to use.
services.beatworker.memoryRequest 512Mi Every deployment in kubernetes can be set to use minimum memory they are allowed to use. This key sets the memory request for this deployment to use.
services.beatworker.cpuRequest 100m Every deployment in kubernetes can be set to use minimum cpu they are allowed to use. This key sets the cpu request for this deployment to use.
services.beatworker.nodeSelector {} This key allows you to set the node selector for the deployment of beatworker. This is useful when you want to run the deployment on specific nodes in your Kubernetes cluster.
services.beatworker.tolerations [] This key allows you to set the tolerations for the deployment of beatworker. This is useful when you want to run the deployment on nodes with specific taints in your Kubernetes cluster.
services.beatworker.affinity {} This key allows you to set the affinity rules for the deployment of beatworker. This is useful when you want to control how pods are scheduled on nodes in your Kubernetes cluster.
services.beatworker.labels {} Custom labels to add to the beat-worker deployment
services.beatworker.annotations {} Custom annotations to add to the beat-worker deployment

Email Service Deployment

Setting Default Required Description
services.email_service.enabled false Set to true to enable the email service deployment
services.email_service.replicas 1 Number of replicas for the email service deployment
services.email_service.memoryLimit 1000Mi Memory limit for the email service deployment
services.email_service.cpuLimit 500m CPU limit for the email service deployment
services.email_service.memoryRequest 128Mi Memory request for the email service deployment
services.email_service.cpuRequest 100m CPU request for the email service deployment
services.email_service.image makeplane/email-commercial Docker image for the email service deployment
services.email_service.pullPolicy Always Image pull policy for the email service deployment
services.email_service.nodeSelector {} This key allows you to set the node selector for the deployment of email_service. This is useful when you want to run the deployment on specific nodes in your Kubernetes cluster.
services.email_service.tolerations [] This key allows you to set the tolerations for the deployment of email_service. This is useful when you want to run the deployment on nodes with specific taints in your Kubernetes cluster.
services.email_service.affinity {} This key allows you to set the affinity rules for the deployment of email_service. This is useful when you want to control how pods are scheduled on nodes in your Kubernetes cluster.
services.email_service.labels {} Custom labels to add to the email service deployment
services.email_service.annotations {} Custom annotations to add to the email service deployment
env.email_service_envs.smtp_domain Yes The SMTP Domain to be used with email service
env.email_service_envs.max_attachment_size 10485760 (10MB) Maximum email attachment size in bytes

Note: When the email service is enabled, the cert-issuer will be automatically created to handle TLS certificates for the email service.

Outbox Poller Service Deployment

Setting Default Required Description
services.outbox_poller.enabled false Set to true to enable the outbox poller service deployment
services.outbox_poller.replicas 1 Number of replicas for the outbox poller service deployment
services.outbox_poller.memoryLimit 1000Mi Memory limit for the outbox poller service deployment
services.outbox_poller.cpuLimit 500m CPU limit for the outbox poller service deployment
services.outbox_poller.memoryRequest 256Mi Memory request for the outbox poller service deployment
services.outbox_poller.cpuRequest 100m CPU request for the outbox poller service deployment
services.outbox_poller.pullPolicy Always Image pull policy for the outbox poller service deployment
services.outbox_poller.assign_cluster_ip false Set it to true if you want to assign ClusterIP to the service
services.outbox_poller.nodeSelector {} This key allows you to set the node selector for the deployment of outbox_poller. This is useful when you want to run the deployment on specific nodes in your Kubernetes cluster.
services.outbox_poller.tolerations [] This key allows you to set the tolerations for the deployment of outbox_poller. This is useful when you want to run the deployment on nodes with specific taints in your Kubernetes cluster.
services.outbox_poller.affinity {} This key allows you to set the affinity rules for the deployment of outbox_poller. This is useful when you want to control how pods are scheduled on nodes in your Kubernetes cluster.
services.outbox_poller.labels {} Custom labels to add to the outbox poller deployment
services.outbox_poller.annotations {} Custom annotations to add to the outbox poller deployment
env.outbox_poller_envs.memory_limit_mb 400 Memory limit in MB for the outbox poller
env.outbox_poller_envs.interval_min 0.25 Minimum interval in minutes for polling
env.outbox_poller_envs.interval_max 2 Maximum interval in minutes for polling
env.outbox_poller_envs.batch_size 250 Batch size for processing outbox messages
env.outbox_poller_envs.memory_check_interval 30 Memory check interval in seconds
env.outbox_poller_envs.pool.size 4 Pool size for database connections
env.outbox_poller_envs.pool.min_size 2 Minimum pool size for database connections
env.outbox_poller_envs.pool.max_size 10 Maximum pool size for database connections
env.outbox_poller_envs.pool.timeout 30.0 Pool timeout in seconds
env.outbox_poller_envs.pool.max_idle 300.0 Maximum idle time for connections in seconds
env.outbox_poller_envs.pool.max_lifetime 3600 Maximum lifetime for connections in seconds
env.outbox_poller_envs.pool.reconnect_timeout 5.0 Reconnect timeout in seconds
env.outbox_poller_envs.pool.health_check_interval 60 Health check interval in seconds

Automation Consumer Deployment

Setting Default Required Description
services.automation_consumer.enabled false Set to true to enable the automation consumer service deployment
services.automation_consumer.replicas 1 Number of replicas for the automation consumer service deployment
services.automation_consumer.memoryLimit 1000Mi Memory limit for the automation consumer service deployment
services.automation_consumer.cpuLimit 500m CPU limit for the automation consumer service deployment
services.automation_consumer.memoryRequest 256Mi Memory request for the automation consumer service deployment
services.automation_consumer.cpuRequest 100m CPU request for the automation consumer service deployment
services.automation_consumer.assign_cluster_ip false Set it to true if you want to assign ClusterIP to the service
services.automation_consumer.nodeSelector {} This key allows you to set the node selector for the deployment of automation_consumer. This is useful when you want to run the deployment on specific nodes in your Kubernetes cluster.
services.automation_consumer.tolerations [] This key allows you to set the tolerations for the deployment of automation_consumer. This is useful when you want to run the deployment on nodes with specific taints in your Kubernetes cluster.
services.automation_consumer.affinity {} This key allows you to set the affinity rules for the deployment of automation_consumer. This is useful when you want to control how pods are scheduled on nodes in your Kubernetes cluster.
services.automation_consumer.labels {} Custom labels to add to the automation consumer deployment
services.automation_consumer.annotations {} Custom annotations to add to the automation consumer deployment
env.automation_consumer_envs.event_stream_queue_name "plane.event_stream.automations" Event stream queue name for automations
env.automation_consumer_envs.event_stream_prefetch 10 Event stream prefetch count
env.automation_consumer_envs.exchange_name "plane.event_stream" Exchange name for event stream
env.automation_consumer_envs.event_types "issue" Event types to process

Webhook Consumer Deployment

Setting Default Required Description
services.webhook_consumer.enabled false Set to true to enable the webhook consumer service deployment
services.webhook_consumer.replicas 1 Number of replicas for the webhook consumer service deployment
services.webhook_consumer.memoryLimit 1000Mi Memory limit for the webhook consumer service deployment
services.webhook_consumer.cpuLimit 500m CPU limit for the webhook consumer service deployment
services.webhook_consumer.memoryRequest 256Mi Memory request for the webhook consumer service deployment
services.webhook_consumer.cpuRequest 100m CPU request for the webhook consumer service deployment
services.webhook_consumer.assign_cluster_ip false Set it to true if you want to assign ClusterIP to the service
services.webhook_consumer.nodeSelector {} This key allows you to set the node selector for the deployment of webhook_consumer. This is useful when you want to run the deployment on specific nodes in your Kubernetes cluster.
services.webhook_consumer.tolerations [] This key allows you to set the tolerations for the deployment of webhook_consumer. This is useful when you want to run the deployment on nodes with specific taints in your Kubernetes cluster.
services.webhook_consumer.affinity {} This key allows you to set the affinity rules for the deployment of webhook_consumer. This is useful when you want to control how pods are scheduled on nodes in your Kubernetes cluster.
services.webhook_consumer.labels {} Custom labels to add to the webhook consumer deployment
services.webhook_consumer.annotations {} Custom annotations to add to the webhook consumer deployment
env.webhook_consumer_envs.queue_name "plane.webhook" RabbitMQ queue name the webhook consumer reads from
env.webhook_consumer_envs.prefetch_count 10 Prefetch count for the webhook consumer

Agent Consumer Deployment

Setting Default Required Description
services.agent_consumer.enabled false Set to true to enable the agent consumer service deployment
services.agent_consumer.replicas 1 Number of replicas for the agent consumer service deployment
services.agent_consumer.memoryLimit 1000Mi Memory limit for the agent consumer service deployment
services.agent_consumer.cpuLimit 500m CPU limit for the agent consumer service deployment
services.agent_consumer.memoryRequest 256Mi Memory request for the agent consumer service deployment
services.agent_consumer.cpuRequest 100m CPU request for the agent consumer service deployment
services.agent_consumer.assign_cluster_ip false Set it to true if you want to assign ClusterIP to the service
services.agent_consumer.nodeSelector {} This key allows you to set the node selector for the deployment of agent_consumer. This is useful when you want to run the deployment on specific nodes in your Kubernetes cluster.
services.agent_consumer.tolerations [] This key allows you to set the tolerations for the deployment of agent_consumer. This is useful when you want to run the deployment on nodes with specific taints in your Kubernetes cluster.
services.agent_consumer.affinity {} This key allows you to set the affinity rules for the deployment of agent_consumer. This is useful when you want to control how pods are scheduled on nodes in your Kubernetes cluster.
services.agent_consumer.labels {} Custom labels to add to the agent consumer deployment
services.agent_consumer.annotations {} Custom annotations to add to the agent consumer deployment
env.agent_consumer_envs.queue_name "plane.agent" RabbitMQ queue name the agent consumer reads from
env.agent_consumer_envs.prefetch_count 10 Prefetch count for the agent consumer

Iframely Deployment

Setting Default Required Description
services.iframely.enabled false Set to true to enable the Iframely service deployment
services.iframely.replicas 1 Number of replicas for the Iframely service deployment
services.iframely.memoryLimit 1000Mi Memory limit for the Iframely service deployment
services.iframely.cpuLimit 1000m CPU limit for the Iframely service deployment
services.iframely.memoryRequest 256Mi Memory request for the Iframely service deployment
services.iframely.cpuRequest 100m CPU request for the Iframely service deployment
services.iframely.image makeplane/iframely:v1.2.0 Docker image for the Iframely service deployment
services.iframely.pullPolicy Always Image pull policy for the Iframely service deployment
services.iframely.assign_cluster_ip false Set it to true if you want to assign ClusterIP to the service
services.iframely.nodeSelector {} This key allows you to set the node selector for the deployment of iframely. This is useful when you want to run the deployment on specific nodes in your Kubernetes cluster.
services.iframely.tolerations [] This key allows you to set the tolerations for the deployment of iframely. This is useful when you want to run the deployment on nodes with specific taints in your Kubernetes cluster.
services.iframely.affinity {} This key allows you to set the affinity rules for the deployment of iframely. This is useful when you want to control how pods are scheduled on nodes in your Kubernetes cluster.
services.iframely.labels {} Custom labels to add to the iframely deployment
services.iframely.annotations {} Custom annotations to add to the iframely deployment

Ingress and SSL Setup

Setting Default Required Description
ingress.enabled true Ingress setup in kubernetes is a common practice to expose application to the intended audience. Set it to false if you are using external ingress providers like Cloudflare
ingress.minioHost Based on above configuration, if you want to expose the minio web console to set of users, use this key to set the host mapping or leave it as EMPTY to not expose interface.
ingress.rabbitmqHost Based on above configuration, if you want to expose the rabbitmq web console to set of users, use this key to set the host mapping or leave it as EMPTY to not expose interface.
ingress.controller Selects the ingress resource kind. Supported: traefik renders a Traefik IngressRoute; openshift renders one route.openshift.io/v1 Route per path; nginx renders a standard Ingress using ingressClass verbatim. Required when your class is not exactly nginx, openshift or traefik* — left empty, any other class renders no ingress at all.
ingress.ingressClass traefik Yes Free-form class name written to the standard Ingress spec.ingressClassName (eg. nginx, traefik, nginx-new, etc). While controller is empty it also selects the template, and only nginx, openshift and traefik* are recognised. Unused by the Traefik IngressRoute and by OpenShift Routes.
ingress.ingress_annotations { "nginx.ingress.kubernetes.io/proxy-body-size": "5m" } Ingress controllers comes with various configuration options which can be passed as annotations. Setting this value lets you change the default value to user required.
ingress.traefik.entryPoints [] Traefik entrypoints the IngressRoute binds to. Leave empty to derive them from your ssl.* settings (websecure when TLS is configured, otherwise web). Set explicitly only if your Traefik renamed the default entrypoints, e.g. ['websecure','web']. Ignored unless the controller resolves to traefik
ingress.traefik.maxRequestBodyBytes 20971520 Max request body size in bytes for Traefik's buffering middleware (upload size limit). Ignored unless the controller resolves to traefik
ssl.createIssuer false Kubernets cluster setup supports creating issuer type resource. After deployment, this is step towards creating secure access to the ingress url. Issuer is required for you generate SSL certifiate. Kubernetes can be configured to use any of the certificate authority to generate SSL (depending on CertManager configuration). Set it to true to create the issuer. Applicable only when ingress.enabled=true
ssl.issuer http CertManager configuration allows user to create issuers using http or any of the other DNS Providers like cloudflare, digitalocean, etc. As of now Plane supports http, cloudflare, digitalocean
ssl.token To create issuers using DNS challenge, set the issuer api token of dns provider like cloudflareordigitalocean`(not required for http)
ssl.server https://acme-v02.api.letsencrypt.org/directory Issuer creation configuration need the certificate generation authority server url. Default URL is the Let's Encrypt server
ssl.email plane@example.com Certificate generation authority needs a valid email id before generating certificate. Required when ssl.createIssuer=true
ssl.generateCerts false After creating the issuers, user can still not create the certificate untill sure of configuration. Setting this to true will try to generate SSL certificate and associate with ingress. Applicable only when ingress.enabled=true and ssl.createIssuer=true
ssl.tls_secret_name If you have a custom TLS secret name, set this to the name of the secret. Applicable only when ingress.enabled=true and ssl.createIssuer=false
ssl.externalTermination false Set to true when TLS is terminated in front of Plane and this chart manages no certificate (cloud load balancer, Cloudflare, service mesh, or a Traefik entrypoint carrying its own cert). All app URLs are rendered https://; no tls: block is emitted and the Traefik entrypoint is unchanged (stays web unless you also set ingress.traefik.entryPoints: ['websecure'] — see Option 4b). Leave false if you set ssl.tls_secret_name or ssl.generateCerts. See TLS options

Common Environment Settings

Setting Default Required Description
env.storageClass <k8s-default-storage-class> Creating the persitant volumes for the stateful deployments needs the storageClass name. Set the correct value as per your kubernetes cluster configuration.
env.secret_key 60gp0byfz2dvffa45cxl20p1scy9xbpf6d8c5y0geejgkyp1b5 Yes This must a random string which is used for hashing/encrypting the sensitive data within the application. Once set, changing this might impact the already hashed/encrypted data

Extra Environment Variables

Setting Default Required Description
extraEnv [] No Global extra environment variables that will be applied to all workloads. This allows you to add custom environment variables to all deployments (web, api, worker, etc.). Useful for proxy settings, custom configurations, or any environment-specific variables. Some example variables are HTTP_PROXY, HTTPS_PROXY, NO_PROXY.

Observability (OpenTelemetry)

Opt-in OpenTelemetry (traces, logs and metrics) for the backend services. Nothing is injected unless observability.otel.enabled=true.

When enabled, the chart renders a shared <release>-otel-vars ConfigMap and mounts it via envFrom into api, external-api, worker, worker-importers, beat-worker, automation-consumer, agent-consumer, webhook-consumer, outbox-poller, silo, live, live-exporter, space, pi-api, pi-beat and pi-worker. Each workload also gets an inline OTEL_SERVICE_NAME so it reports its own service.name. web and admin are deliberately not wired — their only telemetry is browser tracing, which the API serves to browsers from its instance config via the frontend.* keys below.

observability.otel.headers usually carries a collector ingestion credential, so it is rendered into a <release>-otel-secrets Secret rather than the ConfigMap. Set external_secrets.otel_env_existingSecret to supply OTEL_EXPORTER_OTLP_HEADERS from a Secret you manage yourself (External Secrets Operator, Vault, sealed-secrets, ...).

Setting Default Required Description
observability.otel.enabled false Master switch. When false no OTel ConfigMap, Secret or env var is rendered at all.
observability.otel.endpoint '' Yes OTLP collector endpoint (required when enabled — the services skip OTel bootstrap without it). An https:// endpoint uses secure gRPC.
observability.otel.protocol grpc OTLP transport: grpc or http/protobuf.
observability.otel.headers '' Extra OTLP exporter headers as k1=v1,k2=v2 (e.g. a collector ingestion key). Rendered into the <release>-otel-secrets Secret.
observability.otel.environment '' Deployment environment tag (e.g. prod, staging). Emitted by every service as the deployment.environment.name resource attribute, so cross-service environment filtering lines up.
observability.otel.resourceAttributes '' Additional OTel resource attributes as k1=v1,k2=v2.
observability.otel.debugConsole false Also print spans to stdout. Debug only.
observability.otel.sampler always_on Trace sampler. always_on exports every span the service sees and ignores an upstream traceparent's sampling decision — use it for test/debug so browser-initiated POST traces aren't dropped. For production prefer parentbased_traceidratio with a ratio.
observability.otel.samplerArg '1.0' Sampling ratio (0.0–1.0) for the ratio-based samplers. Ignored by always_on.
observability.otel.frontend.enabled false Browser/client tracing for web, admin and space. Read only by the API, which serves it to browsers over its public instance endpoint. Takes effect only when frontend.endpoint is also set.
observability.otel.frontend.endpoint '' Public OTLP/HTTP endpoint the browser posts to. Must be internet-reachable and CORS-enabled for the Plane web origin; the client appends /v1/traces.
observability.otel.frontend.headers x-otlp-browser=1 Must be non-empty cross-origin: a header forces the browser exporter onto XHR instead of navigator.sendBeacon, which sends credentials and is rejected by CORS against a wildcard Access-Control-Allow-Origin. The value is arbitrary and public.

External Secrets Config

To configure the external secrets for your application, you need to define specific environment variables for each secret category. Below is a list of the required secrets and their respective environment variables.

Secret Name Env Var Name Required Description Example Value
rabbitmq_existingSecret RABBITMQ_DEFAULT_USER Required if rabbitmq.local_setup=true The default RabbitMQ user plane
RABBITMQ_DEFAULT_PASS Required if rabbitmq.local_setup=true The default RabbitMQ password plane
pgdb_existingSecret POSTGRES_PASSWORD Required if postgres.local_setup=true Password for PostgreSQL database plane
POSTGRES_DB Required if postgres.local_setup=true Name of the PostgreSQL database plane
POSTGRES_USER Required if postgres.local_setup=true PostgreSQL user plane
opensearch_existingSecret OPENSEARCH_ENABLED Yes Flag to enable OpenSearch 1 (enabled) or 0 (disabled)
OPENSEARCH_URL Required if OpenSearch is enabled OpenSearch connection URL k8s service example: http://plane-opensearch.plane-ns.svc.cluster.local:9200

external service example: https://your-opensearch-host:9200
OPENSEARCH_USERNAME Required if OpenSearch is enabled Username for OpenSearch local setup: plane

remote setup: your_remote_username
OPENSEARCH_PASSWORD Required if OpenSearch is enabled Password for OpenSearch local setup: Secure@Pass#123!%^&*

remote setup: your_remote_password
OPENSEARCH_INITIAL_ADMIN_PASSWORD Required if opensearch.local_setup=true Initial admin password for local OpenSearch Secure@Pass#123!%^&*
OPENSEARCH_INDEX_PREFIX Optional Prefix for OpenSearch indices plane_
OPENSEARCH_EMBEDDING_DIMENSION Optional Embedding vector dimension for OpenSearch 1536
doc_store_existingSecret USE_MINIO Yes Flag to enable MinIO as the storage backend 1
MINIO_ROOT_USER Yes MinIO root user admin
MINIO_ROOT_PASSWORD Yes MinIO root password password
AWS_ACCESS_KEY_ID Yes AWS Access Key ID your_aws_key
AWS_SECRET_ACCESS_KEY Yes AWS Secret Access Key your_aws_secret
AWS_S3_BUCKET_NAME Yes AWS S3 Bucket Name your_bucket_name
AWS_S3_ENDPOINT_URL Yes Endpoint URL for AWS S3 or MinIO http://plane-minio.plane-ns.svc.cluster.local:9000
AWS_REGION Optional AWS region where your S3 bucket is located your_aws_region
FILE_SIZE_LIMIT Yes Limit for file uploads in your system 5MB
app_env_existingSecret SECRET_KEY Yes Random secret key 60gp0byfz2dvffa45cxl20p1scy9xbpf6d8c5y0geejgkyp1b5
REDIS_URL Yes Redis URL redis://plane-redis.plane-ns.svc.cluster.local:6379/
DATABASE_URL Yes PostgreSQL connection URL k8s service example: postgresql://plane:plane@plane-pgdb.plane-ns.svc.cluster.local:5432/plane

external service example: postgresql://username:password@your-db-host:5432/plane
AMQP_URL Yes RabbitMQ connection URL k8s service example: amqp://plane:plane@plane-rabbitmq.plane-ns.svc.cluster.local:5672/

external service example: amqp://username:password@your-rabbitmq-host:5672/
live_env_existingSecret REDIS_URL Yes Redis URL redis://plane-redis.plane-ns.svc.cluster.local:6379/
AMQP_URL Yes RabbitMQ connection URL k8s service example: amqp://plane:plane@plane-rabbitmq.plane-ns.svc.cluster.local:5672/

external service example: amqp://username:password@your-rabbitmq-host:5672/
LIVE_SERVER_SECRET_KEY Yes Live server secret key htbqvBJAgpm9bzvf3r4urJer0ENReatceh
silo_env_existingSecret SILO_HMAC_SECRET_KEY Yes Silo HMAC secret Key <random-32-bit-string>
REDIS_URL Yes Redis URL redis://plane-redis.plane-ns.svc.cluster.local:6379/
DATABASE_URL Yes PostgreSQL connection URL k8s service example: postgresql://plane:plane@plane-pgdb.plane-ns.svc.cluster.local:5432/plane

external service example: postgresql://username:password@your-db-host:5432/plane
AMQP_URL Yes RabbitMQ connection URL k8s service example: amqp://plane:plane@plane-rabbitmq.plane-ns.svc.cluster.local:5672/

external service example: amqp://username:password@your-rabbitmq-host:5672/
GITHUB_APP_NAME required if services.silo.connectors.github.enabled is true GitHub app name your_github_app_name
GITHUB_APP_ID required if services.silo.connectors.github.enabled is true GitHub app ID your_github_app_id
GITHUB_CLIENT_ID required if services.silo.connectors.github.enabled is true GitHub client ID your_github_client_id
GITHUB_CLIENT_SECRET required if services.silo.connectors.github.enabled is true GitHub client secret key your_github_client_secret_key
GITHUB_PRIVATE_KEY required if services.silo.connectors.github.enabled is true GitHub private key your_github_private_key
SLACK_CLIENT_ID required if services.silo.connectors.slack.enabled is true Slack client ID your_slack_client_id
SLACK_CLIENT_SECRET required if services.silo.connectors.slack.enabled is true Slack client secret key your_slack_client_secret_key
SLACK_BASE_URL required if services.silo.connectors.slack.enabled is true Base URL for the Slack API https://slack.com (or your own value)
GITLAB_CLIENT_ID required if services.silo.connectors.gitlab.enabled is true GitLab client ID your_gitlab_client_id
GITLAB_CLIENT_SECRET required if services.silo.connectors.gitlab.enabled is true GitLab client secret key your_gitlab_client_secret_key
SENTRY_BASE_URL required if services.silo.connectors.sentry.enabled is true Sentry base URL your_sentry_base_url
SENTRY_CLIENT_ID required if services.silo.connectors.sentry.enabled is true Sentry client ID your_sentry_client_id
SENTRY_CLIENT_SECRET required if services.silo.connectors.sentry.enabled is true Sentry client secret key your_sentry_client_secret_key
SENTRY_INTEGRATION_SLUG required if services.silo.connectors.sentry.enabled is true Sentry integration slug your_sentry_integration_slug
CURSOR_WEBHOOK_SECRET Yes Webhook secret for the Cursor agent integration TTqazTcoBajYKzIAeIKFZeTX9czAoUsG (or your own value)
pi_api_env_existingSecret PLANE_PI_DATABASE_URL Yes (if services.pi.enabled=true) PostgreSQL connection URL for Plane AI (PI) database k8s service example: postgresql://plane:plane@plane-pgdb.plane-ns.svc.cluster.local/plane_pi

external: postgresql://username:password@your-db-host:5432/plane_pi
AMQP_URL Yes (if services.pi.enabled=true) RabbitMQ connection URL k8s service example: amqp://plane:plane@plane-rabbitmq.plane-ns.svc.cluster.local:5672/

external: amqp://username:password@your-rabbitmq-host:5672/
CELERY_BROKER_URL Yes (if services.pi.enabled=true) Redis URL used as the Celery broker for Plane AI (PI) redis://plane-redis.plane-ns.svc.cluster.local:6379/
AES_SECRET_KEY Yes (if services.pi.enabled=true) AES secret key for Plane AI (PI) dsOdt7YrvxsTIFJ37pOaEVvLxN8KGBCr (or your own value)
PI_INTERNAL_SECRET Yes (if services.pi.enabled=true) Internal secret used by Plane AI (PI) for OAuth and internal APIs tyfvfqvBJAgpm9bzvf3r4urJer0Ehfdubk (or your own value)
LIVE_SERVER_SECRET_KEY Yes (if services.pi.enabled=true) Live server secret key. Must match the value used for the live service (live_env_existingSecret / app_env_existingSecret) htbqvBJAgpm9bzvf3r4urJer0ENReatceh (or your own value)
OPENAI_API_KEY required if services.pi.ai_providers.openai.enabled is true OpenAI API key your_openai_api_key
CLAUDE_API_KEY required if services.pi.ai_providers.claude.enabled is true Claude API key your_claude_api_key
GROQ_API_KEY required if services.pi.ai_providers.groq.enabled is true Groq API key your_groq_api_key
COHERE_API_KEY Optional (empty if not using Cohere) Cohere API key your_cohere_api_key
CUSTOM_LLM_API_KEY required if services.pi.ai_providers.custom_llm.enabled is true Custom LLM API key your_custom_llm_api_key
BR_AWS_SECRET_ACCESS_KEY required if services.pi.ai_providers.embedding_model.enabled is true AWS secret for embedding model your_aws_secret_access_key
BR_AWS_SESSION_TOKEN required if embedding model uses temporary credentials AWS session token for embedding model your_aws_session_token
otel_env_existingSecret OTEL_EXPORTER_OTLP_HEADERS Optional (only if observability.otel.enabled=true) OTLP exporter headers, e.g. a collector ingestion key. Leave otel_env_existingSecret blank to let the chart create this Secret from observability.otel.headers. x-api-key=your_collector_key

Custom Ingress Routes

If you are planning to use 3rd party ingress providers, here is the available route configuration

Host Path Service Required
plane.example.com / http://plane-app-web.plane:3000 Yes
plane.example.com /spaces/* http://plane-app-space.plane:3000 Yes
plane.example.com /god-mode/* http://plane-app-admin.plane:3000 Yes
plane.example.com /live/* http://plane-app-live.plane:3000 Yes
plane.example.com /silo/* http://plane-app-silo.plane:3000 Yes (if services.silo.enabled=true )
plane.example.com /pi/* http://plane-app-pi-api.plane:8000 Yes (if services.pi.enabled=true)
plane.example.com /api/* http://plane-app-api.plane:8000 Yes
plane.example.com /auth/* http://plane-app-api.plane:8000 Yes
plane.example.com /graphql/* http://plane-app-api.plane:8000 Yes
plane.example.com /marketplace/* http://plane-app-api.plane:8000 Yes
plane.example.com /uploads/* http://plane-app-minio.plane:9000 Yes (Only if using local setup)
plane-minio.example.com / http://plane-app-minio.plane:9090 (Optional) if using local setup, this will enable minio console access
plane-mq.example.com / http://plane-app-rabbitmq.plane:15672 (Optional) if using local setup, this will enable management console access