Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@ _publish.yml

# helm packages
*.tgz

# local working notes
notes.md
6 changes: 3 additions & 3 deletions charts/rstudio-connect/Chart.lock
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
dependencies:
- name: rstudio-library
repository: https://helm.rstudio.com
version: 0.1.35
digest: sha256:59fe5e712690610495d2ff32c6c78cc136e9685a785151d4cdba4b914d110f87
generated: "2025-10-09T13:37:20.639004-05:00"
version: 0.1.36
digest: sha256:cde061b0b7da43d7adbfcbc8d90e6d466d453dd707d8dad4f702fec6aeea103b
generated: "2026-04-01T12:03:45.783681-05:00"
4 changes: 2 additions & 2 deletions charts/rstudio-connect/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: rstudio-connect
description: Official Helm chart for Posit Connect
version: 0.8.38
version: 0.9.0
apiVersion: v2
appVersion: 2026.03.1
icon: https://raw.githubusercontent.com/rstudio/helm/main/images/posit-icon-fullcolor.svg
Expand All @@ -13,7 +13,7 @@ maintainers:
url: https://github.com/sol-eng
dependencies:
- name: rstudio-library
version: 0.1.35
version: 0.1.36
repository: https://helm.rstudio.com
annotations:
artifacthub.io/images: |
Expand Down
4 changes: 4 additions & 0 deletions charts/rstudio-connect/NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 0.9.0

- TODO

## 0.8.38

- Bump Connect version to 2026.03.1
Expand Down
20 changes: 14 additions & 6 deletions charts/rstudio-connect/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Posit Connect

![Version: 0.8.38](https://img.shields.io/badge/Version-0.8.38-informational?style=flat-square) ![AppVersion: 2026.03.1](https://img.shields.io/badge/AppVersion-2026.03.1-informational?style=flat-square)
![Version: 0.9.0](https://img.shields.io/badge/Version-0.9.0-informational?style=flat-square) ![AppVersion: 2026.03.1](https://img.shields.io/badge/AppVersion-2026.03.1-informational?style=flat-square)

#### _Official Helm chart for Posit Connect_

Expand Down Expand Up @@ -30,11 +30,11 @@ To ensure reproducibility in your environment and insulate yourself from future

## Installing the chart

To install the chart with the release name `my-release` at version 0.8.38:
To install the chart with the release name `my-release` at version 0.9.0:

```{.bash}
helm repo add rstudio https://helm.rstudio.com
helm upgrade --install my-release rstudio/rstudio-connect --version=0.8.38
helm upgrade --install my-release rstudio/rstudio-connect --version=0.9.0
```

To explore other chart versions, look at:
Expand All @@ -48,7 +48,7 @@ helm search repo rstudio/rstudio-connect -l
### 0.8.0

- When upgrading to version 0.8.0 or later, Connect now runs in [Off-Host Execution mode](https://docs.posit.co/connect/admin/getting-started/off-host-install/) by default
- If you desire to run Connect not in Off-Host Execution mode, then set `securityContext.privileged: true` and `launcher.enabled: false`
- If you desire to run Connect in Local Execution mode, then set `securityContext.privileged: true` and `launcher.enabled: false`

## Required configuration

Expand Down Expand Up @@ -262,6 +262,14 @@ The Helm `config` values are converted into the `rstudio-connect.gcfg` service c
|-----|------|---------|-------------|
| affinity | object | `{}` | A map used verbatim as the pod's "affinity" definition |
| args | list | `[]` | The pod's run arguments. By default, it uses the container's default |
| backends.kubernetes.defaultInitContainer.enabled | bool | `true` | Whether to enable the defaultInitContainer. If disabled, you must ensure that the session components are available another way. Changing the default setting is an advanced option and not recommended. For more information on how Connect uses the session init container refer to https://docs.posit.co/connect/admin/appendix/off-host/arch-overview/#runtime-init-container |
| backends.kubernetes.defaultInitContainer.repository | string | `"ghcr.io/rstudio/rstudio-connect-content-init"` | The repository to use for the Content InitContainer image |
| backends.kubernetes.defaultInitContainer.tag | string | `""` | Overrides the image tag whose default is the chart appVersion. |
| backends.kubernetes.defaultInitContainer.tagPrefix | string | `"ubuntu2204-"` | A tag prefix for the Content InitContainer image (common selections: jammy-, ubuntu2204-). Only used if tag is not defined |
| backends.kubernetes.defaultResourceJobBase | object | `{}` | defaultResourceJobBase is an optional Kubernetes Job definition used as the base when launching content jobs. The chart automatically adds the init container and runtime volume when backends.kubernetes.defaultInitContainer.enabled is true. Only set this if you need to customize the job (e.g., add sidecars, node selectors, tolerations). https://kubernetes.io/docs/concepts/workloads/controllers/job/ |
| backends.kubernetes.defaultResourceServiceBase | object | `{}` | defaultResourceServiceBase contains the Kubernetes Service definition which is used as an overlay "base" when creating a content job's Service in Kubernetes. Conceptually this is a similar to a Kustomize base. Connect then applies any required Service configuration on-top of the overlay base to produce a final Service definition. https://docs.posit.co/connect/__unreleased__/admin/appendix/off-host/direct-runner/kubernetes-job-overlays.html https://kubernetes.io/docs/concepts/services-networking/service/ https://kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization/#bases-and-overlays |
| backends.kubernetes.enabled | bool | `false` | Whether to enable the native Go implementation of off-host execution for running content-jobs in remote Kubernetes pods. |
| backends.kubernetes.namespace | string | `""` | The namespace to launch connect-content jobs into. Uses the Release namespace by default |
| chronicleAgent.agentEnvironment | string | `""` | An environment tag to apply to all metrics reported by this agent ([reference](https://docs.posit.co/chronicle/appendix/library/advanced-agent.html#environment)) |
| chronicleAgent.autoDiscovery | bool | `true` | If true, the chart will attempt to lookup the Chronicle Server address and version in the cluster |
| chronicleAgent.connectApiKey | object | `{"value":"","valueFrom":{}}` | An Administrator permissions API key generated in Connect for the Chronicle agent to use, API keys can only be created after Connect has been deployed so this value may need to be filled in later if performing an initial deployment ([reference](https://docs.posit.co/connect/user/api-keys/#api-keys-creating)) |
Expand Down Expand Up @@ -350,8 +358,8 @@ The Helm `config` values are converted into the `rstudio-connect.gcfg` service c
| prometheus.enabled | bool | `true` | The parent setting for whether to enable prometheus metrics. Default is to use the built-in product exporter |
| prometheus.port | int | `3232` | The port that prometheus will listen on |
| rbac.clusterRoleCreate | bool | `false` | Whether to create the ClusterRole that grants access to the Kubernetes nodes API. This is used by the Launcher to get all of the IP addresses associated with the node that is running a particular job. In most cases, this can be disabled as the node's internal address is sufficient to allow proper functionality. |
| rbac.create | bool | `true` | Whether to create rbac. (also depends on launcher.enabled = true) |
| rbac.serviceAccount | object | `{"annotations":{},"create":true,"labels":{},"name":""}` | The serviceAccount to be associated with rbac (also depends on launcher.enabled = true) |
| rbac.create | bool | `true` | Whether to create rbac. (also depends on launcher.enabled = true or backends.kubernetes.enabled = true) |
| rbac.serviceAccount | object | `{"annotations":{},"create":true,"labels":{},"name":""}` | The serviceAccount to be associated with rbac (also depends on launcher.enabled = true or backends.kubernetes.enabled = true) |
| readinessProbe | object | `{"enabled":true,"failureThreshold":3,"httpGet":{"path":"/__ping__","port":3939},"initialDelaySeconds":3,"periodSeconds":3,"successThreshold":1,"timeoutSeconds":1}` | Used to configure the container's readinessProbe. Only included if enabled = true |
| replicas | int | `1` | The number of replica pods to maintain for this service |
| resources | object | `{}` | Defines resources for the rstudio-connect container |
Expand Down
2 changes: 1 addition & 1 deletion charts/rstudio-connect/README.md.gotmpl
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
### 0.8.0

- When upgrading to version 0.8.0 or later, Connect now runs in [Off-Host Execution mode](https://docs.posit.co/connect/admin/getting-started/off-host-install/) by default
- If you desire to run Connect not in Off-Host Execution mode, then set `securityContext.privileged: true` and `launcher.enabled: false`
- If you desire to run Connect in Local Execution mode, then set `securityContext.privileged: true` and `launcher.enabled: false`

## Required configuration

Expand Down
18 changes: 18 additions & 0 deletions charts/rstudio-connect/ci/kubernetes-values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
license:
file:
secret: pct-license
secretKey: pct.lic

launcher:
enabled: false

backends:
kubernetes:
enabled: true

# a PVC is required for Connect to run in OHE (now the default)
sharedStorage:
create: true
# normally this should be ReadWriteMany, setting just for CI
accessModes:
- ReadWriteOnce
4 changes: 4 additions & 0 deletions charts/rstudio-connect/templates/NOTES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ Please consider removing this configuration value.

{{- /* chart deprecations and misconfiguration warnings */ -}}

{{- if and .Values.launcher.enabled .Values.backends.kubernetes.enabled }}
{{- fail "\n\n`launcher.enabled` and `backends.kubernetes.enabled` cannot both be true"}}
{{- end }}

{{- if and .Values.launcher.useTemplates .Values.launcher.enabled }}
{{- range $k,$v := .Values.launcher.launcherKubernetesProfilesConf }}
{{- if hasKey $v "job-json-overrides" }}
Expand Down
113 changes: 113 additions & 0 deletions charts/rstudio-connect/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,20 @@ app.kubernetes.io/instance: {{ .Release.Name }}
{{- $eeDict := dict "ExecutionEnvironments" (dict "ConfigFilePath" "/etc/rstudio-connect/execution-environments/environments.yaml") }}
{{- $defaultConfig = merge $defaultConfig $eeDict }}
{{- end }}
{{- if .Values.backends.kubernetes.enabled }}
{{- $namespace := default $.Release.Namespace .Values.backends.kubernetes.namespace }}
{{- $kubernetesSettingsDict := dict "Enabled" ("true") "Namespace" ($namespace) }}
{{- if and (or .Values.sharedStorage.create .Values.sharedStorage.mount) .Values.sharedStorage.mountContent }}
{{- $dataDirPVCName := default (print (include "rstudio-connect.fullname" .) "-shared-storage" ) .Values.sharedStorage.name }}
{{- $_ := set $kubernetesSettingsDict "DataDirPVCName" $dataDirPVCName }}
{{- end }}
{{- $_ := set $kubernetesSettingsDict "DefaultResourceJobBase" (default "/etc/rstudio-connect/job.yaml" .Values.config.Kubernetes.DefaultResourceJobBase) }}
{{- if .Values.backends.kubernetes.defaultResourceServiceBase }}
{{- $_ := set $kubernetesSettingsDict "DefaultResourceServiceBase" (default "/etc/rstudio-connect/service.yaml" .Values.config.Kubernetes.DefaultResourceServiceBase) }}
{{- end }}
{{- $kubernetesDict := dict "Kubernetes" ( $kubernetesSettingsDict ) }}
{{- $defaultConfig = merge $defaultConfig $kubernetesDict }}
{{- end }}
{{- /* default licensing configuration */}}
{{- if .Values.license.server }}
{{- $licenseDict := dict "Licensing" ( dict "LicenseType" ("Remote") ) }}
Expand Down Expand Up @@ -155,3 +169,102 @@ app.kubernetes.io/instance: {{ .Release.Name }}
{{ $key }}: {{ $value | quote }}
{{ end }}
{{- end -}}

{{/*
Build the job resource base for the native Kubernetes runner.
Starts with the user-provided defaultResourceJobBase (or empty dict),
then adds the init container, content container, and shared volume
when defaultInitContainer.enabled is true.
*/}}
{{- define "rstudio-connect.jobBase" -}}
{{- $jobBase := deepCopy (default (dict) .Values.backends.kubernetes.defaultResourceJobBase) }}
{{- /* ensure top-level fields */}}
{{- if not (hasKey $jobBase "apiVersion") }}
{{- $_ := set $jobBase "apiVersion" "batch/v1" }}
{{- end }}
{{- if not (hasKey $jobBase "kind") }}
{{- $_ := set $jobBase "kind" "Job" }}
{{- end }}
{{- if .Values.backends.kubernetes.defaultInitContainer.enabled }}
{{- /* build init container image tag */}}
{{- $defaultVersion := .Values.versionOverride | default $.Chart.AppVersion }}
{{- $tag := .Values.backends.kubernetes.defaultInitContainer.tag | default (printf "%s%s" .Values.backends.kubernetes.defaultInitContainer.tagPrefix $defaultVersion) }}
{{- $image := printf "%s:%s" .Values.backends.kubernetes.defaultInitContainer.repository $tag }}
{{- /* build the init container */}}
{{- $initVolumeMount := dict "name" "rsc-volume" "mountPath" "/mnt/rstudio-connect-runtime/" }}
{{- $initContainer := dict "name" "connect-content-init" "image" $image "volumeMounts" (list $initVolumeMount) }}
{{- /* build the content container */}}
{{- $contentVolumeMount := dict "name" "rsc-volume" "mountPath" "/opt/rstudio-connect" }}
{{- $contentContainer := dict "name" "connect-content" "volumeMounts" (list $contentVolumeMount) }}
{{- /* build the shared volume */}}
{{- $rscVolume := dict "name" "rsc-volume" "emptyDir" (dict) }}
{{- /* ensure spec.template.spec exists */}}
{{- if not (hasKey $jobBase "spec") }}
{{- $_ := set $jobBase "spec" (dict) }}
{{- end }}
{{- if not (hasKey $jobBase.spec "template") }}
{{- $_ := set $jobBase.spec "template" (dict) }}
{{- end }}
{{- if not (hasKey $jobBase.spec.template "spec") }}
{{- $_ := set $jobBase.spec.template "spec" (dict) }}
{{- end }}
{{- $podSpec := $jobBase.spec.template.spec }}
{{- /* add init container if not already present */}}
{{- $existingInits := default list $podSpec.initContainers }}
{{- $hasInit := false }}
{{- range $existingInits }}
{{- if eq .name "connect-content-init" }}
{{- $_ := set . "image" $image }}
{{- $hasInit = true }}
{{- $mounts := default list .volumeMounts }}
{{- $hasMount := false }}
{{- range $mounts }}
{{- if and (eq .name "rsc-volume") (eq .mountPath "/mnt/rstudio-connect-runtime/") }}
{{- $hasMount = true }}
{{- end }}
{{- end }}
{{- if not $hasMount }}
{{- $_ := set . "volumeMounts" (append $mounts $initVolumeMount) }}
{{- end }}
{{- end }}
{{- end }}
{{- if not $hasInit }}
{{- $_ := set $podSpec "initContainers" (append $existingInits $initContainer) }}
{{- else }}
{{- $_ := set $podSpec "initContainers" $existingInits }}
{{- end }}
{{- /* add content container if not already present, or ensure volume mount if it is */}}
{{- $existingContainers := default list $podSpec.containers }}
{{- $hasContent := false }}
{{- range $existingContainers }}
{{- if eq .name "connect-content" }}
{{- $hasContent = true }}
{{- $mounts := default list .volumeMounts }}
{{- $hasMount := false }}
{{- range $mounts }}
{{- if eq .mountPath "/opt/rstudio-connect" }}
{{- $hasMount = true }}
{{- end }}
{{- end }}
{{- if not $hasMount }}
{{- $_ := set . "volumeMounts" (append $mounts $contentVolumeMount) }}
{{- end }}
{{- end }}
{{- end }}
{{- if not $hasContent }}
{{- $_ := set $podSpec "containers" (append $existingContainers $contentContainer) }}
{{- end }}
{{- /* add rsc-volume if not already present */}}
{{- $existingVolumes := default list $podSpec.volumes }}
{{- $hasVolume := false }}
{{- range $existingVolumes }}
{{- if eq .name "rsc-volume" }}
{{- $hasVolume = true }}
{{- end }}
{{- end }}
{{- if not $hasVolume }}
{{- $_ := set $podSpec "volumes" (append $existingVolumes $rscVolume) }}
{{- end }}
{{- end }}
{{- toYaml $jobBase }}
{{- end -}}
2 changes: 1 addition & 1 deletion charts/rstudio-connect/templates/configmap-prestart.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{{- if .Values.launcher.enabled }}
{{- if or .Values.launcher.enabled .Values.backends.kubernetes.enabled }}
---
apiVersion: v1
kind: ConfigMap
Expand Down
8 changes: 8 additions & 0 deletions charts/rstudio-connect/templates/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ metadata:
data:
rstudio-connect.gcfg: |
{{- include "rstudio-connect.config" . | nindent 4 }}
{{- if .Values.backends.kubernetes.enabled }}
job.yaml: |
{{- include "rstudio-connect.jobBase" . | nindent 4 }}
{{- if .Values.backends.kubernetes.defaultResourceServiceBase }}
service.yaml: |
{{- .Values.backends.kubernetes.defaultResourceServiceBase | toYaml | nindent 4 }}
{{- end }}
{{- end }}
{{- $sessionTemplate := deepCopy .Values.launcher.templateValues }}
{{- if .Values.launcher.enabled }}
runtime.yaml: |
Expand Down
22 changes: 18 additions & 4 deletions charts/rstudio-connect/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ spec:
metadata:
annotations:
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
{{- if .Values.launcher.enabled }}
{{- if or .Values.launcher.enabled .Values.backends.kubernetes.enabled }}
checksum/config-prestart: {{ include (print $.Template.BasePath "/configmap-prestart.yaml") . | sha256sum }}
{{- end }}
{{- if .Values.prometheus }}
Expand Down Expand Up @@ -73,7 +73,7 @@ spec:
* and also the "Note" callout at the end of this section:
* https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-multiple-service-accounts
*/}}
{{- if and .Values.rbac.create .Values.launcher.enabled }}
{{- if and .Values.rbac.create (or .Values.launcher.enabled .Values.backends.kubernetes.enabled) }}
{{ $serviceAccountName := default (include "rstudio-connect.fullname" .) .Values.rbac.serviceAccount.name }}
serviceAccountName: {{ $serviceAccountName }}
{{- else }}
Expand Down Expand Up @@ -167,7 +167,7 @@ spec:
{{- if .Values.command }}
command:
{{ toYaml .Values.command | indent 10 }}
{{- else if .Values.launcher.enabled }}
{{- else if (or .Values.launcher.enabled .Values.backends.kubernetes.enabled) }}
command:
- tini
- -s
Expand All @@ -176,7 +176,7 @@ spec:
{{- if .Values.args }}
args:
{{ toYaml .Values.args | indent 10 }}
{{- else if .Values.launcher.enabled }}
{{- else if (or .Values.launcher.enabled .Values.backends.kubernetes.enabled) }}
args:
- /scripts/prestart.bash
- /usr/local/bin/startup.sh
Expand All @@ -197,6 +197,16 @@ spec:
- name: rstudio-connect-config
mountPath: "/etc/rstudio-connect/rstudio-connect.gcfg"
subPath: "rstudio-connect.gcfg"
{{- if .Values.backends.kubernetes.enabled }}
- name: rstudio-connect-config
mountPath: {{ default "/etc/rstudio-connect/job.yaml" .Values.config.Kubernetes.DefaultResourceJobBase | quote }}
subPath: "job.yaml"
{{- if .Values.backends.kubernetes.defaultResourceServiceBase }}
- name: rstudio-connect-config
mountPath: {{ default "/etc/rstudio-connect/service.yaml" .Values.config.Kubernetes.DefaultResourceServiceBase | quote }}
subPath: "service.yaml"
{{- end }}
{{- end }}
{{- if .Values.launcher.enabled }}
- name: rstudio-connect-config
mountPath: "/etc/rstudio-connect/runtime.yaml"
Expand All @@ -219,6 +229,8 @@ spec:
- name: overrides
mountPath: "/mnt/job-json-overrides/"
{{- end }}
{{- end }}
{{- if or .Values.launcher.enabled .Values.backends.kubernetes.enabled }}
- name: rstudio-connect-prestart
mountPath: "/scripts/"
{{- end }}
Expand Down Expand Up @@ -313,6 +325,8 @@ spec:
name: {{ include "rstudio-connect.fullname" . }}-overrides
defaultMode: 0644
{{- end }}
{{- end }}
{{- if or .Values.launcher.enabled .Values.backends.kubernetes.enabled }}
- name: rstudio-connect-prestart
configMap:
name: {{ include "rstudio-connect.fullname" . }}-prestart
Expand Down
Loading
Loading