From 4dfd37a96ac7d82c01ad8bd6c30d4f1b2f67f921 Mon Sep 17 00:00:00 2001 From: akshat5302 Date: Mon, 3 Aug 2026 16:07:14 +0530 Subject: [PATCH 1/5] [INFRA-473] feat(plane-enterprise): add live-exporter service and EXPORT_QUEUE_NAME env MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add live-exporter Deployment (same image as live, LIVE_MODE=exporter, no HTTP port) - Add AMQP_URL to live-secrets (Secret) for live and live-exporter - Add EXPORT_QUEUE_NAME to live-vars ConfigMap (default: plane-exports) - Declare services.live_exporter and env.export_queue_name in values.yaml - Add Rancher form entries in questions.yml - Document in README under Live Exporter and live_env_existingSecret sections - Bump chart version 3.0.0 → 3.1.0 Co-Authored-By: Claude Sonnet 4.6 --- charts/plane-enterprise/Chart.yaml | 2 +- charts/plane-enterprise/README.md | 18 +++++++ charts/plane-enterprise/questions.yml | 33 ++++++++++++ .../templates/config-secrets/live-env.yaml | 9 ++++ .../workloads/live-exporter.deployment.yaml | 54 +++++++++++++++++++ charts/plane-enterprise/values.yaml | 19 +++++++ 6 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 charts/plane-enterprise/templates/workloads/live-exporter.deployment.yaml diff --git a/charts/plane-enterprise/Chart.yaml b/charts/plane-enterprise/Chart.yaml index 32f83301..e1eb826e 100644 --- a/charts/plane-enterprise/Chart.yaml +++ b/charts/plane-enterprise/Chart.yaml @@ -5,7 +5,7 @@ description: Meet Plane. An Enterprise software development tool to manage issue type: application -version: 3.0.0 +version: 3.1.0 appVersion: "3.0.0" home: https://plane.so/ diff --git a/charts/plane-enterprise/README.md b/charts/plane-enterprise/README.md index 1fa17fe0..8e9c9572 100644 --- a/charts/plane-enterprise/README.md +++ b/charts/plane-enterprise/README.md @@ -455,6 +455,7 @@ securityContext: | 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. | @@ -463,6 +464,21 @@ securityContext: | 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 | 50Mi | | Memory request for the exporter pod. | +| services.live_exporter.cpuRequest | 50m | | 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 | @@ -874,6 +890,8 @@ To configure the external secrets for your application, you need to define speci | | `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 | `` | | | `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` | diff --git a/charts/plane-enterprise/questions.yml b/charts/plane-enterprise/questions.yml index 12241b87..4c11f66e 100644 --- a/charts/plane-enterprise/questions.yml +++ b/charts/plane-enterprise/questions.yml @@ -267,6 +267,39 @@ questions: label: "Live Server Secret Key" type: string default: "htbqvBJAgpm9bzvf3r4urJer0ENReatceh" + - variable: env.export_queue_name + label: "Export Queue Name" + description: "RabbitMQ queue name for background PDF/DOCX export jobs consumed by the live-exporter service." + type: string + default: "plane-exports" + +- variable: services.live_exporter.enabled + label: "Install Live Exporter Service" + type: boolean + default: true + group: "Live Exporter Setup" + show_subquestion_if: true + subquestions: + - variable: services.live_exporter.replicas + label: "Default Replica Count" + type: int + default: 1 + - variable: services.live_exporter.memoryLimit + label: "Memory Limit" + type: string + default: 2000Mi + - variable: services.live_exporter.cpuLimit + label: "CPU Limit" + type: string + default: 1000m + - variable: services.live_exporter.memoryRequest + label: "Memory Request" + type: string + default: 50Mi + - variable: services.live_exporter.cpuRequest + label: "CPU Request" + type: string + default: 50m - variable: services.silo.enabled label: "Install Silo Service" diff --git a/charts/plane-enterprise/templates/config-secrets/live-env.yaml b/charts/plane-enterprise/templates/config-secrets/live-env.yaml index 16855c46..05470869 100644 --- a/charts/plane-enterprise/templates/config-secrets/live-env.yaml +++ b/charts/plane-enterprise/templates/config-secrets/live-env.yaml @@ -14,6 +14,13 @@ stringData: {{- else }} REDIS_URL: {{ .Values.env.remote_redis_url | default "" | quote }} {{- end }} + {{- if .Values.services.rabbitmq.local_setup }} + AMQP_URL: "amqp://{{ .Values.services.rabbitmq.default_user }}:{{ .Values.services.rabbitmq.default_password }}@{{ .Release.Name }}-rabbitmq.{{ .Release.Namespace }}.svc.{{ .Values.env.default_cluster_domain | default "cluster.local" }}/" + {{- else if .Values.services.rabbitmq.external_rabbitmq_url }} + AMQP_URL: {{ .Values.services.rabbitmq.external_rabbitmq_url | quote }} + {{- else }} + AMQP_URL: "" + {{- end }} {{- end }} --- apiVersion: v1 @@ -41,4 +48,6 @@ data: {{- else }} IFRAMELY_URL: http://{{ .Release.Name }}-iframely.{{ .Release.Namespace }}.svc.{{ .Values.env.default_cluster_domain | default "cluster.local" }}:8061/ {{- end }} + + EXPORT_QUEUE_NAME: {{ .Values.env.export_queue_name | default "plane-exports" | quote }} --- diff --git a/charts/plane-enterprise/templates/workloads/live-exporter.deployment.yaml b/charts/plane-enterprise/templates/workloads/live-exporter.deployment.yaml new file mode 100644 index 00000000..eb781a73 --- /dev/null +++ b/charts/plane-enterprise/templates/workloads/live-exporter.deployment.yaml @@ -0,0 +1,54 @@ + +{{- if .Values.services.live_exporter.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-live-exporter-wl + {{- include "plane.labelsAndAnnotations" (dict "context" $ "values" .Values.services.live_exporter) }} +spec: + replicas: {{ .Values.services.live_exporter.replicas | default 1 }} + selector: + matchLabels: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-live-exporter + template: + metadata: + namespace: {{ .Release.Namespace }} + labels: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-live-exporter + {{- include "plane.commonLabels" $ | nindent 8 }} + annotations: + timestamp: {{ now | quote }} + spec: + {{- include "plane.podScheduling" .Values.services.live_exporter }} + {{- include "plane.podSecurityContext" . }} + containers: + - name: {{ .Release.Name }}-live-exporter + {{- include "plane.containerSecurityContext" . }} + imagePullPolicy: {{ .Values.services.live_exporter.pullPolicy | default "Always" }} + image: {{ .Values.services.live_exporter.image | default "makeplane/live-commercial" }}:{{ .Values.planeVersion }} + stdin: true + tty: true + resources: + requests: + memory: {{ .Values.services.live_exporter.memoryRequest | default "50Mi" | quote }} + cpu: {{ .Values.services.live_exporter.cpuRequest | default "50m" | quote }} + limits: + memory: {{ .Values.services.live_exporter.memoryLimit | default "2000Mi" | quote }} + cpu: {{ .Values.services.live_exporter.cpuLimit | default "1000m" | quote }} + envFrom: + - configMapRef: + name: {{ .Release.Name }}-live-vars + optional: false + - secretRef: + name: {{ if not (empty .Values.external_secrets.live_env_existingSecret) }}{{ .Values.external_secrets.live_env_existingSecret }}{{ else }}{{ .Release.Name }}-live-secrets{{ end }} + optional: false + env: + - name: LIVE_MODE + value: "exporter" + {{- if .Values.extraEnv }} + {{- toYaml .Values.extraEnv | nindent 10 }} + {{- end }} + serviceAccount: {{ .Release.Name }}-srv-account + serviceAccountName: {{ .Release.Name }}-srv-account +{{- end }} diff --git a/charts/plane-enterprise/values.yaml b/charts/plane-enterprise/values.yaml index 8394e9af..23482b8e 100644 --- a/charts/plane-enterprise/values.yaml +++ b/charts/plane-enterprise/values.yaml @@ -273,6 +273,22 @@ services: labels: {} annotations: {} + live_exporter: + enabled: true + replicas: 1 + # PDF render footprint is 500MB-2GB; default limits reflect that. + memoryLimit: 2000Mi + cpuLimit: 1000m + memoryRequest: 50Mi + cpuRequest: 50m + image: makeplane/live-commercial + pullPolicy: Always + nodeSelector: {} + tolerations: [] + affinity: {} + labels: {} + annotations: {} + api: replicas: 1 memoryLimit: 1000Mi @@ -614,6 +630,9 @@ env: live_sentry_environment: "" live_sentry_traces_sample_rate: "" live_server_secret_key: "htbqvBJAgpm9bzvf3r4urJer0ENReatceh" + + # Background PDF/DOCX export worker queue. + export_queue_name: "plane-exports" external_iframely_url: "" silo_envs: From c0ce8571e29fb30186659359e0893f9a016dbaf0 Mon Sep 17 00:00:00 2001 From: akshat5302 Date: Tue, 4 Aug 2026 12:50:42 +0530 Subject: [PATCH 2/5] feat(live-exporter): remove LIVE_MODE environment variable from deployment --- .../templates/workloads/live-exporter.deployment.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/charts/plane-enterprise/templates/workloads/live-exporter.deployment.yaml b/charts/plane-enterprise/templates/workloads/live-exporter.deployment.yaml index eb781a73..71d9108f 100644 --- a/charts/plane-enterprise/templates/workloads/live-exporter.deployment.yaml +++ b/charts/plane-enterprise/templates/workloads/live-exporter.deployment.yaml @@ -44,8 +44,6 @@ spec: name: {{ if not (empty .Values.external_secrets.live_env_existingSecret) }}{{ .Values.external_secrets.live_env_existingSecret }}{{ else }}{{ .Release.Name }}-live-secrets{{ end }} optional: false env: - - name: LIVE_MODE - value: "exporter" {{- if .Values.extraEnv }} {{- toYaml .Values.extraEnv | nindent 10 }} {{- end }} From 0c6ed120972cf7f6de50ad686e847959e91defb8 Mon Sep 17 00:00:00 2001 From: akshat5302 Date: Tue, 4 Aug 2026 13:05:26 +0530 Subject: [PATCH 3/5] feat(live-exporter): add pull policy configuration for Live Exporter service --- charts/plane-enterprise/questions.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/charts/plane-enterprise/questions.yml b/charts/plane-enterprise/questions.yml index 4c11f66e..aaa85cb5 100644 --- a/charts/plane-enterprise/questions.yml +++ b/charts/plane-enterprise/questions.yml @@ -284,6 +284,14 @@ questions: label: "Default Replica Count" type: int default: 1 + - variable: services.live_exporter.pullPolicy + label: "Live Exporter Pull Policy" + type: enum + options: + - "Always" + - "IfNotPresent" + - "Never" + default: "Always" - variable: services.live_exporter.memoryLimit label: "Memory Limit" type: string From 97a7496dd8816ed52158e143c2b27b8ca95b15cc Mon Sep 17 00:00:00 2001 From: akshat5302 Date: Wed, 5 Aug 2026 14:00:30 +0530 Subject: [PATCH 4/5] fix(plane-enterprise): add LIVE_MODE=exporter env to live-exporter deployment Co-Authored-By: Claude Sonnet 4.6 --- .../templates/workloads/live-exporter.deployment.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/charts/plane-enterprise/templates/workloads/live-exporter.deployment.yaml b/charts/plane-enterprise/templates/workloads/live-exporter.deployment.yaml index 71d9108f..eb781a73 100644 --- a/charts/plane-enterprise/templates/workloads/live-exporter.deployment.yaml +++ b/charts/plane-enterprise/templates/workloads/live-exporter.deployment.yaml @@ -44,6 +44,8 @@ spec: name: {{ if not (empty .Values.external_secrets.live_env_existingSecret) }}{{ .Values.external_secrets.live_env_existingSecret }}{{ else }}{{ .Release.Name }}-live-secrets{{ end }} optional: false env: + - name: LIVE_MODE + value: "exporter" {{- if .Values.extraEnv }} {{- toYaml .Values.extraEnv | nindent 10 }} {{- end }} From 01296050c5f49593fc7ab80aef6c3617bd4324be Mon Sep 17 00:00:00 2001 From: akshat5302 Date: Wed, 5 Aug 2026 17:12:35 +0530 Subject: [PATCH 5/5] feat(plane-enterprise): add EXPORT_DOWNLOAD_BASE_URL env to live-vars Defaults to licenseDomain with protocol inferred from SSL settings. Configurable via env.export_download_base_url. Co-Authored-By: Claude Sonnet 4.6 --- charts/plane-enterprise/questions.yml | 5 +++++ .../templates/config-secrets/live-env.yaml | 7 +++++++ charts/plane-enterprise/values.yaml | 2 ++ 3 files changed, 14 insertions(+) diff --git a/charts/plane-enterprise/questions.yml b/charts/plane-enterprise/questions.yml index aaa85cb5..209d627d 100644 --- a/charts/plane-enterprise/questions.yml +++ b/charts/plane-enterprise/questions.yml @@ -272,6 +272,11 @@ questions: description: "RabbitMQ queue name for background PDF/DOCX export jobs consumed by the live-exporter service." type: string default: "plane-exports" + - variable: env.export_download_base_url + label: "Export Download Base URL" + description: "Base URL for export download redirects. Defaults to licenseDomain with protocol inferred from SSL settings." + type: string + default: "" - variable: services.live_exporter.enabled label: "Install Live Exporter Service" diff --git a/charts/plane-enterprise/templates/config-secrets/live-env.yaml b/charts/plane-enterprise/templates/config-secrets/live-env.yaml index 05470869..5f249ce6 100644 --- a/charts/plane-enterprise/templates/config-secrets/live-env.yaml +++ b/charts/plane-enterprise/templates/config-secrets/live-env.yaml @@ -49,5 +49,12 @@ data: IFRAMELY_URL: http://{{ .Release.Name }}-iframely.{{ .Release.Namespace }}.svc.{{ .Values.env.default_cluster_domain | default "cluster.local" }}:8061/ {{- end }} + {{- if or .Values.ssl.tls_secret_name (and .Values.ssl.createIssuer .Values.ssl.generateCerts) }} + EXPORT_DOWNLOAD_BASE_URL: {{ .Values.env.export_download_base_url | default (printf "https://%s" .Values.license.licenseDomain) | quote }} + {{- else }} + EXPORT_DOWNLOAD_BASE_URL: {{ .Values.env.export_download_base_url | default (printf "http://%s" .Values.license.licenseDomain) | quote }} + {{- end }} + EXPORT_QUEUE_NAME: {{ .Values.env.export_queue_name | default "plane-exports" | quote }} + --- diff --git a/charts/plane-enterprise/values.yaml b/charts/plane-enterprise/values.yaml index 23482b8e..999c8416 100644 --- a/charts/plane-enterprise/values.yaml +++ b/charts/plane-enterprise/values.yaml @@ -633,6 +633,8 @@ env: # Background PDF/DOCX export worker queue. export_queue_name: "plane-exports" + # Base URL for export download redirects. Defaults to licenseDomain with protocol from SSL settings. + export_download_base_url: "" external_iframely_url: "" silo_envs: