From 68dae078a692bebe82915050edf49d898a3d5308 Mon Sep 17 00:00:00 2001 From: oleksandr-codefresh Date: Fri, 17 Apr 2026 09:31:23 +0300 Subject: [PATCH 1/9] VIP --- .../octopus-deploy/applied-statefulset.yaml | 145 ++++++ charts/octopus-deploy/build.yaml | 467 ++++++++++++++++++ .../octopus-deploy/cluster-statefulset.yaml | 179 +++++++ charts/octopus-deploy/custom-values.yaml | 13 + charts/octopus-deploy/templates/_helpers.tpl | 2 +- 5 files changed, 805 insertions(+), 1 deletion(-) create mode 100644 charts/octopus-deploy/applied-statefulset.yaml create mode 100644 charts/octopus-deploy/build.yaml create mode 100644 charts/octopus-deploy/cluster-statefulset.yaml create mode 100644 charts/octopus-deploy/custom-values.yaml diff --git a/charts/octopus-deploy/applied-statefulset.yaml b/charts/octopus-deploy/applied-statefulset.yaml new file mode 100644 index 00000000..fe827fc3 --- /dev/null +++ b/charts/octopus-deploy/applied-statefulset.yaml @@ -0,0 +1,145 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: octopus-deploy + labels: + app.kubernetes.io/name: octopus-deploy + helm.sh/chart: octopusdeploy-helm-1.11.1 + app.kubernetes.io/instance: octopus-deploy + app.kubernetes.io/managed-by: Helm +spec: + selector: + matchLabels: + app.kubernetes.io/name: octopus-deploy + helm.sh/chart: octopusdeploy-helm-1.11.1 + app.kubernetes.io/instance: octopus-deploy + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: octopus-server + serviceName: octopus-deploy + replicas: 1 + template: + metadata: + labels: + app.kubernetes.io/name: octopus-deploy + helm.sh/chart: octopusdeploy-helm-1.11.1 + app.kubernetes.io/instance: octopus-deploy + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: octopus-server + spec: + serviceAccountName: default + containers: + - name: octopus + image: "docker.packages.octopushq.com/octopusdeploy/octopusdeploy:2026.2.4992-noamgal-yos-32-investigate-octopus-deploy-helm-chart-compatibility-with-linux" + securityContext: + env: + + - name: ACCEPT_EULA + value: "Y" + - name: OCTOPUS_SERVER_NODE_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: DB_CONNECTION_STRING + valueFrom: + secretKeyRef: + name: octopus-deploy-connectionstring + key: secret + - name: ADMIN_USERNAME + valueFrom: + secretKeyRef: + name: octopus-deploy-adminusername + key: secret + - name: ADMIN_PASSWORD + valueFrom: + secretKeyRef: + name: octopus-deploy-adminpassword + key: secret + - name: ADMIN_EMAIL + value: + - name: TASK_CAP + value: !!str + - name: OCTOPUS_SERVER_BASE64_LICENSE + # Your license key goes here. When using more than one node, a HA license is required. + # Without a HA license, the stateful set can have a replica count of 1. + valueFrom: + secretKeyRef: + name: octopus-deploy-licensekey + key: secret + - name: MASTER_KEY + valueFrom: + secretKeyRef: + name: octopus-deploy-masterkey + key: secret + - name: DISABLE_DIND + value: !!str "Y" + - name: OCTOPUS_INSTALLED_VIA_HELM + value: "true" + - name: OCTOPUS_GRPC_SERVICES_PORT + value: "8443" + ports: + - containerPort: 8080 + name: web + - containerPort: 10943 + name: tentacle + - containerPort: 8443 + name: grpcs + volumeMounts: + - name: package-repository-volume + mountPath: /repository + - name: artifacts-volume + mountPath: /artifacts + - name: task-log-volume + mountPath: /taskLogs + - name: server-log-volume + mountPath: /home/octopus/.octopus/OctopusServer/Server/Logs + - name: audit-log-volume + mountPath: /eventExports + readinessProbe: + exec: + command: + - /bin/bash + - -c + - URL=http://localhost:8080; response=$(/usr/bin/curl -k $URL/api/serverstatus/hosted/internal --write-out %{http_code} --silent --output /dev/null); /usr/bin/test "$response" -ge 200 && /usr/bin/test "$response" -le 299 || /usr/bin/test + initialDelaySeconds: 30 + periodSeconds: 30 + timeoutSeconds: 5 + failureThreshold: 60 + livenessProbe: + exec: + command: + - /bin/bash + - -c + - URL=http://localhost:8080; response=$(/usr/bin/curl -k $URL/api/octopusservernodes/ping --write-out %{http_code} --silent --output /dev/null); /usr/bin/test "$response" -ge 200 && /usr/bin/test "$response" -le 299 || /usr/bin/test "$response" -eq 418 + periodSeconds: 30 + timeoutSeconds: 5 + failureThreshold: 10 + startupProbe: + exec: + command: + - /bin/bash + - -c + - URL=http://localhost:8080; response=$(/usr/bin/curl -k $URL/api/octopusservernodes/ping --write-out %{http_code} --silent --output /dev/null); /usr/bin/test "$response" -ge 200 && /usr/bin/test "$response" -le 299 || /usr/bin/test "$response" -eq 418 + failureThreshold: 30 + periodSeconds: 60 + terminationGracePeriodSeconds: 10 + volumes: + - name: package-repository-volume + persistentVolumeClaim: + claimName: package-repository-claim + - name: artifacts-volume + persistentVolumeClaim: + claimName: artifacts-claim + - name: task-log-volume + persistentVolumeClaim: + claimName: task-log-claim + - name: audit-log-volume + persistentVolumeClaim: + claimName: audit-log-claim + volumeClaimTemplates: + - metadata: + name: server-log-volume + spec: + accessModes: [ "ReadWriteOnce" ] + resources: + requests: + storage: 200Mi \ No newline at end of file diff --git a/charts/octopus-deploy/build.yaml b/charts/octopus-deploy/build.yaml new file mode 100644 index 00000000..49ceb03e --- /dev/null +++ b/charts/octopus-deploy/build.yaml @@ -0,0 +1,467 @@ +--- +# Source: octopusdeploy-helm/charts/mssql/templates/secret.yaml +apiVersion: v1 +kind: Secret +metadata: + name: mssql + labels: + app.kubernetes.io/name: octopus-deploy + helm.sh/chart: mssql-0.0.1 + app.kubernetes.io/instance: octopus-deploy + app.kubernetes.io/managed-by: Helm +type: Opaque +data: + sa_password : "VlNzZ2xkUzN5anZnbWdZRnhLemQwNXc1NjVVVUdScjc=" +--- +# Source: octopusdeploy-helm/templates/secrets.yaml +apiVersion: v1 +kind: Secret +type: opaque +metadata: + name: octopus-deploy-adminpassword + labels: + app.kubernetes.io/name: octopus-deploy + helm.sh/chart: octopusdeploy-helm-1.11.1 + app.kubernetes.io/instance: octopus-deploy + app.kubernetes.io/managed-by: Helm +data: + secret: UGFzc3dvcmQwMSE= +--- +# Source: octopusdeploy-helm/templates/secrets.yaml +apiVersion: v1 +kind: Secret +type: opaque +metadata: + name: octopus-deploy-adminusername + labels: + app.kubernetes.io/name: octopus-deploy + helm.sh/chart: octopusdeploy-helm-1.11.1 + app.kubernetes.io/instance: octopus-deploy + app.kubernetes.io/managed-by: Helm +data: + secret: YWRtaW4= +--- +# Source: octopusdeploy-helm/templates/secrets.yaml +apiVersion: v1 +kind: Secret +type: opaque +metadata: + name: octopus-deploy-connectionstring + labels: + app.kubernetes.io/name: octopus-deploy + helm.sh/chart: octopusdeploy-helm-1.11.1 + app.kubernetes.io/instance: octopus-deploy + app.kubernetes.io/managed-by: Helm +data: + secret: U2VydmVyPW1zc3FsLTAub2N0b3B1cy1kZXBsb3ktbXNzcWw7SW5pdGlhbCBDYXRhbG9nPU9jdG9wdXNEZXBsb3k7UGVyc2lzdCBTZWN1cml0eSBJbmZvPUZhbHNlO1VzZXIgSUQ9U0E7UGFzc3dvcmQ9VlNzZ2xkUzN5anZnbWdZRnhLemQwNXc1NjVVVUdScjc7RW5jcnlwdD1UcnVlO0Nvbm5lY3Rpb24gVGltZW91dD0zMDs= +--- +# Source: octopusdeploy-helm/templates/secrets.yaml +apiVersion: v1 +kind: Secret +type: opaque +metadata: + name: octopus-deploy-licensekey + labels: + app.kubernetes.io/name: octopus-deploy + helm.sh/chart: octopusdeploy-helm-1.11.1 + app.kubernetes.io/instance: octopus-deploy + app.kubernetes.io/managed-by: Helm +data: + secret: UEV4cFkyVnVjMlVnVTJsbmJtRjBkWEpsUFNKTGQwRnhRVVphTkZwS1Z6WnRjMEZSZUdKdlNHaHBkVXRuVDA1Nk5HbHJXVGRMYzBGcFNsaHlNVlpaVkRGUFMybFZjeXROWmk5dFFVcG5LMnAwU0ZjelYxTXpOVmhPUzNCMWVGWnhkM0pYVUV0emVFeGFaejA5SWo0S0lDQThUR2xqWlc1elpVdGxlVDR4TWpVME5TMDFNalUwT1MwME5UUXlNeTAyTWpVM05Ud3ZUR2xqWlc1elpVdGxlVDRLSUNBOFZtVnljMmx2Ymo0eUxqQThJUzB0SUV4cFkyVnVjMlVnVTJOb1pXMWhJRlpsY25OcGIyNGdMUzArUEM5V1pYSnphVzl1UGdvZ0lEeFdZV3hwWkVaeWIyMCtNakF5TlMwd09DMHhORHd2Vm1Gc2FXUkdjbTl0UGdvZ0lEeFdZV3hwWkZSdlBqSXdNekF0TURFdE1ESThMMVpoYkdsa1ZHOCtDaUFnUEV0cGJtUStVM1ZpYzJOeWFYQjBhVzl1UEM5TGFXNWtQZ29nSUR4TllXTm9hVzVsVEdsdGFYUWdWSGx3WlhNOUlsUmxiblJoWTJ4bFVHRnpjMmwyWlN4VVpXNTBZV05zWlVGamRHbDJaU3hUYzJnaVBsVnViR2x0YVhSbFpEd3ZUV0ZqYUdsdVpVeHBiV2wwUGdvZ0lEeE9iMlJsVEdsdGFYUStWVzVzYVcxcGRHVmtQQzlPYjJSbFRHbHRhWFErQ2lBZ1BGQnliMnBsWTNSTWFXMXBkRDVWYm14cGJXbDBaV1E4TDFCeWIycGxZM1JNYVcxcGRENEtJQ0E4VkdWdVlXNTBUR2x0YVhRK1ZXNXNhVzFwZEdWa1BDOVVaVzVoYm5STWFXMXBkRDRLSUNBOFUzQmhZMlZNYVcxcGRENVZibXhwYldsMFpXUThMMU53WVdObFRHbHRhWFErQ2lBZ1BGVnpaWEpNYVcxcGRENVZibXhwYldsMFpXUThMMVZ6WlhKTWFXMXBkRDRLSUNBOFYyOXlhMlZ5VEdsdGFYUStWVzVzYVcxcGRHVmtQQzlYYjNKclpYSk1hVzFwZEQ0S0lDQThSbVZoZEhWeVpYTStDaUFnSUNBOFFYVmthWFJNYjJkR1pXVmtjejRLSUNBZ0lDQWdQRlpoYkdsa1ZHOCtNakF5T1MweE1pMHpNVHd2Vm1Gc2FXUlViejRLSUNBZ0lEd3ZRWFZrYVhSTWIyZEdaV1ZrY3o0S0lDQWdJRHhLYVhKaFUyVnlkbWxqWlUxaGJtRm5aVzFsYm5SSmJuUmxaM0poZEdsdmJqNEtJQ0FnSUNBZ1BGWmhiR2xrVkc4K01qQXlPUzB4TWkwek1Ud3ZWbUZzYVdSVWJ6NEtJQ0FnSUR3dlNtbHlZVk5sY25acFkyVk5ZVzVoWjJWdFpXNTBTVzUwWldkeVlYUnBiMjQrQ2lBZ0lDQThVMlZ5ZG1salpVNXZkMGx1ZEdWbmNtRjBhVzl1UGdvZ0lDQWdJQ0E4Vm1Gc2FXUlViejR5TURJNUxURXlMVE14UEM5V1lXeHBaRlJ2UGdvZ0lDQWdQQzlUWlhKMmFXTmxUbTkzU1c1MFpXZHlZWFJwYjI0K0NpQWdJQ0E4U1c1emFXZG9kSE0rQ2lBZ0lDQWdJRHhXWVd4cFpGUnZQakl3TWprdE1USXRNekU4TDFaaGJHbGtWRzgrQ2lBZ0lDQThMMGx1YzJsbmFIUnpQZ29nSUNBZ1BGQnlhVzl5YVhSNVZHRnphejRLSUNBZ0lDQWdQRlpoYkdsa1ZHOCtNakF5T1MweE1pMHpNVHd2Vm1Gc2FXUlViejRLSUNBZ0lEd3ZVSEpwYjNKcGRIbFVZWE5yUGdvZ0lDQWdQRWRzYjJKaGJFUmxjR3h2ZVcxbGJuUkdjbVZsZW1VK0NpQWdJQ0FnSUR4V1lXeHBaRlJ2UGpJd01qa3RNVEl0TXpFOEwxWmhiR2xrVkc4K0NpQWdJQ0E4TDBkc2IySmhiRVJsY0d4dmVXMWxiblJHY21WbGVtVStDaUFnSUNBOFVISnZZMlZ6YzFSbGJYQnNZWFJsY3o0S0lDQWdJQ0FnUEZaaGJHbGtWRzgrTWpBeU9TMHhNaTB6TVR3dlZtRnNhV1JVYno0S0lDQWdJRHd2VUhKdlkyVnpjMVJsYlhCc1lYUmxjejRLSUNBZ0lEeFFiMnhwWTJsbGN6NEtJQ0FnSUNBZ1BGWmhiR2xrVkc4K01qQXlPUzB4TWkwek1Ed3ZWbUZzYVdSVWJ6NEtJQ0FnSUR3dlVHOXNhV05wWlhNK0NpQWdJQ0E4VUhKdmFtVmpkRlJsYlhCc1lYUmxjejRLSUNBZ0lDQWdQRlpoYkdsa1ZHOCtNakF5T1MweE1pMHpNRHd2Vm1Gc2FXUlViejRLSUNBZ0lEd3ZVSEp2YW1WamRGUmxiWEJzWVhSbGN6NEtJQ0E4TDBabFlYUjFjbVZ6UGdvOEwweHBZMlZ1YzJVK0NnPT0= +--- +# Source: octopusdeploy-helm/templates/secrets.yaml +apiVersion: v1 +kind: Secret +type: opaque +metadata: + name: octopus-deploy-masterkey + labels: + app.kubernetes.io/name: octopus-deploy + helm.sh/chart: octopusdeploy-helm-1.11.1 + app.kubernetes.io/instance: octopus-deploy + app.kubernetes.io/managed-by: Helm +data: + secret: U3lWemZHTXhablFuY0hCaGFqZ3lVdz09 +--- +# Source: octopusdeploy-helm/templates/secrets.yaml +apiVersion: v1 +kind: Secret +type: opaque +metadata: + name: octopus-deploy-sapassword + labels: + app.kubernetes.io/name: octopus-deploy + helm.sh/chart: octopusdeploy-helm-1.11.1 + app.kubernetes.io/instance: octopus-deploy + app.kubernetes.io/managed-by: Helm +data: + secret: VlNzZ2xkUzN5anZnbWdZRnhLemQwNXc1NjVVVUdScjc= +--- +# Source: octopusdeploy-helm/charts/mssql/templates/mssqlconfig.yaml +kind: ConfigMap +apiVersion: v1 +metadata: + name: mssql + labels: + app.kubernetes.io/name: octopus-deploy + helm.sh/chart: mssql-0.0.1 + app.kubernetes.io/instance: octopus-deploy + app.kubernetes.io/managed-by: Helm +data: + mssql.conf: | + [EULA] + accepteula = Y + accepteulaml = Y + + [coredump] + captureminiandfull = true + coredumptype = full + + [hadr] + hadrenabled = 1 + + [language] + lcid = 1033 +--- +# Source: octopusdeploy-helm/templates/pvc.yaml +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: package-repository-claim + labels: + app.kubernetes.io/name: octopus-deploy + helm.sh/chart: octopusdeploy-helm-1.11.1 + app.kubernetes.io/instance: octopus-deploy + app.kubernetes.io/managed-by: Helm +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi +--- +# Source: octopusdeploy-helm/templates/pvc.yaml +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: artifacts-claim + labels: + app.kubernetes.io/name: octopus-deploy + helm.sh/chart: octopusdeploy-helm-1.11.1 + app.kubernetes.io/instance: octopus-deploy + app.kubernetes.io/managed-by: Helm +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi +--- +# Source: octopusdeploy-helm/templates/pvc.yaml +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: task-log-claim + labels: + app.kubernetes.io/name: octopus-deploy + helm.sh/chart: octopusdeploy-helm-1.11.1 + app.kubernetes.io/instance: octopus-deploy + app.kubernetes.io/managed-by: Helm +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi +--- +# Source: octopusdeploy-helm/templates/pvc.yaml +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: audit-log-claim + labels: + app.kubernetes.io/name: octopus-deploy + helm.sh/chart: octopusdeploy-helm-1.11.1 + app.kubernetes.io/instance: octopus-deploy + app.kubernetes.io/managed-by: Helm +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi +--- +# Source: octopusdeploy-helm/charts/mssql/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: octopus-deploy-mssql + labels: + app.kubernetes.io/name: octopus-deploy + helm.sh/chart: mssql-0.0.1 + app.kubernetes.io/instance: octopus-deploy + app.kubernetes.io/managed-by: Helm +spec: + clusterIP: None + ports: + - port: 1433 + targetPort: 1433 + protocol: TCP + selector: + app.kubernetes.io/name: octopus-deploy + helm.sh/chart: mssql-0.0.1 + app.kubernetes.io/instance: octopus-deploy + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: mssql +--- +# Source: octopusdeploy-helm/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: octopus-deploy + labels: + app.kubernetes.io/name: octopus-deploy + helm.sh/chart: octopusdeploy-helm-1.11.1 + app.kubernetes.io/instance: octopus-deploy + app.kubernetes.io/managed-by: Helm +spec: + type: NodePort + selector: + app.kubernetes.io/name: octopus-deploy + helm.sh/chart: octopusdeploy-helm-1.11.1 + app.kubernetes.io/instance: octopus-deploy + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: octopus-server + ports: + - name: web + port: 80 + targetPort: 8080 + protocol: TCP + - name: grpcs + port: 8443 + targetPort: 8443 + protocol: TCP # If there is only one node, expose the tentacle along with the web port + - name: tentacle + port: 10943 + targetPort: 10943 + protocol: TCP +--- +# Source: octopusdeploy-helm/charts/mssql/templates/statefulset.yaml +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: mssql + labels: + app.kubernetes.io/name: octopus-deploy + helm.sh/chart: mssql-0.0.1 + app.kubernetes.io/instance: octopus-deploy + app.kubernetes.io/managed-by: Helm +spec: + serviceName: octopus-deploy-mssql + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: octopus-deploy + helm.sh/chart: mssql-0.0.1 + app.kubernetes.io/instance: octopus-deploy + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: mssql + template: + metadata: + labels: + app.kubernetes.io/name: octopus-deploy + helm.sh/chart: mssql-0.0.1 + app.kubernetes.io/instance: octopus-deploy + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: mssql + spec: + securityContext: + fsGroup: 10001 + containers: + - name: mssql + command: + - /bin/bash + - -c + - cp /var/opt/config/mssql.conf /var/opt/mssql/mssql.conf && /opt/mssql/bin/sqlservr + image: "mcr.microsoft.com/mssql/server:2022-latest" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 1433 + env: + - name: MSSQL_PID + value: "Developer" + - name: ACCEPT_EULA + value: "Y" + - name: MSSQL_AGENT_ENABLED + value: "false" + - name: SA_PASSWORD + valueFrom: + secretKeyRef: + name: mssql + key: sa_password + volumeMounts: + - name: mssql + mountPath: "/var/opt/mssql" + - name: mssql-config-volume + mountPath: /var/opt/config + volumes: + - name: mssql-config-volume + configMap: + name: mssql + volumeClaimTemplates: + - metadata: + name: mssql + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 8Gi +--- +# Source: octopusdeploy-helm/templates/statefulset.yaml +# Octopus Deploy server nodes are modeled as StatefulSet, as terminating a node while deployments or runbooks are executing will cause these tasks to be terminated +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: octopus-deploy + labels: + app.kubernetes.io/name: octopus-deploy + helm.sh/chart: octopusdeploy-helm-1.11.1 + app.kubernetes.io/instance: octopus-deploy + app.kubernetes.io/managed-by: Helm +spec: + selector: + matchLabels: + app.kubernetes.io/name: octopus-deploy + helm.sh/chart: octopusdeploy-helm-1.11.1 + app.kubernetes.io/instance: octopus-deploy + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: octopus-server + serviceName: octopus-deploy + replicas: 1 + template: + metadata: + labels: + app.kubernetes.io/name: octopus-deploy + helm.sh/chart: octopusdeploy-helm-1.11.1 + app.kubernetes.io/instance: octopus-deploy + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: octopus-server + spec: + serviceAccountName: default + containers: + - name: octopus + image: "docker.packages.octopushq.com/octopusdeploy/octopusdeploy:2026.2.4992-noamgal-yos-32-investigate-octopus-deploy-helm-chart-compatibility-with-linux" + securityContext: + env: + + - name: ACCEPT_EULA + value: "Y" + - name: OCTOPUS_SERVER_NODE_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: DB_CONNECTION_STRING + valueFrom: + secretKeyRef: + name: octopus-deploy-connectionstring + key: secret + - name: ADMIN_USERNAME + valueFrom: + secretKeyRef: + name: octopus-deploy-adminusername + key: secret + - name: ADMIN_PASSWORD + valueFrom: + secretKeyRef: + name: octopus-deploy-adminpassword + key: secret + - name: ADMIN_EMAIL + value: + - name: TASK_CAP + value: !!str + - name: OCTOPUS_SERVER_BASE64_LICENSE + # Your license key goes here. When using more than one node, a HA license is required. + # Without a HA license, the stateful set can have a replica count of 1. + valueFrom: + secretKeyRef: + name: octopus-deploy-licensekey + key: secret + - name: MASTER_KEY + valueFrom: + secretKeyRef: + name: octopus-deploy-masterkey + key: secret + - name: DISABLE_DIND + value: !!str "Y" + - name: OCTOPUS_INSTALLED_VIA_HELM + value: "true" + - name: OCTOPUS_GRPC_SERVICES_PORT + value: "8443" + ports: + - containerPort: 8080 + name: web + - containerPort: 10943 + name: tentacle + - containerPort: 8443 + name: grpcs + volumeMounts: + - name: package-repository-volume + mountPath: /repository + - name: artifacts-volume + mountPath: /artifacts + - name: task-log-volume + mountPath: /taskLogs + - name: server-log-volume + mountPath: /home/octopus/.octopus/OctopusServer/Server/Logs + - name: audit-log-volume + mountPath: /eventExports + readinessProbe: + exec: + command: + - /bin/bash + - -c + - URL=http://localhost:8080; response=$(/usr/bin/curl -k $URL/api/serverstatus/hosted/internal --write-out %{http_code} --silent --output /dev/null); /usr/bin/test "$response" -ge 200 && /usr/bin/test "$response" -le 299 || /usr/bin/test + initialDelaySeconds: 30 + periodSeconds: 30 + timeoutSeconds: 5 + failureThreshold: 60 + livenessProbe: + exec: + command: + - /bin/bash + - -c + - URL=http://localhost:8080; response=$(/usr/bin/curl -k $URL/api/octopusservernodes/ping --write-out %{http_code} --silent --output /dev/null); /usr/bin/test "$response" -ge 200 && /usr/bin/test "$response" -le 299 || /usr/bin/test "$response" -eq 418 + periodSeconds: 30 + timeoutSeconds: 5 + failureThreshold: 10 + startupProbe: + exec: + command: + - /bin/bash + - -c + - URL=http://localhost:8080; response=$(/usr/bin/curl -k $URL/api/octopusservernodes/ping --write-out %{http_code} --silent --output /dev/null); /usr/bin/test "$response" -ge 200 && /usr/bin/test "$response" -le 299 || /usr/bin/test "$response" -eq 418 + failureThreshold: 30 + periodSeconds: 60 + terminationGracePeriodSeconds: 10 + volumes: + - name: package-repository-volume + persistentVolumeClaim: + claimName: package-repository-claim + - name: artifacts-volume + persistentVolumeClaim: + claimName: artifacts-claim + - name: task-log-volume + persistentVolumeClaim: + claimName: task-log-claim + - name: audit-log-volume + persistentVolumeClaim: + claimName: audit-log-claim + volumeClaimTemplates: + - metadata: + name: server-log-volume + spec: + accessModes: [ "ReadWriteOnce" ] + resources: + requests: + storage: 200Mi diff --git a/charts/octopus-deploy/cluster-statefulset.yaml b/charts/octopus-deploy/cluster-statefulset.yaml new file mode 100644 index 00000000..f61f216a --- /dev/null +++ b/charts/octopus-deploy/cluster-statefulset.yaml @@ -0,0 +1,179 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + annotations: + meta.helm.sh/release-name: octopus-deploy + meta.helm.sh/release-namespace: octopus-deploy + creationTimestamp: "2026-04-09T12:42:43Z" + generation: 1 + labels: + app.kubernetes.io/instance: octopus-deploy + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: octopus-deploy + helm.sh/chart: octopusdeploy-helm-1.11.0 + name: octopus-deploy + namespace: octopus-deploy + resourceVersion: "19021723" + uid: 95d43143-cf37-4755-96e9-07f3a5da728e +spec: + persistentVolumeClaimRetentionPolicy: + whenDeleted: Retain + whenScaled: Retain + podManagementPolicy: OrderedReady + replicas: 1 + revisionHistoryLimit: 10 + selector: + matchLabels: + app.kubernetes.io/component: octopus-server + app.kubernetes.io/instance: octopus-deploy + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: octopus-deploy + helm.sh/chart: octopusdeploy-helm-1.11.0 + serviceName: octopus-deploy + template: + metadata: + creationTimestamp: null + labels: + app.kubernetes.io/component: octopus-server + app.kubernetes.io/instance: octopus-deploy + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: octopus-deploy + helm.sh/chart: octopusdeploy-helm-1.11.0 + spec: + containers: + - env: + - name: ACCEPT_EULA + value: "Y" + - name: OCTOPUS_SERVER_NODE_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: DB_CONNECTION_STRING + valueFrom: + secretKeyRef: + key: secret + name: octopus-deploy-connectionstring + - name: ADMIN_EMAIL + - name: TASK_CAP + - name: OCTOPUS_SERVER_BASE64_LICENSE + valueFrom: + secretKeyRef: + key: secret + name: octopus-deploy-licensekey + - name: MASTER_KEY + valueFrom: + secretKeyRef: + key: secret + name: octopus-deploy-masterkey + - name: DISABLE_DIND + value: "Y" + - name: OCTOPUS_INSTALLED_VIA_HELM + value: "true" + - name: OCTOPUS_GRPC_SERVICES_PORT + value: "8443" + image: docker.packages.octopushq.com/octopusdeploy/octopusdeploy:2026.2.4992-noamgal-yos-32-investigate-octopus-deploy-helm-chart-compatibility-with-linux + imagePullPolicy: IfNotPresent + livenessProbe: + exec: + command: + - /bin/bash + - -c + - URL=http://localhost:8080; response=$(/usr/bin/curl -k $URL/api/octopusservernodes/ping + --write-out %{http_code} --silent --output /dev/null); /usr/bin/test + "$response" -ge 200 && /usr/bin/test "$response" -le 299 || /usr/bin/test + "$response" -eq 418 + failureThreshold: 10 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 5 + name: octopus + ports: + - containerPort: 8080 + name: web + protocol: TCP + - containerPort: 10943 + name: tentacle + protocol: TCP + - containerPort: 8443 + name: grpc + protocol: TCP + readinessProbe: + exec: + command: + - /bin/bash + - -c + - URL=http://localhost:8080; response=$(/usr/bin/curl -k $URL/api/serverstatus/hosted/internal + --write-out %{http_code} --silent --output /dev/null); /usr/bin/test + "$response" -ge 200 && /usr/bin/test "$response" -le 299 || /usr/bin/test + failureThreshold: 60 + initialDelaySeconds: 30 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 5 + resources: {} + startupProbe: + exec: + command: + - /bin/bash + - -c + - URL=http://localhost:8080; response=$(/usr/bin/curl -k $URL/api/octopusservernodes/ping + --write-out %{http_code} --silent --output /dev/null); /usr/bin/test + "$response" -ge 200 && /usr/bin/test "$response" -le 299 || /usr/bin/test + "$response" -eq 418 + failureThreshold: 30 + periodSeconds: 60 + successThreshold: 1 + timeoutSeconds: 1 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /repository + name: package-repository-volume + - mountPath: /artifacts + name: artifacts-volume + - mountPath: /taskLogs + name: task-log-volume + - mountPath: /home/octopus/.octopus/OctopusServer/Server/Logs + name: server-log-volume + - mountPath: /eventExports + name: audit-log-volume + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + serviceAccount: default + serviceAccountName: default + terminationGracePeriodSeconds: 10 + volumes: + - name: package-repository-volume + persistentVolumeClaim: + claimName: package-repository-claim + - name: artifacts-volume + persistentVolumeClaim: + claimName: artifacts-claim + - name: task-log-volume + persistentVolumeClaim: + claimName: task-log-claim + - name: audit-log-volume + persistentVolumeClaim: + claimName: audit-log-claim + updateStrategy: + rollingUpdate: + partition: 0 + type: RollingUpdate + volumeClaimTemplates: + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + creationTimestamp: null + name: server-log-volume + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 200Mi + volumeMode: Filesystem + status: + phase: Pending diff --git a/charts/octopus-deploy/custom-values.yaml b/charts/octopus-deploy/custom-values.yaml new file mode 100644 index 00000000..52c8df90 --- /dev/null +++ b/charts/octopus-deploy/custom-values.yaml @@ -0,0 +1,13 @@ +mssql: + enabled: true + SA_PASSWORD: KOzoyi8d7UwuCtgOPoS3GRsfMe6w1zum +octopus: + acceptEula: "Y" + enableDockerInDocker: false + image: + repository: docker.packages.octopushq.com/octopusdeploy/octopusdeploy + tag: 2026.2.4992-noamgal-yos-32-investigate-octopus-deploy-helm-chart-compatibility-with-linux + masterKey: SyVzfGMxZnQncHBhajgyUw== + username: admin + password: Password01! + licenseKeyBase64: PExpY2Vuc2UgU2lnbmF0dXJlPSJLd0FxQUZaNFpKVzZtc0FReGJvSGhpdUtnT056NGlrWTdLc0FpSlhyMVZZVDFPS2lVcytNZi9tQUpnK2p0SFczV1MzNVhOS3B1eFZxd3JXUEtzeExaZz09Ij4KICA8TGljZW5zZUtleT4xMjU0NS01MjU0OS00NTQyMy02MjU3NTwvTGljZW5zZUtleT4KICA8VmVyc2lvbj4yLjA8IS0tIExpY2Vuc2UgU2NoZW1hIFZlcnNpb24gLS0+PC9WZXJzaW9uPgogIDxWYWxpZEZyb20+MjAyNS0wOC0xNDwvVmFsaWRGcm9tPgogIDxWYWxpZFRvPjIwMzAtMDEtMDI8L1ZhbGlkVG8+CiAgPEtpbmQ+U3Vic2NyaXB0aW9uPC9LaW5kPgogIDxNYWNoaW5lTGltaXQgVHlwZXM9IlRlbnRhY2xlUGFzc2l2ZSxUZW50YWNsZUFjdGl2ZSxTc2giPlVubGltaXRlZDwvTWFjaGluZUxpbWl0PgogIDxOb2RlTGltaXQ+VW5saW1pdGVkPC9Ob2RlTGltaXQ+CiAgPFByb2plY3RMaW1pdD5VbmxpbWl0ZWQ8L1Byb2plY3RMaW1pdD4KICA8VGVuYW50TGltaXQ+VW5saW1pdGVkPC9UZW5hbnRMaW1pdD4KICA8U3BhY2VMaW1pdD5VbmxpbWl0ZWQ8L1NwYWNlTGltaXQ+CiAgPFVzZXJMaW1pdD5VbmxpbWl0ZWQ8L1VzZXJMaW1pdD4KICA8V29ya2VyTGltaXQ+VW5saW1pdGVkPC9Xb3JrZXJMaW1pdD4KICA8RmVhdHVyZXM+CiAgICA8QXVkaXRMb2dGZWVkcz4KICAgICAgPFZhbGlkVG8+MjAyOS0xMi0zMTwvVmFsaWRUbz4KICAgIDwvQXVkaXRMb2dGZWVkcz4KICAgIDxKaXJhU2VydmljZU1hbmFnZW1lbnRJbnRlZ3JhdGlvbj4KICAgICAgPFZhbGlkVG8+MjAyOS0xMi0zMTwvVmFsaWRUbz4KICAgIDwvSmlyYVNlcnZpY2VNYW5hZ2VtZW50SW50ZWdyYXRpb24+CiAgICA8U2VydmljZU5vd0ludGVncmF0aW9uPgogICAgICA8VmFsaWRUbz4yMDI5LTEyLTMxPC9WYWxpZFRvPgogICAgPC9TZXJ2aWNlTm93SW50ZWdyYXRpb24+CiAgICA8SW5zaWdodHM+CiAgICAgIDxWYWxpZFRvPjIwMjktMTItMzE8L1ZhbGlkVG8+CiAgICA8L0luc2lnaHRzPgogICAgPFByaW9yaXR5VGFzaz4KICAgICAgPFZhbGlkVG8+MjAyOS0xMi0zMTwvVmFsaWRUbz4KICAgIDwvUHJpb3JpdHlUYXNrPgogICAgPEdsb2JhbERlcGxveW1lbnRGcmVlemU+CiAgICAgIDxWYWxpZFRvPjIwMjktMTItMzE8L1ZhbGlkVG8+CiAgICA8L0dsb2JhbERlcGxveW1lbnRGcmVlemU+CiAgICA8UHJvY2Vzc1RlbXBsYXRlcz4KICAgICAgPFZhbGlkVG8+MjAyOS0xMi0zMTwvVmFsaWRUbz4KICAgIDwvUHJvY2Vzc1RlbXBsYXRlcz4KICAgIDxQb2xpY2llcz4KICAgICAgPFZhbGlkVG8+MjAyOS0xMi0zMDwvVmFsaWRUbz4KICAgIDwvUG9saWNpZXM+CiAgICA8UHJvamVjdFRlbXBsYXRlcz4KICAgICAgPFZhbGlkVG8+MjAyOS0xMi0zMDwvVmFsaWRUbz4KICAgIDwvUHJvamVjdFRlbXBsYXRlcz4KICA8L0ZlYXR1cmVzPgo8L0xpY2Vuc2U+Cg== \ No newline at end of file diff --git a/charts/octopus-deploy/templates/_helpers.tpl b/charts/octopus-deploy/templates/_helpers.tpl index 918b6e68..59373994 100644 --- a/charts/octopus-deploy/templates/_helpers.tpl +++ b/charts/octopus-deploy/templates/_helpers.tpl @@ -36,7 +36,7 @@ Common Labels */}} {{- define "labels" -}} app.kubernetes.io/name: {{ include "octopus.name" . }} -helm.sh/chart: {{ include "octopus.chart" . }} +# helm.sh/chart: {{ include "octopus.chart" . }} app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/managed-by: {{ .Release.Service }} {{- end -}} From 279d64138d5cfb471a9b031ab9e467ca6108335c Mon Sep 17 00:00:00 2001 From: oleksandr-codefresh Date: Tue, 5 May 2026 09:32:44 +0300 Subject: [PATCH 2/9] server: added default securityContext to comply openshift restricted-v2 SCC --- charts/octopus-deploy/README.md | 35 +++++++++++++++---- .../charts/mssql/templates/_helpers.tpl | 8 +++++ .../mssql/templates/serviceaccount.yaml | 16 +++++++++ .../charts/mssql/templates/statefulset.yaml | 5 +++ .../octopus-deploy/charts/mssql/values.yaml | 18 +++++++++- .../octopus-deploy/values-rorfsexample.yaml | 10 ------ charts/octopus-deploy/values.yaml | 11 ++++-- 7 files changed, 84 insertions(+), 19 deletions(-) create mode 100644 charts/octopus-deploy/charts/mssql/templates/serviceaccount.yaml diff --git a/charts/octopus-deploy/README.md b/charts/octopus-deploy/README.md index be9c1b04..5d343135 100644 --- a/charts/octopus-deploy/README.md +++ b/charts/octopus-deploy/README.md @@ -147,13 +147,7 @@ A minimal set of writable paths for a read-only root filesystem is: ```yaml octopus: containerSecurityContext: - runAsNonRoot: true - runAsGroup: 999 - runAsUser: 999 readOnlyRootFilesystem: true - podSecurityContext: - fsGroup: 999 - fsGroupChangePolicy: OnRootMismatch serverConfigurationDirectory: /home/octopus/.local @@ -187,6 +181,35 @@ A complete working example including environment variable overrides for .NET too Note: `enableDockerInDocker` must be set to `false` when using a read-only root filesystem, as Docker-in-Docker requires a privileged, writable container. +### Openshift +If you are using build in mssql chart on Openshift with values: +``` +mssql: + enabled: true +``` + +Our mssql has such default security contexts for mssql. + +``` +podSecurityContext: + fsGroup: 10001 + seccompProfile: + type: RuntimeDefault +containerSecurityContext: + runAsUser: 10001 + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + add: + - NET_BIND_SERVICE +``` + +As we're usign hardcoded UID and fsGroup in our `securityContext` you need to assign `nonroot-v2` SCC to allow the SQL Server SA to run: + +```oc adm policy add-scc-to-user nonroot-v2 -z octopus-deploy-mssql -n octopus-deploy``` + + ### Ingress You'll likely want to allow external traffic to your Octopus instance, and this generally means configuring [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/). diff --git a/charts/octopus-deploy/charts/mssql/templates/_helpers.tpl b/charts/octopus-deploy/charts/mssql/templates/_helpers.tpl index 6f3d3493..b438d772 100644 --- a/charts/octopus-deploy/charts/mssql/templates/_helpers.tpl +++ b/charts/octopus-deploy/charts/mssql/templates/_helpers.tpl @@ -50,3 +50,11 @@ this template will return sa_password - either from values or autogenerated {{- include "random_secret" (list . "sapassword") -}} {{- end -}} {{- end -}} + +{{- define "mssql.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} +{{- default (printf "%s-mssql" (include "octopus.fullname" .)) .Values.serviceAccount.name -}} +{{- else -}} +default "default-mssql" .Values.serviceAccount.name +{{- end -}} +{{- end -}} diff --git a/charts/octopus-deploy/charts/mssql/templates/serviceaccount.yaml b/charts/octopus-deploy/charts/mssql/templates/serviceaccount.yaml new file mode 100644 index 00000000..93c4ae88 --- /dev/null +++ b/charts/octopus-deploy/charts/mssql/templates/serviceaccount.yaml @@ -0,0 +1,16 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + {{- include "labels" . | nindent 4 }} + {{- if .Values.serviceAccount.labels }} + {{- toYaml .Values.serviceAccount.labels | nindent 4 }} + {{- end }} + name: {{ template "mssql.serviceAccountName" . }} +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} +{{- end -}} \ No newline at end of file diff --git a/charts/octopus-deploy/charts/mssql/templates/statefulset.yaml b/charts/octopus-deploy/charts/mssql/templates/statefulset.yaml index ff3433cd..3bdbae30 100644 --- a/charts/octopus-deploy/charts/mssql/templates/statefulset.yaml +++ b/charts/octopus-deploy/charts/mssql/templates/statefulset.yaml @@ -19,6 +19,7 @@ spec: labels: {{- include "mssql.selectorLabels" . | nindent 8 }} spec: + serviceAccountName: {{ template "mssql.serviceAccountName" . }} securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} {{- with .Values.nodeSelector }} @@ -41,6 +42,10 @@ spec: - cp /var/opt/config/mssql.conf /var/opt/mssql/mssql.conf && /opt/mssql/bin/sqlservr image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- with .Values.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} ports: - containerPort: {{ .Values.containers.ports.containerPort}} env: diff --git a/charts/octopus-deploy/charts/mssql/values.yaml b/charts/octopus-deploy/charts/mssql/values.yaml index 850c6557..df8a9ad8 100644 --- a/charts/octopus-deploy/charts/mssql/values.yaml +++ b/charts/octopus-deploy/charts/mssql/values.yaml @@ -14,6 +14,22 @@ podAnnotations: {} podSecurityContext: fsGroup: 10001 + seccompProfile: + type: RuntimeDefault +containerSecurityContext: + runAsUser: 10001 + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + add: + - NET_BIND_SERVICE service: - port: 1433 \ No newline at end of file + port: 1433 + +serviceAccount: + create: true + automountServiceAccountToken: false + annotations: {} + labels: {} \ No newline at end of file diff --git a/charts/octopus-deploy/values-rorfsexample.yaml b/charts/octopus-deploy/values-rorfsexample.yaml index 75db98f2..28b02332 100644 --- a/charts/octopus-deploy/values-rorfsexample.yaml +++ b/charts/octopus-deploy/values-rorfsexample.yaml @@ -54,16 +54,6 @@ octopus: mountPath: /Octopus/.diagnostics sizeLimit: "100Mi" - podSecurityContext: - fsGroup: 999 - fsGroupChangePolicy: OnRootMismatch - - containerSecurityContext: - runAsNonRoot: true - runAsGroup: 999 - runAsUser: 999 - readOnlyRootFilesystem: true - serverConfigurationDirectory: /home/octopus/.local mssql: diff --git a/charts/octopus-deploy/values.yaml b/charts/octopus-deploy/values.yaml index 6526bb93..02019a9a 100644 --- a/charts/octopus-deploy/values.yaml +++ b/charts/octopus-deploy/values.yaml @@ -178,11 +178,18 @@ octopus: - watch - list # Pod security context settings - podSecurityContext: {} + podSecurityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault # Container security context settings # IMPORTANT: When enableDockerInDocker is true (default), the container must run as privileged. # If setting security contexts that conflict with privileged mode, set enableDockerInDocker to false. - containerSecurityContext: {} + containerSecurityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL # Custom directory for Octopus server configuration when using non-root security contexts serverConfigurationDirectory: From 435d9c6a868ee678df2183a3d5424f70777e5f13 Mon Sep 17 00:00:00 2001 From: oleksandr-codefresh Date: Tue, 5 May 2026 09:40:15 +0300 Subject: [PATCH 3/9] mssql: Ensure podSecurityContext enforces non-root user execution --- charts/octopus-deploy/charts/mssql/values.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/charts/octopus-deploy/charts/mssql/values.yaml b/charts/octopus-deploy/charts/mssql/values.yaml index df8a9ad8..d80aa30a 100644 --- a/charts/octopus-deploy/charts/mssql/values.yaml +++ b/charts/octopus-deploy/charts/mssql/values.yaml @@ -13,6 +13,7 @@ containers: podAnnotations: {} podSecurityContext: + runAsNonRoot: true fsGroup: 10001 seccompProfile: type: RuntimeDefault From f82ed56d3ed7092b715c91f33a3a5c5ee1ed0226 Mon Sep 17 00:00:00 2001 From: oleksandr-codefresh Date: Wed, 13 May 2026 13:23:06 +0300 Subject: [PATCH 4/9] Add tests for mssql service account creation and name resolution --- .../charts/mssql/templates/_helpers.tpl | 2 +- .../tests/mssql_serviceaccount_test.yaml | 109 ++++++++++++++++++ .../tests/mssql_serviceaccountname_test.yaml | 53 +++++++++ charts/octopus-deploy/tests/values/mssql.yaml | 2 + 4 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 charts/octopus-deploy/tests/mssql_serviceaccount_test.yaml create mode 100644 charts/octopus-deploy/tests/mssql_serviceaccountname_test.yaml create mode 100644 charts/octopus-deploy/tests/values/mssql.yaml diff --git a/charts/octopus-deploy/charts/mssql/templates/_helpers.tpl b/charts/octopus-deploy/charts/mssql/templates/_helpers.tpl index b438d772..3b111521 100644 --- a/charts/octopus-deploy/charts/mssql/templates/_helpers.tpl +++ b/charts/octopus-deploy/charts/mssql/templates/_helpers.tpl @@ -55,6 +55,6 @@ this template will return sa_password - either from values or autogenerated {{- if .Values.serviceAccount.create -}} {{- default (printf "%s-mssql" (include "octopus.fullname" .)) .Values.serviceAccount.name -}} {{- else -}} -default "default-mssql" .Values.serviceAccount.name +{{- required "A valid .Values.serviceAccount.name is required when .Values.serviceAccount.create is false" .Values.serviceAccount.name }} {{- end -}} {{- end -}} diff --git a/charts/octopus-deploy/tests/mssql_serviceaccount_test.yaml b/charts/octopus-deploy/tests/mssql_serviceaccount_test.yaml new file mode 100644 index 00000000..1133d593 --- /dev/null +++ b/charts/octopus-deploy/tests/mssql_serviceaccount_test.yaml @@ -0,0 +1,109 @@ +suite: mssql serviceaccount +templates: + - charts/mssql/templates/serviceaccount.yaml + +tests: + - it: renders by default + values: + - ./values/required.yaml + - ./values/mssql.yaml + asserts: + - hasDocuments: + count: 1 + - isKind: + of: ServiceAccount + documentIndex: 0 + + - it: does not render when create is false + values: + - ./values/required.yaml + - ./values/mssql.yaml + set: + mssql.serviceAccount.create: false + mssql.serviceAccount.name: "preexisting-sa" + asserts: + - hasDocuments: + count: 0 + + - it: uses generated default name when create is true and name is empty + values: + - ./values/required.yaml + - ./values/mssql.yaml + set: + mssql.serviceAccount.create: true + asserts: + - equal: + path: metadata.name + value: RELEASE-NAME-octopus-deploy-mssql + documentIndex: 0 + + - it: uses provided name when create is true and name is set + values: + - ./values/required.yaml + - ./values/mssql.yaml + set: + mssql.serviceAccount.create: true + mssql.serviceAccount.name: "custom-mssql-sa" + asserts: + - equal: + path: metadata.name + value: custom-mssql-sa + documentIndex: 0 + + - it: honors automountServiceAccountToken false by default + values: + - ./values/required.yaml + - ./values/mssql.yaml + asserts: + - equal: + path: automountServiceAccountToken + value: false + documentIndex: 0 + + - it: honors automountServiceAccountToken true when set + values: + - ./values/required.yaml + - ./values/mssql.yaml + set: + mssql.serviceAccount.automountServiceAccountToken: true + asserts: + - equal: + path: automountServiceAccountToken + value: true + documentIndex: 0 + + - it: labels are configurable + values: + - ./values/required.yaml + - ./values/mssql.yaml + set: + mssql.serviceAccount.labels: + label1: "example" + label2: "example2" + asserts: + - equal: + path: metadata.labels.label1 + value: "example" + documentIndex: 0 + - equal: + path: metadata.labels.label2 + value: "example2" + documentIndex: 0 + + - it: annotations are configurable + values: + - ./values/required.yaml + - ./values/mssql.yaml + set: + mssql.serviceAccount.annotations: + example.com/annotation: "example" + example.com/annotation2: "example2" + asserts: + - equal: + path: metadata.annotations["example.com/annotation"] + value: "example" + documentIndex: 0 + - equal: + path: metadata.annotations["example.com/annotation2"] + value: "example2" + documentIndex: 0 diff --git a/charts/octopus-deploy/tests/mssql_serviceaccountname_test.yaml b/charts/octopus-deploy/tests/mssql_serviceaccountname_test.yaml new file mode 100644 index 00000000..cb20d147 --- /dev/null +++ b/charts/octopus-deploy/tests/mssql_serviceaccountname_test.yaml @@ -0,0 +1,53 @@ +suite: mssql serviceAccountName resolution (statefulset) +templates: + - charts/mssql/templates/statefulset.yaml + +tests: + - it: statefulset uses default generated SA name when create is true and name is empty + values: + - ./values/required.yaml + - ./values/mssql.yaml + set: + mssql.serviceAccount.create: true + asserts: + - equal: + path: spec.template.spec.serviceAccountName + value: RELEASE-NAME-octopus-deploy-mssql + documentIndex: 0 + + - it: statefulset uses provided SA name when create is true + values: + - ./values/required.yaml + - ./values/mssql.yaml + set: + mssql.serviceAccount.create: true + mssql.serviceAccount.name: "custom-mssql-sa" + asserts: + - equal: + path: spec.template.spec.serviceAccountName + value: custom-mssql-sa + documentIndex: 0 + + - it: statefulset references preexisting SA when create is false and name is provided + values: + - ./values/required.yaml + - ./values/mssql.yaml + set: + mssql.serviceAccount.create: false + mssql.serviceAccount.name: "preexisting-sa" + asserts: + - equal: + path: spec.template.spec.serviceAccountName + value: preexisting-sa + documentIndex: 0 + + - it: rendering fails when create is false and name is empty + values: + - ./values/required.yaml + - ./values/mssql.yaml + set: + mssql.serviceAccount.create: false + mssql.serviceAccount.name: "" + asserts: + - failedTemplate: + errorMessage: "A valid .Values.serviceAccount.name is required when .Values.serviceAccount.create is false" diff --git a/charts/octopus-deploy/tests/values/mssql.yaml b/charts/octopus-deploy/tests/values/mssql.yaml new file mode 100644 index 00000000..20c9d228 --- /dev/null +++ b/charts/octopus-deploy/tests/values/mssql.yaml @@ -0,0 +1,2 @@ +mssql: + enabled: true \ No newline at end of file From 18c6897858c8a312518e85783d6a8571c5d01112 Mon Sep 17 00:00:00 2001 From: oleksandr-codefresh Date: Wed, 13 May 2026 17:09:05 +0300 Subject: [PATCH 5/9] restore previous values --- charts/octopus-deploy/values-rorfsexample.yaml | 10 ++++++++++ charts/octopus-deploy/values.yaml | 11 ++--------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/charts/octopus-deploy/values-rorfsexample.yaml b/charts/octopus-deploy/values-rorfsexample.yaml index 28b02332..75db98f2 100644 --- a/charts/octopus-deploy/values-rorfsexample.yaml +++ b/charts/octopus-deploy/values-rorfsexample.yaml @@ -54,6 +54,16 @@ octopus: mountPath: /Octopus/.diagnostics sizeLimit: "100Mi" + podSecurityContext: + fsGroup: 999 + fsGroupChangePolicy: OnRootMismatch + + containerSecurityContext: + runAsNonRoot: true + runAsGroup: 999 + runAsUser: 999 + readOnlyRootFilesystem: true + serverConfigurationDirectory: /home/octopus/.local mssql: diff --git a/charts/octopus-deploy/values.yaml b/charts/octopus-deploy/values.yaml index 02019a9a..6526bb93 100644 --- a/charts/octopus-deploy/values.yaml +++ b/charts/octopus-deploy/values.yaml @@ -178,18 +178,11 @@ octopus: - watch - list # Pod security context settings - podSecurityContext: - runAsNonRoot: true - seccompProfile: - type: RuntimeDefault + podSecurityContext: {} # Container security context settings # IMPORTANT: When enableDockerInDocker is true (default), the container must run as privileged. # If setting security contexts that conflict with privileged mode, set enableDockerInDocker to false. - containerSecurityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL + containerSecurityContext: {} # Custom directory for Octopus server configuration when using non-root security contexts serverConfigurationDirectory: From 8be7c8bd22d8dd45259a42254780ce89b021f362 Mon Sep 17 00:00:00 2001 From: oleksandr-codefresh Date: Wed, 13 May 2026 19:50:05 +0300 Subject: [PATCH 6/9] server docs: added strict security context section and openshift installation section --- charts/octopus-deploy/README.md | 112 ++++++++++++++++++++++---------- 1 file changed, 78 insertions(+), 34 deletions(-) diff --git a/charts/octopus-deploy/README.md b/charts/octopus-deploy/README.md index 5d343135..6e52adcf 100644 --- a/charts/octopus-deploy/README.md +++ b/charts/octopus-deploy/README.md @@ -66,7 +66,7 @@ If you ever need to create a new Octopus instance and wish to use keep all your By default, the master key is generated, stored in Kubernetes secret, and output when the Helm chart is installed. If you need to supply an existing master key this can be done as follows -``` +```yaml octopus: masterKey: ``` @@ -87,7 +87,7 @@ This default can be overridden in two ways. You can configure the storage class to be used for all three of the persistent volumes above (and for the SQL Server sub-chart if enabled) via: -``` +```yaml global: storageClass: "" ``` @@ -97,7 +97,7 @@ ReadWriteOnce or ReadWriteMany can be used for single node clusters. Alternatively, each volume may be configured individually. An example is shown below. -``` +```yaml octopus: packageRepositoryVolume: size: 20Gi @@ -131,8 +131,46 @@ octopus: sizeLimit: 10Gi # Set to some upper bound limit to protect from unbound usage ``` +## Strict Security Context / Non-root setup -### Read-Only Root Filesystem +#### Octopus Deploy Server +To run Server in non-root mode you need to use values: +```yaml +octopus: + enableDockerInDocker: false # required - otherwise Server will be running in privileged mode + podSecurityContext: + fsGroup: 999 + fsGroupChangePolicy: OnRootMismatch + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + containerSecurityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + runAsUser: 999 + runAsGroup: 999 +``` + +#### Built-in mssql +The built-in mssql chart ships with default security context values: +```yaml +podSecurityContext: + fsGroup: 10001 + seccompProfile: + type: RuntimeDefault +containerSecurityContext: + runAsUser: 10001 + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + add: + - NET_BIND_SERVICE +``` + +#### Read-Only Root Filesystem If your security policy requires a read-only root filesystem (`readOnlyRootFilesystem: true`), you must provide writable `emptyDir` mounts for the directories Octopus writes to at runtime. @@ -147,7 +185,13 @@ A minimal set of writable paths for a read-only root filesystem is: ```yaml octopus: containerSecurityContext: + runAsNonRoot: true + runAsGroup: 999 + runAsUser: 999 readOnlyRootFilesystem: true + podSecurityContext: + fsGroup: 999 + fsGroupChangePolicy: OnRootMismatch serverConfigurationDirectory: /home/octopus/.local @@ -181,33 +225,33 @@ A complete working example including environment variable overrides for .NET too Note: `enableDockerInDocker` must be set to `false` when using a read-only root filesystem, as Docker-in-Docker requires a privileged, writable container. -### Openshift -If you are using build in mssql chart on Openshift with values: -``` -mssql: - enabled: true -``` +## Openshift + +[Hardcoded UID and fsGroup](#strict-security-context) in our `securityContext` requires assigning `nonroot-v2` SCC to service accounts. -Our mssql has such default security contexts for mssql. +Installation steps are following: +1. create dedicated project (namespace) +```bash +NS_NAME="octopus-deploy" +oc new-project $NS_NAME --description="Octopus Deploy resources" --display-name="Octopus Deploy" ``` -podSecurityContext: - fsGroup: 10001 - seccompProfile: - type: RuntimeDefault -containerSecurityContext: - runAsUser: 10001 - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - add: - - NET_BIND_SERVICE +2. Assign `nonroot-v2` SCC to SAs +- Server +```bash +NS_NAME="octopus-deploy" +SERVER_SERVICE_ACCOUNT="default" +oc adm policy add-scc-to-user nonroot-v2 -z $SERVER_SERVICE_ACCOUNT -n $NS_NAME ``` +- Built-in mssql (if applicable) +```bash +NS_NAME="octopus-deploy" +MSSQL_SERVICE_ACCOUNT="octopus-deploy-mssql" +oc adm policy add-scc-to-user nonroot-v2 -z $MSSQL_SERVICE_ACCOUNT -n $NS_NAME +``` +3. run `helm install` command with extra values from [Strict Security Context](#strict-security-context) section. -As we're usign hardcoded UID and fsGroup in our `securityContext` you need to assign `nonroot-v2` SCC to allow the SQL Server SA to run: -```oc adm policy add-scc-to-user nonroot-v2 -z octopus-deploy-mssql -n octopus-deploy``` ### Ingress @@ -222,7 +266,7 @@ There are three types of traffic which you will typically want to configure ingr An example of a values file which configures ingress for HTTP traffic to the web portal and HTTP API using [NGINX](https://kubernetes.github.io/ingress-nginx/) is shown below: -``` +```yaml octopus: ingress: enabled: true @@ -235,7 +279,7 @@ octopus: To enable TLS in the ingress, you can create a certificate using cert-manager, and then reference it in the ingress configuration. An example is shown below: Certificate: -``` +```yaml apiVersion: cert-manager.io/v1 kind: Certificate metadata: @@ -251,7 +295,7 @@ spec: ``` Values file: -``` +```yaml octopus: ingress: enabled: true @@ -273,7 +317,7 @@ If the chart is configured to create a single Octopus node (`replicaCount: 1`) t The following configuration will create an ingress endpoint for each Octopus node (replica). -``` +```yaml octopus: ingress: enabled: true @@ -302,7 +346,7 @@ Octopus Server uses gRPC communication for the Kubernetes monitor. By default, O The Octopus Deploy service exposes this port for you by default. To allow external consumers of this service, you can either set this service to be a LoadBalancer, or use an ingress (or the Gateway API). Setting the service to be a Load Balancer can be done by setting the following in the values: -``` +```yaml octopus: service: type: LoadBalancer @@ -314,7 +358,7 @@ To pass through the default SSL certificate, you can use the `nginx.ingress.kube Note that to do this, you must [enable SSL passthrough in your nginx ingress controller](https://kubernetes.github.io/ingress-nginx/user-guide/tls/#ssl-passthrough). To enable passthrough, you can set the following in your values file: -``` +```yaml octopus: ingress: enabled: true @@ -333,7 +377,7 @@ octopus: ``` If you wish to terminate SSL rather than use passthrough, you must ensure that your certificate is issued by a CA that is generally trusted. Using a certificate from LetsEncrypt is the recommended way to do this. An example certificate would be: -``` +```yaml apiVersion: cert-manager.io/v1 kind: Certificate metadata: @@ -349,7 +393,7 @@ spec: ``` You can then set your ingress up as follows to enable the ingress: -``` +```yaml octopus: ingress: enabled: true @@ -370,7 +414,7 @@ octopus: ``` The resulting ingress will be as follows: -``` +```yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: From c99291f007a5fd9c3559b9ae07c8bdf0e4be98ea Mon Sep 17 00:00:00 2001 From: oleksandr-codefresh Date: Wed, 13 May 2026 19:55:26 +0300 Subject: [PATCH 7/9] fix(docs): update code block syntax highlighting in README.md --- charts/octopus-deploy/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/charts/octopus-deploy/README.md b/charts/octopus-deploy/README.md index 6e52adcf..f024dce3 100644 --- a/charts/octopus-deploy/README.md +++ b/charts/octopus-deploy/README.md @@ -12,7 +12,7 @@ If you are creating a long-lived, production Octopus instance we recommend you r Once you have your [license key](#license-key), you can run the command below to install Octopus Deploy: -``` +```bash helm upgrade octopus-deploy \ --install \ --namespace octopus-deploy \ @@ -43,7 +43,7 @@ The Quick Start installs SQL Server as a sub-chart. If you want to host SQL Server independently, you must supply the connection string: -``` +```yaml octopus: databaseConnectionString: ``` From c1bd80734a09be27f3c29e8160402d06a9f1a2f8 Mon Sep 17 00:00:00 2001 From: oleksandr-codefresh Date: Mon, 18 May 2026 08:14:35 +0300 Subject: [PATCH 8/9] fix title levels --- charts/octopus-deploy/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/charts/octopus-deploy/README.md b/charts/octopus-deploy/README.md index f024dce3..c0b3fcfa 100644 --- a/charts/octopus-deploy/README.md +++ b/charts/octopus-deploy/README.md @@ -131,7 +131,7 @@ octopus: sizeLimit: 10Gi # Set to some upper bound limit to protect from unbound usage ``` -## Strict Security Context / Non-root setup +### Strict Security Context / Non-root setup #### Octopus Deploy Server To run Server in non-root mode you need to use values: @@ -225,7 +225,7 @@ A complete working example including environment variable overrides for .NET too Note: `enableDockerInDocker` must be set to `false` when using a read-only root filesystem, as Docker-in-Docker requires a privileged, writable container. -## Openshift +### Openshift [Hardcoded UID and fsGroup](#strict-security-context) in our `securityContext` requires assigning `nonroot-v2` SCC to service accounts. From 16a5ae542bf0e8dd7aff4bf79bccf5577306cf9b Mon Sep 17 00:00:00 2001 From: oleksandr-codefresh Date: Mon, 18 May 2026 08:46:25 +0300 Subject: [PATCH 9/9] Server values: removed runAsNonRoot: true --- charts/octopus-deploy/charts/mssql/values.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/charts/octopus-deploy/charts/mssql/values.yaml b/charts/octopus-deploy/charts/mssql/values.yaml index d80aa30a..df8a9ad8 100644 --- a/charts/octopus-deploy/charts/mssql/values.yaml +++ b/charts/octopus-deploy/charts/mssql/values.yaml @@ -13,7 +13,6 @@ containers: podAnnotations: {} podSecurityContext: - runAsNonRoot: true fsGroup: 10001 seccompProfile: type: RuntimeDefault