diff --git a/ci/matrix-synapse/fixtures.yaml b/ci/matrix-synapse/fixtures.yaml index fb5d192..a6ef53c 100644 --- a/ci/matrix-synapse/fixtures.yaml +++ b/ci/matrix-synapse/fixtures.yaml @@ -40,7 +40,7 @@ spec: containers: - name: generate # Same image the chart deploys (appVersion of matrix-synapse). - image: ghcr.io/element-hq/synapse:v1.149.1 + image: ghcr.io/element-hq/synapse:v1.159.0 args: ["generate"] env: - name: SYNAPSE_SERVER_NAME diff --git a/ci/matrix-synapse/test-values.yaml b/ci/matrix-synapse/test-values.yaml index 622c13b..1657582 100644 --- a/ci/matrix-synapse/test-values.yaml +++ b/ci/matrix-synapse/test-values.yaml @@ -1,6 +1,8 @@ +secrets: + configSecretRef: op://ci/matrix-synapse-config + matrix: serverName: synapse.ci.local - configSecretRef: op://ci/matrix-synapse-config delegation: enabled: true serverUrl: ci.local diff --git a/matrix-synapse/Chart.yaml b/matrix-synapse/Chart.yaml index c5e6b12..7af98eb 100644 --- a/matrix-synapse/Chart.yaml +++ b/matrix-synapse/Chart.yaml @@ -3,7 +3,7 @@ name: matrix-synapse description: A Helm chart to deploy a Matrix Synapse server on Kubernetes icon: https://raw.githubusercontent.com/element-hq/synapse/develop/docs/favicon.png type: application -version: 4.2.1+upv1.159.0 +version: 5.0.0+upv1.159.0 appVersion: "v1.159.0" maintainers: - name: jklein \ No newline at end of file diff --git a/matrix-synapse/templates/matrix-delegation-nginx.configmap.yaml b/matrix-synapse/templates/matrix-delegation-nginx.configmap.yaml index ddafd98..1e86398 100644 --- a/matrix-synapse/templates/matrix-delegation-nginx.configmap.yaml +++ b/matrix-synapse/templates/matrix-delegation-nginx.configmap.yaml @@ -2,7 +2,7 @@ apiVersion: v1 kind: ConfigMap metadata: - name: {{ .Release.Name }}-{{ .Chart.Name }}-delegation-nginx-config + name: {{ .Release.Name }}-{{ .Chart.Name }}-delegation-nginx-configmap data: nginx.conf: | worker_processes 1; diff --git a/matrix-synapse/templates/matrix-delegation-nginx.deployment.yaml b/matrix-synapse/templates/matrix-delegation-nginx.deployment.yaml index da3717a..3934c0c 100644 --- a/matrix-synapse/templates/matrix-delegation-nginx.deployment.yaml +++ b/matrix-synapse/templates/matrix-delegation-nginx.deployment.yaml @@ -2,18 +2,18 @@ apiVersion: apps/v1 kind: Deployment metadata: - name: {{ .Release.Name }}-{{ .Chart.Name }}-delegation-nginx + name: {{ .Release.Name }}-{{ .Chart.Name }}-delegation-nginx-deployment labels: - app: {{ .Release.Name }}-{{ .Chart.Name }}-delegation-nginx + app: {{ .Release.Name }}-{{ .Chart.Name }}-delegation-nginx-deployment spec: replicas: {{ include "matrix-synapse.replicas" (dict "scaleDown" .Values.scaleDown "replicas" .Values.matrix.delegation.replicas) }} selector: matchLabels: - app: {{ .Release.Name }}-{{ .Chart.Name }}-delegation-nginx + app: {{ .Release.Name }}-{{ .Chart.Name }}-delegation-nginx-deployment template: metadata: labels: - app: {{ .Release.Name }}-{{ .Chart.Name }}-delegation-nginx + app: {{ .Release.Name }}-{{ .Chart.Name }}-delegation-nginx-deployment spec: automountServiceAccountToken: false securityContext: @@ -38,37 +38,18 @@ spec: resources: {{- include "matrix-synapse.resources" .Values.matrix.delegation.resources | nindent 12 }} readinessProbe: - httpGet: - path: /.well-known/matrix/server - port: http - scheme: HTTP - periodSeconds: 10 - timeoutSeconds: 3 - failureThreshold: 3 + {{- toYaml .Values.matrix.delegation.readinessProbe | nindent 12 }} livenessProbe: - httpGet: - path: /.well-known/matrix/server - port: http - scheme: HTTP - periodSeconds: 10 - timeoutSeconds: 3 - failureThreshold: 3 - # The startup probe gates liveness/readiness. Startup budget = 5s * 30 = 150s. + {{- toYaml .Values.matrix.delegation.livenessProbe | nindent 12 }} startupProbe: - httpGet: - path: /.well-known/matrix/server - port: http - scheme: HTTP - periodSeconds: 5 - timeoutSeconds: 3 - failureThreshold: 30 + {{- toYaml .Values.matrix.delegation.startupProbe | nindent 12 }} volumes: - name: tmp emptyDir: {} - name: nginx-config configMap: - name: {{ .Release.Name }}-{{ .Chart.Name }}-delegation-nginx-config + name: {{ .Release.Name }}-{{ .Chart.Name }}-delegation-nginx-configmap items: - key: nginx.conf path: nginx.conf -{{- end }} \ No newline at end of file +{{- end }} diff --git a/matrix-synapse/templates/matrix-delegation-nginx.service.yaml b/matrix-synapse/templates/matrix-delegation-nginx.service.yaml index c644e95..c8ac50a 100644 --- a/matrix-synapse/templates/matrix-delegation-nginx.service.yaml +++ b/matrix-synapse/templates/matrix-delegation-nginx.service.yaml @@ -5,7 +5,7 @@ metadata: name: {{ .Release.Name }}-{{ .Chart.Name }}-delegation-service spec: selector: - app: {{ .Release.Name }}-{{ .Chart.Name }}-delegation-nginx + app: {{ .Release.Name }}-{{ .Chart.Name }}-delegation-nginx-deployment ports: - protocol: TCP port: 80 diff --git a/matrix-synapse/templates/matrix-synapse-config.secret.yaml b/matrix-synapse/templates/matrix-synapse-config.secret.yaml index c48c1af..bd33c03 100644 --- a/matrix-synapse/templates/matrix-synapse-config.secret.yaml +++ b/matrix-synapse/templates/matrix-synapse-config.secret.yaml @@ -3,4 +3,4 @@ kind: OnePasswordItem metadata: name: {{ .Release.Name }}-{{ .Chart.Name }}-config-secret spec: - itemPath: {{ required "You must provide a configSecret Reference" .Values.matrix.configSecretRef }} + itemPath: {{ required "You must provide a configSecret Reference" .Values.secrets.configSecretRef }} diff --git a/matrix-synapse/templates/matrix-synapse.ingress.yaml b/matrix-synapse/templates/matrix-synapse.ingress.yaml index 893aa69..9e0ea7b 100644 --- a/matrix-synapse/templates/matrix-synapse.ingress.yaml +++ b/matrix-synapse/templates/matrix-synapse.ingress.yaml @@ -4,8 +4,11 @@ metadata: name: {{ .Release.Name }}-{{ .Chart.Name }}-ingress annotations: cert-manager.io/cluster-issuer: {{ required "A Cluster-Issuer must be provided" .Values.ingress.clusterIssuer }} + {{- with .Values.ingress.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} spec: - ingressClassName: nginx + ingressClassName: {{ .Values.ingress.className }} rules: - host: {{ required "A Domain/Host must be provided" .Values.ingress.domain }} http: diff --git a/matrix-synapse/templates/matrix-synapse.sfs.yaml b/matrix-synapse/templates/matrix-synapse.sfs.yaml index eade2d5..b72436e 100644 --- a/matrix-synapse/templates/matrix-synapse.sfs.yaml +++ b/matrix-synapse/templates/matrix-synapse.sfs.yaml @@ -18,52 +18,49 @@ spec: spec: automountServiceAccountToken: false securityContext: - fsGroup: 1000 - fsGroupChangePolicy: Always + {{- toYaml .Values.matrix.securityContext.pod | nindent 8 }} containers: - name: "{{ .Release.Name }}-{{ .Chart.Name }}-container" image: "ghcr.io/element-hq/synapse:{{ .Chart.AppVersion }}" + securityContext: + {{- toYaml .Values.matrix.securityContext.container | nindent 12 }} env: - name: SYNAPSE_SERVER_NAME value: "{{ required "You must provide a Server-Name" .Values.matrix.serverName }}" - name: SYNAPSE_REPORT_STATS value: "no" - - name: UID - value: "1000" - - name: GID - value: "1000" - name: TZ value: "{{ .Values.matrix.timezone }}" + {{- range $value := .Values.matrix.env }} + {{- if $value.value }} + - name: {{ $value.name }} + value: {{ tpl $value.value $ }} + {{- else if $value.valueFrom }} + {{- if $value.valueFrom.secretKeyRef }} + - name: {{ $value.name }} + valueFrom: + secretKeyRef: + name: {{ tpl $value.valueFrom.secretKeyRef.name $ }} + key: {{ tpl $value.valueFrom.secretKeyRef.key $ }} + {{- else if $value.valueFrom.configMapKeyRef }} + - name: {{ $value.name }} + valueFrom: + configMapKeyRef: + name: {{ tpl $value.valueFrom.configMapKeyRef.name $ }} + key: {{ tpl $value.valueFrom.configMapKeyRef.key $ }} + {{- end }} + {{- end }} + {{- end }} ports: - name: http containerPort: 8008 protocol: TCP readinessProbe: - httpGet: - path: /health - port: http - scheme: HTTP - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 3 + {{- toYaml .Values.matrix.readinessProbe | nindent 12 }} livenessProbe: - httpGet: - path: /health - port: http - scheme: HTTP - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 3 - # The startup probe gates liveness/readiness. Synapse can take a - # while to start (migrations, cache warmup): budget 10s * 30 = 300s. + {{- toYaml .Values.matrix.livenessProbe | nindent 12 }} startupProbe: - httpGet: - path: /health - port: http - scheme: HTTP - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 30 + {{- toYaml .Values.matrix.startupProbe | nindent 12 }} resources: {{- include "matrix-synapse.resources" .Values.matrix.resources | nindent 12 }} volumeMounts: @@ -76,7 +73,13 @@ spec: - name: matrix-synapse-config-secret mountPath: /data/homeserver.yaml subPath: homeserver.yaml + # Scratch space so the read-only root filesystem never blocks + # temp-file writes (e.g. URL-preview downloads). + - name: tmp + mountPath: /tmp volumes: + - name: tmp + emptyDir: {} - name: matrix-synapse-volume persistentVolumeClaim: claimName: {{ .Release.Name }}-{{ .Chart.Name }}-pvc diff --git a/matrix-synapse/values.yaml b/matrix-synapse/values.yaml index 1cad93d..0375764 100644 --- a/matrix-synapse/values.yaml +++ b/matrix-synapse/values.yaml @@ -4,13 +4,75 @@ # Services stay in place; scaleDown: false brings the workloads back up. scaleDown: false +secrets: + configSecretRef: null + matrix: # Replica count for this workload; 0 is allowed and scales it down. # The chart-global scaleDown flag takes precedence. replicas: 1 serverName: null timezone: UTC - configSecretRef: null + # The upstream image (ghcr.io/element-hq/synapse) only drops privileges + # itself (via gosu, driven by UID/GID env vars) when started as root; with + # an explicit non-root runAsUser it skips that step and runs directly as + # that user. Synapse writes to /data and /media_store (both on the PVC) and + # to /tmp (mounted as an emptyDir by the chart), so the root filesystem + # stays read-only. The uid/gid 1000 matches the previous gosu default, so + # existing PVC data stays accessible. + securityContext: + pod: + runAsNonRoot: true + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + fsGroupChangePolicy: Always + container: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + capabilities: + drop: + - ALL + livenessProbe: + httpGet: + path: /health + port: http + scheme: HTTP + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /health + port: http + scheme: HTTP + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + # The startup probe gates liveness/readiness. Synapse can take a + # while to start (migrations, cache warmup): budget 10s * 30 = 300s. + startupProbe: + httpGet: + path: /health + port: http + scheme: HTTP + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 30 + # Extra environment variables, appended to the ones the chart always sets. + # Values are rendered through tpl; value, secretKeyRef and configMapKeyRef + # forms are supported. + env: [] + resources: + # Limits are optional: memory and ephemeral-storage limits default to + # limitFactor x the request, an explicitly set limit always wins, and a + # CPU limit is only set when configured explicitly under "limits". + limitFactor: 3 + requests: + memory: "1Gi" + cpu: "1" + ephemeralStorage: "1Gi" delegation: # Replica count for this workload; 0 is allowed and scales it down. # The chart-global scaleDown flag takes precedence. @@ -37,6 +99,31 @@ matrix: capabilities: drop: - ALL + livenessProbe: + httpGet: + path: /.well-known/matrix/server + port: http + scheme: HTTP + periodSeconds: 10 + timeoutSeconds: 3 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /.well-known/matrix/server + port: http + scheme: HTTP + periodSeconds: 10 + timeoutSeconds: 3 + failureThreshold: 3 + # The startup probe gates liveness/readiness. Startup budget = 5s * 30 = 150s. + startupProbe: + httpGet: + path: /.well-known/matrix/server + port: http + scheme: HTTP + periodSeconds: 5 + timeoutSeconds: 3 + failureThreshold: 30 resources: # Limits are optional: memory and ephemeral-storage limits default to # limitFactor x the request, an explicitly set limit always wins, and a @@ -46,15 +133,6 @@ matrix: memory: "64Mi" cpu: "125m" ephemeralStorage: "50Mi" - resources: - # Limits are optional: memory and ephemeral-storage limits default to - # limitFactor x the request, an explicitly set limit always wins, and a - # CPU limit is only set when configured explicitly under "limits". - limitFactor: 3 - requests: - memory: "1Gi" - cpu: "1" - ephemeralStorage: "1Gi" storage: amount: 10Gi @@ -63,3 +141,7 @@ storage: ingress: domain: null clusterIssuer: null + className: nginx + # Extra annotations for the Ingress; merged with the cert-manager + # cluster-issuer annotation the chart always sets. + annotations: {}