diff --git a/.github/workflows/test-chart.yml b/.github/workflows/test-chart.yml index a4482b6..3e02fc6 100644 --- a/.github/workflows/test-chart.yml +++ b/.github/workflows/test-chart.yml @@ -76,7 +76,10 @@ jobs: # higher. # - k3s-channel: v1.21 - helm-version: v3.6.0 + helm-version: v3.8.0 + + env: + HELM_EXPERIMENTAL_OCI: "1" steps: - uses: actions/checkout@v3 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ee3892e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +charts/ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..2b6c100 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,108 @@ +# 5.1.0 + +- Added values for Active Record Encryption in Redis: + ```yaml + mastodon: + secrets: + activeRecordEncryption: + primaryKey: + deterministicKey: + keyDerivationSalt: + ``` + +- Small bugfix related to automatic secret generation + +# [5.0.0](https://github.com/mastodon/chart/commit/63a052b6a5c19dabd172c15c1fd74298dcc544b2) + +- Updated major versions of chart dependencies (postgres, redis, elasticsearch) + +# [4.0.0](https://github.com/mastodon/chart/compare/920cf37..ae892d5) + +- adds support for multiple Sidekiq deployments to be configured to manage + different sets of queues. + +- smtp: replaces `enable_starttls_auto` boolean with `enable_starttls` setting + that defaults to `auto`. + +- adds support for statsd publishing: + ``` + mastodon: + metrics: + statsd: + address: + ``` + +- allows disabling the included redis deployment in order to use an existing external redis server: + ``` + redis: + enabled: false + ``` + +- adds support for [authorized + fetch](https://docs.joinmastodon.org/admin/config/#authorized_fetch): + ``` + mastodon: + authorizedFetch: true + ``` + +- removed the `HorizontalPodAutoscaler` and the global autoscaling configuration. + +A number of other configuration options have been added, see [values.yaml](./values.yaml). + +# 3.0.0 + +skipped + +# 2.1.0 + +## ingressClassName and tls-acme changes +The annotations previously defaulting to nginx have been removed and support + for ingressClassName has been added. +```yaml +ingress: + annotations: + kubernetes.io/ingress.class: nginx + kubernetes.io/tls-acme: "true" +``` + +To restore the old functionality simply add the above snippet to your `values.yaml`, +but the recommendation is to replace these with `ingress.ingressClassName` and use +cert-manager's issuer/cluster-issuer instead of tls-acme. +If you're uncertain about your current setup leave `ingressClassName` empty and add +`kubernetes.io/tls-acme` to `ingress.annotations` in your `values.yaml`. + +# 2.0.0 + +## Fixed labels +Because of the changes in [#19706](https://github.com/mastodon/mastodon/pull/19706) the upgrade may fail with the following error: +```Error: UPGRADE FAILED: cannot patch "mastodon-sidekiq"``` + +If you want an easy upgrade and you're comfortable with some downtime then +simply delete the -sidekiq, -web, and -streaming Deployments manually. + +If you require a no-downtime upgrade then: +1. run `helm template` instead of `helm upgrade` +2. Copy the new -web and -streaming services into `services.yml` +3. Copy the new -web and -streaming deployments into `deployments.yml` +4. Append -temp to the name of each deployment in `deployments.yml` +5. `kubectl apply -f deployments.yml` then wait until all pods are ready +6. `kubectl apply -f services.yml` +7. Delete the old -sidekiq, -web, and -streaming deployments manually +8. `helm upgrade` like normal +9. `kubectl delete -f deployments.yml` to clear out the temporary deployments + +## PostgreSQL passwords +If you've previously installed the chart and you're having problems with +postgres not accepting your password then make sure to set `username` to +`postgres` and `password` and `postgresPassword` to the same passwords. +```yaml +postgresql: + auth: + username: postgres + password: + postgresPassword: +``` + +And make sure to set `password` to the same value as `postgres-password` +in your `mastodon-postgresql` secret: +```kubectl edit secret mastodon-postgresql``` diff --git a/Chart.lock b/Chart.lock index 961e4fa..e985f1a 100644 --- a/Chart.lock +++ b/Chart.lock @@ -1,12 +1,12 @@ dependencies: - name: elasticsearch - repository: https://raw.githubusercontent.com/bitnami/charts/archive-full-index/bitnami - version: 19.0.1 + repository: oci://registry-1.docker.io/bitnamicharts + version: 19.19.2 - name: postgresql - repository: https://raw.githubusercontent.com/bitnami/charts/archive-full-index/bitnami - version: 11.1.3 + repository: oci://registry-1.docker.io/bitnamicharts + version: 14.2.3 - name: redis - repository: https://raw.githubusercontent.com/bitnami/charts/archive-full-index/bitnami - version: 16.13.2 -digest: sha256:17ea58a3264aa22faff18215c4269f47dabae956d0df273c684972f356416193 -generated: "2022-08-08T21:44:18.0195364+02:00" + repository: oci://registry-1.docker.io/bitnamicharts + version: 18.16.1 +digest: sha256:684daaf2067d96e2aa6d93e9d29b7b13fc586f6ae929342e5e9c7c169b1c0748 +generated: "2024-02-23T15:14:47.536480528-08:00" diff --git a/Chart.yaml b/Chart.yaml index 1ebc973..2ee7189 100644 --- a/Chart.yaml +++ b/Chart.yaml @@ -12,26 +12,26 @@ description: Mastodon is a free, open-source social network server based on Acti # pipeline. Library charts do not define any templates and therefore cannot be deployed. type: application -# This is the chart version. This version number should be incremented each time you make changes -# to the chart and its templates, including the app version. +# This is the chart version. This version number should be incremented each time +# you make changes to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 4.0.0 +version: 5.1.1 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. -appVersion: v4.0.2 +appVersion: v4.2.8 dependencies: - name: elasticsearch - version: 19.0.1 - repository: https://raw.githubusercontent.com/bitnami/charts/archive-full-index/bitnami + version: 19.19.2 + repository: oci://registry-1.docker.io/bitnamicharts condition: elasticsearch.enabled - name: postgresql - version: 11.1.3 - repository: https://raw.githubusercontent.com/bitnami/charts/archive-full-index/bitnami + version: 14.2.3 + repository: oci://registry-1.docker.io/bitnamicharts condition: postgresql.enabled - name: redis - version: 16.13.2 - repository: https://raw.githubusercontent.com/bitnami/charts/archive-full-index/bitnami + version: 18.16.1 + repository: oci://registry-1.docker.io/bitnamicharts condition: redis.enabled diff --git a/README.md b/README.md index 53f9599..35303c0 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,18 @@ This is a [Helm](https://helm.sh/) chart for installing Mastodon into a Kubernetes cluster. The basic usage is: 1. edit `values.yaml` or create a separate yaml file for custom values -1. `helm dep update` +1. `helm dep install` 1. `helm install --namespace mastodon --create-namespace my-mastodon ./ -f path/to/additional/values.yaml` -This chart is tested with k8s 1.21+ and helm 3.6.0+. +This chart is tested with k8s 1.21+ and helm 3.8.0+. + +# NOTICE: Future Deprecation + +We have plans in the very near future to deprecate this chart in favor of a [new git repo](https://github.com/mastodon/helm-charts), which has proper helm repository support (e.g. `helm repo add`), and will contain multiple charts, both for mastodon and for supplementary components that we make use of. + +We still encourage suggestions and PRs to help make this chart better, and this repository will remain available after the new charts are ready to give users time to migrate. However, we will not be approving large PRs, or PRs that change fundamental chart functions, as those changes should be directed to the new charts. + +Please see the pinned [GitHub issue](https://github.com/mastodon/chart/issues/129) for more info & discussion. # Configuration @@ -64,57 +72,3 @@ Sidekiq deployments, it’s possible they will occur in the wrong order. After upgrading Mastodon versions, it may sometimes be necessary to manually delete the Rails and Sidekiq pods so that they are recreated against the latest migration. - -# Upgrades in 2.1.0 - -## ingressClassName and tls-acme changes -The annotations previously defaulting to nginx have been removed and support - for ingressClassName has been added. -```yaml -ingress: - annotations: - kubernetes.io/ingress.class: nginx - kubernetes.io/tls-acme: "true" -``` - -To restore the old functionality simply add the above snippet to your `values.yaml`, -but the recommendation is to replace these with `ingress.ingressClassName` and use -cert-manager's issuer/cluster-issuer instead of tls-acme. -If you're uncertain about your current setup leave `ingressClassName` empty and add -`kubernetes.io/tls-acme` to `ingress.annotations` in your `values.yaml`. - -# Upgrades in 2.0.0 - -## Fixed labels -Because of the changes in [#19706](https://github.com/mastodon/mastodon/pull/19706) the upgrade may fail with the following error: -```Error: UPGRADE FAILED: cannot patch "mastodon-sidekiq"``` - -If you want an easy upgrade and you're comfortable with some downtime then -simply delete the -sidekiq, -web, and -streaming Deployments manually. - -If you require a no-downtime upgrade then: -1. run `helm template` instead of `helm upgrade` -2. Copy the new -web and -streaming services into `services.yml` -3. Copy the new -web and -streaming deployments into `deployments.yml` -4. Append -temp to the name of each deployment in `deployments.yml` -5. `kubectl apply -f deployments.yml` then wait until all pods are ready -6. `kubectl apply -f services.yml` -7. Delete the old -sidekiq, -web, and -streaming deployments manually -8. `helm upgrade` like normal -9. `kubectl delete -f deployments.yml` to clear out the temporary deployments - -## PostgreSQL passwords -If you've previously installed the chart and you're having problems with -postgres not accepting your password then make sure to set `username` to -`postgres` and `password` and `postgresPassword` to the same passwords. -```yaml -postgresql: - auth: - username: postgres - password: - postgresPassword: -``` - -And make sure to set `password` to the same value as `postgres-password` -in your `mastodon-postgresql` secret: -```kubectl edit secret mastodon-postgresql``` \ No newline at end of file diff --git a/dev-values.yaml b/dev-values.yaml index f4e5330..86ca98a 100644 --- a/dev-values.yaml +++ b/dev-values.yaml @@ -7,6 +7,11 @@ mastodon: vapid: private_key: dummy-vapid-private_key public_key: dummy-vapid-public_key + activeRecordEncryption: + primaryKey: dummy-are-primary_key + deterministicKey: dummy-are-deterministic_key + keyDerivationSalt: dummy-are-key_derivation_salt + # ref: https://github.com/bitnami/charts/tree/main/bitnami/redis#parameters redis: diff --git a/templates/_helpers.tpl b/templates/_helpers.tpl index 0e1804f..81872f9 100644 --- a/templates/_helpers.tpl +++ b/templates/_helpers.tpl @@ -31,12 +31,22 @@ Create chart name and version as used by the chart label. {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} {{- end }} +{{/* +Labels added on every Mastodon resource +*/}} +{{- define "mastodon.globalLabels" -}} +{{- range $k, $v := .Values.mastodon.labels }} +{{ $k }}: {{ quote $v }} +{{- end -}} +{{- end }} + {{/* Common labels */}} {{- define "mastodon.labels" -}} helm.sh/chart: {{ include "mastodon.chart" . }} {{ include "mastodon.selectorLabels" . }} +{{ include "mastodon.globalLabels" . }} {{- if .Chart.AppVersion }} app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} {{- end }} @@ -55,7 +65,9 @@ app.kubernetes.io/instance: {{ .Release.Name }} Rolling pod annotations */}} {{- define "mastodon.rollingPodAnnotations" -}} +{{- if .Values.revisionPodAnnotation }} rollme: {{ .Release.Revision | quote }} +{{- end }} checksum/config-secrets: {{ include ( print $.Template.BasePath "/secrets.yaml" ) . | sha256sum | quote }} checksum/config-configmap: {{ include ( print $.Template.BasePath "/configmap-env.yaml" ) . | sha256sum | quote }} {{- end }} @@ -94,7 +106,18 @@ Get the mastodon secret. {{- if .Values.mastodon.secrets.existingSecret }} {{- printf "%s" (tpl .Values.mastodon.secrets.existingSecret $) -}} {{- else -}} - {{- printf "%s" (include "common.names.fullname" .) -}} + {{- printf "%s" (include "mastodon.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Get the smtp secret. +*/}} +{{- define "mastodon.smtp.secretName" -}} +{{- if .Values.mastodon.smtp.existingSecret }} + {{- printf "%s" (tpl .Values.mastodon.smtp.existingSecret $) -}} +{{- else -}} + {{- printf "%s-smtp" (include "mastodon.fullname" .) -}} {{- end -}} {{- end -}} @@ -107,7 +130,7 @@ Get the postgresql secret. {{- else if .Values.postgresql.enabled -}} {{- printf "%s-postgresql" (tpl .Release.Name $) -}} {{- else -}} - {{- printf "%s" (include "common.names.fullname" .) -}} + {{- printf "%s" (include "mastodon.fullname" .) -}} {{- end -}} {{- end -}} @@ -148,3 +171,16 @@ Find highest number of needed database connections to set DB_POOL variable {{- end }} {{- $poolSize | quote }} {{- end }} + +{{/* +Full hostname for a custom Elasticsearch cluster +*/}} +{{- define "mastodon.elasticsearch.fullHostname" -}} +{{- if not .Values.elasticsearch.enabled }} + {{- if .Values.elasticsearch.tls }} + {{- printf "https://%s" (tpl .Values.elasticsearch.hostname $) -}} + {{- else -}} + {{- printf "%s" (tpl .Values.elasticsearch.hostname $) -}} + {{- end }} +{{- end -}} +{{- end -}} diff --git a/templates/_statsd.yaml b/templates/_statsd.yaml new file mode 100644 index 0000000..410e4f1 --- /dev/null +++ b/templates/_statsd.yaml @@ -0,0 +1,54 @@ +{{/* + The exporter container attached to every Mastodon pod +*/}} + +{{- define "mastodon.statsdExporterContainer" }} +{{- with .Values.mastodon.metrics.statsd }} +{{- if and .exporter.enabled (not .address) }} +- name: statsd-exporter + image: prom/statsd-exporter + args: + - "--statsd.mapping-config=/statsd-mappings/mastodon.yml" + resources: + requests: + cpu: "0.1" + memory: "180M" + limits: + cpu: "0.5" + memory: "250M" + ports: + - name: statsd + containerPort: {{ .exporter.port }} + volumeMounts: + - name: statsd-mappings + mountPath: /statsd-mappings +{{- end }} +{{- end }} +{{- end }} + +{{/* + The volume needed for the container above +*/}} +{{- define "mastodon.statsdExporterVolume" }} +{{- with .Values.mastodon.metrics.statsd }} +{{- if and .exporter.enabled (not .address) }} +- name: statsd-mappings + configMap: + name: {{ include "mastodon.fullname" $ }}-statsd-mappings + items: + - key: mastodon-statsd-mappings.yml + path: mastodon.yml +{{- end }} +{{- end }} +{{- end }} + +{{/* + Labels added to every statsd_exporter-enabled pod +*/}} +{{- define "mastodon.statsdExporterLabels" }} +{{- with .Values.mastodon.metrics.statsd }} +{{- if and .exporter.enabled (not .address) }} +mastodon/statsd-exporter: "true" +{{- end }} +{{- end }} +{{- end }} diff --git a/templates/configmap-env.yaml b/templates/configmap-env.yaml index 8adebb5..dfc6b56 100644 --- a/templates/configmap-env.yaml +++ b/templates/configmap-env.yaml @@ -15,11 +15,36 @@ data: DB_NAME: {{ .Values.postgresql.auth.database }} DB_POOL: {{ include "mastodon.maxDbPool" . }} DB_USER: {{ .Values.postgresql.auth.username }} + {{- if .Values.postgresql.readReplica.hostname }} + REPLICA_DB_HOST: {{ .Values.postgresql.readReplica.hostname }} + {{- end }} + {{- if .Values.postgresql.readReplica.port }} + REPLICA_DB_PORT: {{ .Values.postgresql.readReplica.port }} + {{- end }} + {{- if .Values.postgresql.readReplica.auth.database }} + REPLICA_DB_NAME: {{ .Values.postgresql.readReplica.auth.database }} + {{- end }} + {{- if .Values.postgresql.readReplica.auth.username }} + REPLICA_DB_USER: {{ .Values.postgresql.readReplica.auth.username }} + {{- end }} + {{- if .Values.postgresql.readReplica.auth.password }} + REPLICA_DB_PASS: {{ .Values.postgresql.readReplica.auth.password }} + {{- end }} + PREPARED_STATEMENTS: {{ .Values.mastodon.preparedStatements | quote }} DEFAULT_LOCALE: {{ .Values.mastodon.locale }} {{- if .Values.elasticsearch.enabled }} ES_ENABLED: "true" + ES_PRESET: {{ .Values.elasticsearch.preset | default "single_node_cluster" | quote }} ES_HOST: {{ template "mastodon.elasticsearch.fullname" . }}-master-hl ES_PORT: "9200" + {{- else if .Values.elasticsearch.hostname }} + ES_ENABLED: "true" + ES_PRESET: {{ .Values.elasticsearch.preset | default "single_node_cluster" | quote }} + ES_HOST: {{ include "mastodon.elasticsearch.fullHostname" .}} + ES_PORT: {{ .Values.elasticsearch.port | default "9200" | quote }} + {{- end }} + {{- with .Values.elasticsearch.user }} + ES_USER: {{ . }} {{- end }} LOCAL_DOMAIN: {{ .Values.mastodon.local_domain }} {{- with .Values.mastodon.web_domain }} @@ -31,6 +56,9 @@ data: {{- with .Values.mastodon.authorizedFetch }} AUTHORIZED_FETCH: {{ . | quote }} {{- end }} + {{- with .Values.mastodon.limitedFederationMode }} + LIMITED_FEDERATION_MODE: {{ . | quote }} + {{- end }} # https://devcenter.heroku.com/articles/tuning-glibc-memory-behavior MALLOC_ARENA_MAX: "2" NODE_ENV: "production" @@ -47,11 +75,20 @@ data: S3_ENDPOINT: {{ .Values.mastodon.s3.endpoint }} S3_HOSTNAME: {{ .Values.mastodon.s3.hostname }} S3_PROTOCOL: "https" + {{- if .Values.mastodon.s3.permission }} + S3_PERMISSION: {{ .Values.mastodon.s3.permission }} + {{- end }} {{- with .Values.mastodon.s3.region }} S3_REGION: {{ . }} {{- end }} {{- with .Values.mastodon.s3.alias_host }} - S3_ALIAS_HOST: {{ .Values.mastodon.s3.alias_host}} + S3_ALIAS_HOST: {{ . }} + {{- end }} + {{- with .Values.mastodon.s3.multipart_threshold }} + S3_MULTIPART_THRESHOLD: "{{ . }}" + {{- end }} + {{- with .Values.mastodon.s3.override_path_style }} + S3_OVERRIDE_PATH_STYLE: "{{ . }}" {{- end }} {{- end }} {{- with .Values.mastodon.smtp.auth_method }} @@ -75,15 +112,12 @@ data: {{- with .Values.mastodon.smtp.from_address }} SMTP_FROM_ADDRESS: {{ . }} {{- end }} - {{- with .Values.mastodon.smtp.login }} - SMTP_LOGIN: {{ . }} + {{- with .Values.mastodon.smtp.return_path }} + SMTP_RETURN_PATH: {{ . }} {{- end }} {{- with .Values.mastodon.smtp.openssl_verify_mode }} SMTP_OPENSSL_VERIFY_MODE: {{ . }} {{- end }} - {{- with .Values.mastodon.smtp.password }} - SMTP_PASSWORD: {{ . }} - {{- end }} {{- with .Values.mastodon.smtp.port }} SMTP_PORT: {{ . | quote }} {{- end }} @@ -288,13 +322,16 @@ data: {{- if .Values.externalAuth.ldap.enabled }} LDAP_ENABLED: {{ .Values.externalAuth.ldap.enabled | quote }} LDAP_HOST: {{ .Values.externalAuth.ldap.host }} - LDAP_PORT: {{ .Values.externalAuth.ldap.port }} + LDAP_PORT: {{ .Values.externalAuth.ldap.port | quote }} LDAP_METHOD: {{ .Values.externalAuth.ldap.method }} - {{- with .Values.externalAuth.ldap.base }} - LDAP_BASE: {{ . }} + {{- if .Values.externalAuth.ldap.tls_no_verify }} + LDAP_TLS_NO_VERIFY: {{ .Values.externalAuth.ldap.tls_no_verify | quote }} {{- end }} - {{- with .Values.externalAuth.ldap.bind_on }} - LDAP_BIND_ON: {{ . }} + {{- if .Values.externalAuth.ldap.base }} + LDAP_BASE: {{ .Values.externalAuth.ldap.base }} + {{- end }} + {{- if .Values.externalAuth.ldap.bind_dn }} + LDAP_BIND_DN: {{ .Values.externalAuth.ldap.bind_dn }} {{- end }} {{- with .Values.externalAuth.ldap.password }} LDAP_PASSWORD: {{ . }} @@ -318,8 +355,33 @@ data: LDAP_UID_CONVERSION_REPLACE: {{ . }} {{- end }} {{- end }} - {{- with .Values.mastodon.metrics.statsd.address }} - STATSD_ADDR: {{ . }} + {{- if .Values.mastodon.metrics.statsd.address }} + STATSD_ADDR: {{ .Values.mastodon.metrics.statsd.address }} + {{- else if .Values.mastodon.metrics.statsd.exporter.enabled }} + STATSD_ADDR: localhost:9125 + {{- end }} + {{- range $k, $v := .Values.mastodon.extraEnvVars }} + {{ $k }}: {{ quote $v }} + {{- end }} + + {{- if .Values.mastodon.deepl.enabled }} + DEEPL_PLAN: {{ .Values.mastodon.deepl.plan }} + {{- end }} + + {{- if .Values.mastodon.hcaptcha.enabled }} + HCAPTCHA_SITE_KEY: {{ .Values.mastodon.hcaptcha.siteId }} + {{- end }} + + {{- if .Values.mastodon.cacheBuster.enabled }} + CACHE_BUSTER_ENABLED: "true" + {{- if .Values.mastodon.cacheBuster.httpMethod }} + CACHE_BUSTER_HTTP_METHOD: {{ .Values.mastodon.cacheBuster.httpMethod }} + {{- end }} + {{- if .Values.mastodon.cacheBuster.authHeader }} + CACHE_BUSTER_SECRET_HEADER: {{ .Values.mastodon.cacheBuster.authHeader }} + {{- end }} + {{- else }} + CACHE_BUSTER_ENABLED: "false" {{- end }} {{- with .Values.timezone }} TZ: {{ . | quote }} diff --git a/templates/cronjob-media-remove.yaml b/templates/cronjob-media-remove.yaml index d70afeb..33229a8 100644 --- a/templates/cronjob-media-remove.yaml +++ b/templates/cronjob-media-remove.yaml @@ -65,6 +65,13 @@ spec: secretKeyRef: name: {{ template "mastodon.redis.secretName" . }} key: redis-password + {{- if and .Values.elasticsearch.existingSecret (or .Values.elasticsearch.enabled .Values.elasticsearch.hostname) }} + - name: "ES_PASS" + valueFrom: + secretKeyRef: + name: {{ .Values.elasticsearch.existingSecret }} + key: password + {{- end }} - name: "PORT" value: {{ .Values.mastodon.web.port | quote }} {{- if (and .Values.mastodon.s3.enabled .Values.mastodon.s3.existingSecret) }} diff --git a/templates/deployment-sidekiq.yaml b/templates/deployment-sidekiq.yaml index a03019e..f6e9c7e 100644 --- a/templates/deployment-sidekiq.yaml +++ b/templates/deployment-sidekiq.yaml @@ -9,6 +9,10 @@ metadata: {{- include "mastodon.labels" $context | nindent 4 }} app.kubernetes.io/component: sidekiq-{{ .name }} app.kubernetes.io/part-of: rails + annotations: + {{- with $context.Values.deploymentAnnotations }} + {{- toYaml . | nindent 4 }} + {{- end }} spec: {{- if (has "scheduler" .queues) }} {{- if (gt (int .replicas) 1) }} @@ -18,6 +22,9 @@ spec: type: Recreate {{- end }} replicas: {{ .replicas }} + {{- if (ne (toString $context.Values.mastodon.revisionHistoryLimit) "") }} + revisionHistoryLimit: {{ $context.Values.mastodon.revisionHistoryLimit }} + {{- end }} selector: matchLabels: {{- include "mastodon.selectorLabels" $context | nindent 6 }} @@ -31,8 +38,11 @@ spec: {{- end }} # roll the pods to pick up any db migrations or other changes {{- include "mastodon.rollingPodAnnotations" $context | nindent 8 }} + checksum/config-secrets-smtp: {{ include ( print $.Template.BasePath "/secret-smtp.yaml" ) $context | sha256sum | quote }} labels: + {{- include "mastodon.globalLabels" $context | nindent 8 }} {{- include "mastodon.selectorLabels" $context | nindent 8 }} + {{- include "mastodon.statsdExporterLabels" $context | nindent 8 }} app.kubernetes.io/component: sidekiq-{{ .name }} app.kubernetes.io/part-of: rails spec: @@ -49,8 +59,12 @@ spec: affinity: {{- toYaml . | nindent 8 }} {{- end }} - {{- if (not $context.Values.mastodon.s3.enabled) }} + {{- with (default (default $context.Values.topologySpreadConstraints $context.Values.mastodon.sidekiq.topologySpreadConstraints) .topologySpreadConstraints) }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} volumes: + {{- if (not $context.Values.mastodon.s3.enabled) }} - name: assets persistentVolumeClaim: claimName: {{ template "mastodon.fullname" $context }}-assets @@ -58,11 +72,20 @@ spec: persistentVolumeClaim: claimName: {{ template "mastodon.fullname" $context }}-system {{- end }} + {{- include "mastodon.statsdExporterVolume" $ | indent 8 }} + {{- if dig "customDatabaseConfigYml" "configMapRef" "name" false . }} + - name: config-database-yml + configMap: + name: {{ .customDatabaseConfigYml.configMapRef.name }} + {{- end }} + {{- with $context.Values.volumes }} + {{- toYaml . | nindent 8 }} + {{- end }} containers: - name: {{ $context.Chart.Name }} securityContext: {{- toYaml $context.Values.mastodon.sidekiq.securityContext | nindent 12 }} - image: "{{ $context.Values.image.repository }}:{{ $context.Values.image.tag | default $context.Chart.AppVersion }}" + image: "{{ coalesce (dig "image" "repository" false .) $context.Values.image.repository }}:{{ coalesce (dig "image" "tag" false .) $context.Values.image.tag $context.Chart.AppVersion }}" imagePullPolicy: {{ $context.Values.image.pullPolicy }} command: - bundle @@ -79,17 +102,47 @@ spec: name: {{ include "mastodon.fullname" $context }}-env - secretRef: name: {{ template "mastodon.secretName" $context }} + {{- if $context.Values.mastodon.extraEnvFrom }} + - configMapRef: + name: {{ $context.Values.mastodon.extraEnvFrom }} + {{- end}} env: - name: "DB_PASS" valueFrom: secretKeyRef: name: {{ template "mastodon.postgresql.secretName" $context }} key: password + {{- if $context.Values.postgresql.readReplica.auth.existingSecret }} + - name: "REPLICA_DB_PASS" + valueFrom: + secretKeyRef: + name: {{ $context.Values.postgresql.readReplica.auth.existingSecret }} + key: password + {{- end }} - name: "REDIS_PASSWORD" valueFrom: secretKeyRef: name: {{ template "mastodon.redis.secretName" $context }} key: redis-password + {{- if and $context.Values.elasticsearch.existingSecret (or $context.Values.elasticsearch.enabled $context.Values.elasticsearch.hostname) }} + - name: "ES_PASS" + valueFrom: + secretKeyRef: + name: {{ $context.Values.elasticsearch.existingSecret }} + key: password + {{- end }} + - name: "SMTP_LOGIN" + valueFrom: + secretKeyRef: + name: {{ include "mastodon.smtp.secretName" $context }} + key: login + optional: true + - name: "SMTP_PASSWORD" + valueFrom: + secretKeyRef: + name: {{ include "mastodon.smtp.secretName" $context }} + key: password + optional: true {{- if (and $context.Values.mastodon.s3.enabled $context.Values.mastodon.s3.existingSecret) }} - name: "AWS_SECRET_ACCESS_KEY" valueFrom: @@ -102,28 +155,38 @@ spec: name: {{ $context.Values.mastodon.s3.existingSecret }} key: AWS_ACCESS_KEY_ID {{- end }} - {{- if $context.Values.mastodon.smtp.existingSecret }} - - name: "SMTP_LOGIN" + {{- if and $context.Values.mastodon.deepl.enabled }} + - name: "DEEPL_API_KEY" valueFrom: secretKeyRef: - name: {{ $context.Values.mastodon.smtp.existingSecret }} - key: login - optional: true - - name: "SMTP_PASSWORD" + name: {{ $context.Values.mastodon.deepl.apiKeySecretRef.name }} + key: {{ $context.Values.mastodon.deepl.apiKeySecretRef.key }} + {{- end }} + {{- if and $context.Values.mastodon.cacheBuster.enabled $context.Values.mastodon.cacheBuster.authToken.existingSecret }} + - name: CACHE_BUSTER_SECRET valueFrom: secretKeyRef: - name: {{ $context.Values.mastodon.smtp.existingSecret }} + name: {{ $context.Values.mastodon.cacheBuster.authToken.existingSecret }} key: password {{- end }} - {{- if (not $context.Values.mastodon.s3.enabled) }} volumeMounts: + {{- if (not $context.Values.mastodon.s3.enabled) }} - name: assets mountPath: /opt/mastodon/public/assets - name: system mountPath: /opt/mastodon/public/system {{- end }} + {{- if dig "customDatabaseConfigYml" "configMapRef" "name" false . }} + - name: config-database-yml + mountPath: /opt/mastodon/config/database.yml + subPath: {{ .customDatabaseConfigYml.configMapRef.key }} + {{- end }} + {{- with $context.Values.volumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} resources: {{- toYaml (default (default $context.Values.resources $context.Values.mastodon.sidekiq.resources) .resources) | nindent 12 }} + {{- include "mastodon.statsdExporterContainer" $ | indent 8 }} {{- with $context.Values.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} diff --git a/templates/deployment-streaming.yaml b/templates/deployment-streaming.yaml index dd80404..8d66361 100644 --- a/templates/deployment-streaming.yaml +++ b/templates/deployment-streaming.yaml @@ -4,8 +4,15 @@ metadata: name: {{ include "mastodon.fullname" . }}-streaming labels: {{- include "mastodon.labels" . | nindent 4 }} + annotations: + {{- with (default .Values.deploymentAnnotations .Values.mastodon.streaming.deploymentAnnotations) }} + {{- toYaml . | nindent 4 }} + {{- end }} spec: replicas: {{ .Values.mastodon.streaming.replicas }} + {{- if (ne (toString .Values.mastodon.revisionHistoryLimit) "") }} + revisionHistoryLimit: {{ .Values.mastodon.revisionHistoryLimit }} + {{- end }} selector: matchLabels: {{- include "mastodon.selectorLabels" . | nindent 6 }} @@ -19,6 +26,7 @@ spec: # roll the pods to pick up any db migrations or other changes {{- include "mastodon.rollingPodAnnotations" . | nindent 8 }} labels: + {{- include "mastodon.globalLabels" . | nindent 8 }} {{- include "mastodon.selectorLabels" . | nindent 8 }} app.kubernetes.io/component: streaming spec: @@ -31,26 +39,65 @@ spec: securityContext: {{- toYaml . | nindent 8 }} {{- end }} + {{- with .Values.mastodon.streaming.extraCerts }} + {{- $name := .name | default "extra-certs" }} + volumes: + - name: {{ $name }} + secret: + secretName: {{ .existingSecret }} + items: + - key: ca.crt + path: trusted-ca.crt + {{- end }} containers: - name: {{ .Chart.Name }}-streaming {{- with (default .Values.securityContext .Values.mastodon.streaming.securityContext) }} securityContext: {{- toYaml . | nindent 12 }} {{- end }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + image: "{{ coalesce .Values.mastodon.streaming.image.repository .Values.image.repository }}:{{ coalesce .Values.mastodon.streaming.image.tag .Values.image.tag .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} command: - node - ./streaming + {{- with .Values.mastodon.streaming.extraCerts }} + {{- $name := .name | default "extra-certs" }} + volumeMounts: + - name: {{ $name }} + mountPath: "/usr/local/share/ca-certificates" + {{- end }} envFrom: - configMapRef: name: {{ include "mastodon.fullname" . }}-env + {{- if .Values.mastodon.extraEnvFrom }} + - configMapRef: + name: {{ .Values.mastodon.extraEnvFrom }} + {{- end}} env: + {{- with .Values.mastodon.streaming.extraCerts }} + - name: "NODE_EXTRA_CA_CERTS" + value: "/usr/local/share/ca-certificates/trusted-ca.crt" + {{- with .sslMode }} + - name: "DB_SSLMODE" + value: {{ . }} + {{- end }} + {{- end }} + {{- with .Values.postgresql.postgresqlReplicaHostname }} + - name: "DB_HOST" + value: {{ . }} + {{- end }} - name: "DB_PASS" valueFrom: secretKeyRef: name: {{ template "mastodon.postgresql.secretName" . }} key: password + {{- if .Values.postgresql.readReplica.auth.existingSecret }} + - name: "REPLICA_DB_PASS" + valueFrom: + secretKeyRef: + name: {{ .Values.postgresql.readReplica.auth.existingSecret }} + key: password + {{- end }} - name: "REDIS_PASSWORD" valueFrom: secretKeyRef: @@ -82,6 +129,10 @@ spec: affinity: {{- toYaml . | nindent 8 }} {{- end }} + {{- with (default .Values.topologySpreadConstraints .Values.mastodon.streaming.topologySpreadConstraints) }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} {{- with .Values.tolerations }} tolerations: {{- toYaml . | nindent 8 }} diff --git a/templates/deployment-web.yaml b/templates/deployment-web.yaml index c1ec232..b1bb0b8 100644 --- a/templates/deployment-web.yaml +++ b/templates/deployment-web.yaml @@ -4,8 +4,15 @@ metadata: name: {{ include "mastodon.fullname" . }}-web labels: {{- include "mastodon.labels" . | nindent 4 }} + annotations: + {{- with (default .Values.deploymentAnnotations .Values.mastodon.web.deploymentAnnotations) }} + {{- toYaml . | nindent 4 }} + {{- end }} spec: replicas: {{ .Values.mastodon.web.replicas }} + {{- if (ne (toString .Values.mastodon.revisionHistoryLimit) "") }} + revisionHistoryLimit: {{ .Values.mastodon.revisionHistoryLimit }} + {{- end }} selector: matchLabels: {{- include "mastodon.selectorLabels" . | nindent 6 }} @@ -20,7 +27,9 @@ spec: # roll the pods to pick up any db migrations or other changes {{- include "mastodon.rollingPodAnnotations" . | nindent 8 }} labels: + {{- include "mastodon.globalLabels" . | nindent 8 }} {{- include "mastodon.selectorLabels" . | nindent 8 }} + {{- include "mastodon.statsdExporterLabels" . | nindent 8 }} app.kubernetes.io/component: web app.kubernetes.io/part-of: rails spec: @@ -33,8 +42,8 @@ spec: securityContext: {{- toYaml . | nindent 8 }} {{- end }} - {{- if (not .Values.mastodon.s3.enabled) }} volumes: + {{- if (not .Values.mastodon.s3.enabled) }} - name: assets persistentVolumeClaim: claimName: {{ template "mastodon.fullname" . }}-assets @@ -42,13 +51,22 @@ spec: persistentVolumeClaim: claimName: {{ template "mastodon.fullname" . }}-system {{- end }} + {{- include "mastodon.statsdExporterVolume" $ | indent 8 }} + {{- if .Values.mastodon.web.customDatabaseConfigYml.configMapRef.name }} + - name: config-database-yml + configMap: + name: {{ .Values.mastodon.web.customDatabaseConfigYml.configMapRef.name }} + {{- end }} + {{- with .Values.volumes }} + {{- toYaml . | nindent 8 }} + {{- end }} containers: - name: {{ .Chart.Name }}-web {{- with (default .Values.securityContext .Values.mastodon.web.securityContext) }} securityContext: {{- toYaml . | nindent 12 }} {{- end }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + image: "{{ coalesce .Values.mastodon.web.image.repository .Values.image.repository }}:{{ coalesce .Values.mastodon.web.image.tag .Values.image.tag .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} command: - bundle @@ -61,19 +79,53 @@ spec: name: {{ include "mastodon.fullname" . }}-env - secretRef: name: {{ template "mastodon.secretName" . }} + {{- if .Values.mastodon.extraEnvFrom }} + - configMapRef: + name: {{ .Values.mastodon.extraEnvFrom }} + {{- end}} env: - name: "DB_PASS" valueFrom: secretKeyRef: name: {{ template "mastodon.postgresql.secretName" . }} key: password + {{- if .Values.postgresql.readReplica.auth.existingSecret }} + - name: "REPLICA_DB_PASS" + valueFrom: + secretKeyRef: + name: {{ .Values.postgresql.readReplica.auth.existingSecret}} + key: password + {{- end }} - name: "REDIS_PASSWORD" valueFrom: secretKeyRef: name: {{ template "mastodon.redis.secretName" . }} key: redis-password + {{- if and .Values.elasticsearch.existingSecret (or .Values.elasticsearch.enabled .Values.elasticsearch.hostname) }} + - name: "ES_PASS" + valueFrom: + secretKeyRef: + name: {{ .Values.elasticsearch.existingSecret }} + key: password + {{- end }} - name: "PORT" value: {{ .Values.mastodon.web.port | quote }} + {{- if .Values.mastodon.web.minThreads }} + - name: "MIN_THREADS" + value: {{ .Values.mastodon.web.minThreads | quote }} + {{- end }} + {{- if .Values.mastodon.web.maxThreads }} + - name: "MAX_THREADS" + value: {{ .Values.mastodon.web.maxThreads | quote }} + {{- end }} + {{- if .Values.mastodon.web.workers }} + - name: "WEB_CONCURRENCY" + value: {{ .Values.mastodon.web.workers | quote }} + {{- end }} + {{- if .Values.mastodon.web.persistentTimeout }} + - name: "PERSISTENT_TIMEOUT" + value: {{ .Values.mastodon.web.persistentTimeout | quote }} + {{- end }} {{- if (and .Values.mastodon.s3.enabled .Values.mastodon.s3.existingSecret) }} - name: "AWS_SECRET_ACCESS_KEY" valueFrom: @@ -86,13 +138,42 @@ spec: name: {{ .Values.mastodon.s3.existingSecret }} key: AWS_ACCESS_KEY_ID {{- end }} - {{- if (not .Values.mastodon.s3.enabled) }} + {{- if .Values.mastodon.deepl.enabled }} + - name: "DEEPL_API_KEY" + valueFrom: + secretKeyRef: + name: {{ .Values.mastodon.deepl.apiKeySecretRef.name }} + key: {{ .Values.mastodon.deepl.apiKeySecretRef.key }} + {{- end }} + {{- if .Values.mastodon.hcaptcha.enabled }} + - name: "HCAPTCHA_SECRET_KEY" + valueFrom: + secretKeyRef: + name: {{ .Values.mastodon.hcaptcha.secretKeySecretRef.name }} + key: {{ .Values.mastodon.hcaptcha.secretKeySecretRef.key }} + {{- end }} + {{- if and .Values.mastodon.cacheBuster.enabled .Values.mastodon.cacheBuster.authToken.existingSecret }} + - name: CACHE_BUSTER_SECRET + valueFrom: + secretKeyRef: + name: {{ .Values.mastodon.cacheBuster.authToken.existingSecret }} + key: password + {{- end }} volumeMounts: + {{- if (not .Values.mastodon.s3.enabled) }} - name: assets mountPath: /opt/mastodon/public/assets - name: system mountPath: /opt/mastodon/public/system {{- end }} + {{- if .Values.mastodon.web.customDatabaseConfigYml.configMapRef.name }} + - name: config-database-yml + mountPath: /opt/mastodon/config/database.yml + subPath: {{ .Values.mastodon.web.customDatabaseConfigYml.configMapRef.key }} + {{- end }} + {{- with .Values.volumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} ports: - name: http containerPort: {{ .Values.mastodon.web.port }} @@ -114,6 +195,7 @@ spec: resources: {{- toYaml . | nindent 12 }} {{- end }} + {{- include "mastodon.statsdExporterContainer" $ | indent 8 }} {{- with .Values.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} @@ -122,7 +204,11 @@ spec: affinity: {{- toYaml . | nindent 8 }} {{- end }} - {{- with .Values.tolerations }} + {{- with (default .Values.topologySpreadConstraints .Values.mastodon.web.topologySpreadConstraints) }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with (default .Values.tolerations .Values.mastodon.web.tolerations) }} tolerations: {{- toYaml . | nindent 8 }} {{- end }} diff --git a/templates/ingress-streaming.yml b/templates/ingress-streaming.yml new file mode 100644 index 0000000..4e3ad72 --- /dev/null +++ b/templates/ingress-streaming.yml @@ -0,0 +1,57 @@ +{{- if .Values.ingress.streaming.enabled -}} +{{- $fullName := include "mastodon.fullname" . -}} +{{- $webPort := .Values.mastodon.web.port -}} +{{- $streamingPort := .Values.mastodon.streaming.port -}} +{{- if or (.Capabilities.APIVersions.Has "networking.k8s.io/v1/Ingress") (not (.Capabilities.APIVersions.Has "networking.k8s.io/v1beta1/Ingress")) -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }}-streaming + labels: + {{- include "mastodon.labels" . | nindent 4 }} + {{- with .Values.ingress.streaming.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.ingress.streaming.ingressClassName }} + ingressClassName: {{ .Values.ingress.streaming.ingressClassName }} + {{- end }} + {{- if .Values.ingress.streaming.tls }} + tls: + {{- range .Values.ingress.streaming.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.streaming.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }}api/v1/streaming + backend: + {{- if or ($.Capabilities.APIVersions.Has "networking.k8s.io/v1/Ingress") (not ($.Capabilities.APIVersions.Has "networking.k8s.io/v1beta1/Ingress")) }} + service: + name: {{ $fullName }}-streaming + port: + number: {{ $streamingPort }} + {{- else }} + serviceName: {{ $fullName }}-streaming + servicePort: {{ $streamingPort }} + {{- end }} + {{- if or ($.Capabilities.APIVersions.Has "networking.k8s.io/v1/Ingress") (not ($.Capabilities.APIVersions.Has "networking.k8s.io/v1beta1/Ingress")) }} + pathType: Prefix + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/templates/ingress.yaml b/templates/ingress.yaml index e5c5e1d..3da46ab 100644 --- a/templates/ingress.yaml +++ b/templates/ingress.yaml @@ -52,7 +52,8 @@ spec: {{- if or ($.Capabilities.APIVersions.Has "networking.k8s.io/v1/Ingress") (not ($.Capabilities.APIVersions.Has "networking.k8s.io/v1beta1/Ingress")) }} pathType: Prefix {{- end }} - - path: {{ .path }}api/v1/streaming/ + {{- if not $.Values.ingress.streaming.enabled }} + - path: {{ .path }}api/v1/streaming backend: {{- if or ($.Capabilities.APIVersions.Has "networking.k8s.io/v1/Ingress") (not ($.Capabilities.APIVersions.Has "networking.k8s.io/v1beta1/Ingress")) }} service: @@ -64,8 +65,9 @@ spec: servicePort: {{ $streamingPort }} {{- end }} {{- if or ($.Capabilities.APIVersions.Has "networking.k8s.io/v1/Ingress") (not ($.Capabilities.APIVersions.Has "networking.k8s.io/v1beta1/Ingress")) }} - pathType: Exact + pathType: Prefix {{- end }} {{- end }} + {{- end }} {{- end }} {{- end }} diff --git a/templates/job-assets-precompile.yaml b/templates/job-assets-precompile.yaml index bc5ff7b..3458fea 100644 --- a/templates/job-assets-precompile.yaml +++ b/templates/job-assets-precompile.yaml @@ -1,3 +1,4 @@ +{{- if .Values.mastodon.hooks.assetsPrecompile.enabled -}} apiVersion: batch/v1 kind: Job metadata: @@ -75,3 +76,4 @@ spec: - name: system mountPath: /opt/mastodon/public/system {{- end }} +{{- end -}} diff --git a/templates/job-chewy-upgrade.yaml b/templates/job-chewy-upgrade.yaml index f86a4e3..33e9bf9 100644 --- a/templates/job-chewy-upgrade.yaml +++ b/templates/job-chewy-upgrade.yaml @@ -67,6 +67,13 @@ spec: secretKeyRef: name: {{ template "mastodon.redis.secretName" . }} key: redis-password + {{- if and .Values.elasticsearch.existingSecret (or .Values.elasticsearch.enabled .Values.elasticsearch.hostname) }} + - name: "ES_PASS" + valueFrom: + secretKeyRef: + name: {{ .Values.elasticsearch.existingSecret }} + key: password + {{- end }} - name: "PORT" value: {{ .Values.mastodon.web.port | quote }} {{- if (not .Values.mastodon.s3.enabled) }} diff --git a/templates/job-db-migrate.yaml b/templates/job-db-migrate.yaml index 41324fb..e9a40a7 100644 --- a/templates/job-db-migrate.yaml +++ b/templates/job-db-migrate.yaml @@ -1,3 +1,4 @@ +{{- if .Values.mastodon.hooks.dbMigrate.enabled -}} apiVersion: batch/v1 kind: Job metadata: @@ -75,3 +76,4 @@ spec: - name: system mountPath: /opt/mastodon/public/system {{- end }} +{{- end -}} diff --git a/templates/pvc-assets.yaml b/templates/pvc-assets.yaml index 36d5558..46c90ca 100644 --- a/templates/pvc-assets.yaml +++ b/templates/pvc-assets.yaml @@ -7,7 +7,7 @@ metadata: {{- include "mastodon.labels" . | nindent 4 }} spec: accessModes: - - {{ .Values.mastodon.persistence.system.accessMode }} + - {{ .Values.mastodon.persistence.assets.accessMode }} {{- with .Values.mastodon.persistence.assets.resources }} resources: {{- toYaml . | nindent 4 }} diff --git a/templates/secret-smtp.yaml b/templates/secret-smtp.yaml new file mode 100644 index 0000000..893ecf7 --- /dev/null +++ b/templates/secret-smtp.yaml @@ -0,0 +1,16 @@ +{{- if not .Values.mastodon.smtp.existingSecret -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ printf "%s-smtp" (include "mastodon.fullname" .) }} + labels: + {{- include "mastodon.labels" . | nindent 4 }} +type: Opaque +data: + {{- with .Values.mastodon.smtp.login }} + login: {{ . | b64enc }} + {{- end }} + {{- with .Values.mastodon.smtp.password }} + password: {{ . | b64enc }} + {{- end }} +{{- end }} diff --git a/templates/secrets.yaml b/templates/secrets.yaml index d1776ac..0eec2ab 100644 --- a/templates/secrets.yaml +++ b/templates/secrets.yaml @@ -34,6 +34,21 @@ data: {{- else }} VAPID_PUBLIC_KEY: {{ required "vapid.public_key is required" .Values.mastodon.secrets.vapid.public_key }} {{- end }} + {{- if not (empty .Values.mastodon.secrets.activeRecordEncryption.primaryKey) }} + ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY: "{{ .Values.mastodon.secrets.activeRecordEncryption.primaryKey | b64enc }}" + {{- else }} + ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY: {{ required "activeRecordEncryption.primaryKey is required" .Values.mastodon.secrets.activeRecordEncryption.primaryKey }} + {{- end }} + {{- if not (empty .Values.mastodon.secrets.activeRecordEncryption.deterministicKey) }} + ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY: "{{ .Values.mastodon.secrets.activeRecordEncryption.deterministicKey | b64enc }}" + {{- else }} + ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY: {{ required "activeRecordEncryption.deterministicKey is required" .Values.mastodon.secrets.activeRecordEncryption.deterministicKey }} + {{- end }} + {{- if not (empty .Values.mastodon.secrets.activeRecordEncryption.keyDerivationSalt) }} + ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT: "{{ .Values.mastodon.secrets.activeRecordEncryption.keyDerivationSalt | b64enc }}" + {{- else }} + ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT: {{ required "activeRecordEncryption.keyDerivationSalt is required" .Values.mastodon.secrets.activeRecordEncryption.keyDerivationSalt }} + {{- end }} {{- end }} {{- if not .Values.postgresql.enabled }} {{- if not .Values.postgresql.auth.existingSecret }} diff --git a/templates/statsd-exporter-mappings.yaml b/templates/statsd-exporter-mappings.yaml new file mode 100644 index 0000000..813af1d --- /dev/null +++ b/templates/statsd-exporter-mappings.yaml @@ -0,0 +1,107 @@ +{{- if and .Values.mastodon.metrics.statsd.exporter.enabled (not .Values.mastodon.metrics.statsd.address) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "mastodon.fullname" . }}-statsd-mappings + labels: + {{- include "mastodon.labels" . | nindent 4 }} +data: + mastodon-statsd-mappings.yml: |- + ## From https://ipng.ch/assets/mastodon/statsd-mapping.yaml + ## Prometheus Statsd Exporter mapping for Mastodon 4.0+ + ## + ## Version 1.0, November 2022 + ## + ## Documentation: https://ipng.ch/s/articles/2022/11/27/mastodon-3.html + + mappings: + ## Web collector + - match: Mastodon\.production\.web\.(.+)\.(.+)\.(.+)\.status\.(.+) + match_type: regex + name: "mastodon_controller_status" + labels: + controller: $1 + action: $2 + format: $3 + status: $4 + mastodon: "web" + - match: Mastodon\.production\.web\.(.+)\.(.+)\.(.+)\.db_time + match_type: regex + name: "mastodon_controller_db_time" + labels: + controller: $1 + action: $2 + format: $3 + mastodon: "web" + - match: Mastodon\.production\.web\.(.+)\.(.+)\.(.+)\.view_time + match_type: regex + name: "mastodon_controller_view_time" + labels: + controller: $1 + action: $2 + format: $3 + mastodon: "web" + - match: Mastodon\.production\.web\.(.+)\.(.+)\.(.+)\.total_duration + match_type: regex + name: "mastodon_controller_duration" + labels: + controller: $1 + action: $2 + format: $3 + mastodon: "web" + + ## Database collector + - match: Mastodon\.production\.db\.tables\.(.+)\.queries\.(.+)\.duration + match_type: regex + name: "mastodon_db_operation" + labels: + table: "$1" + operation: "$2" + mastodon: "db" + + ## Cache collector + - match: Mastodon\.production\.cache\.(.+)\.duration + match_type: regex + name: "mastodon_cache_duration" + labels: + operation: "$1" + mastodon: "cache" + + ## Sidekiq collector + - match: Mastodon\.production\.sidekiq\.(.+)\.processing_time + match_type: regex + name: "mastodon_sidekiq_worker_processing_time" + labels: + worker: "$1" + mastodon: "sidekiq" + - match: Mastodon\.production\.sidekiq\.(.+)\.success + match_type: regex + name: "mastodon_sidekiq_worker_success_total" + labels: + worker: "$1" + mastodon: "sidekiq" + - match: Mastodon\.production\.sidekiq\.(.+)\.failure + match_type: regex + name: "mastodon_sidekiq_worker_failure_total" + labels: + worker: "$1" + mastodon: "sidekiq" + - match: Mastodon\.production\.sidekiq\.queues\.(.+)\.enqueued + match_type: regex + name: "mastodon_sidekiq_queue_enqueued" + labels: + queue: "$1" + mastodon: "sidekiq" + - match: Mastodon\.production\.sidekiq\.queues\.(.+)\.latency + match_type: regex + name: "mastodon_sidekiq_queue_latency" + labels: + queue: "$1" + mastodon: "sidekiq" + - match: Mastodon\.production\.sidekiq\.(.+) + match_type: regex + name: "mastodon_sidekiq_$1" + labels: + mastodon: "sidekiq" + +{{- end }} diff --git a/values.yaml b/values.yaml index 9b63329..45b43fd 100644 --- a/values.yaml +++ b/values.yaml @@ -1,16 +1,19 @@ image: - repository: tootsuite/mastodon - # https://hub.docker.com/r/tootsuite/mastodon/tags + repository: ghcr.io/mastodon/mastodon + # https://github.com/mastodon/mastodon/pkgs/container/mastodon # # alternatively, use `latest` for the latest release or `edge` for the image # built from the most recent commit # # tag: latest - tag: "" + tag: "v4.2.8" # use `Always` when using `latest` tag pullPolicy: IfNotPresent mastodon: + # Labels added to every Mastodon-related object + labels: {} + # -- create an initial administrator user; the password is autogenerated and will # have to be reset createAdmin: @@ -20,6 +23,13 @@ mastodon: username: not_gargron # @ignored email: not@example.com + hooks: + dbMigrate: + enabled: true + assetsPrecompile: + enabled: true + # Custom labels to add to kubernetes resources + #labels: cron: # -- run `tootctl media remove` every week removeMedia: @@ -38,6 +48,8 @@ mastodon: singleUserMode: false # -- Enables "Secure Mode" for more details see: https://docs.joinmastodon.org/admin/config/#authorized_fetch authorizedFetch: false + # -- Enables "Limited Federation Mode" for more details see: https://docs.joinmastodon.org/admin/config/#limited_federation_mode + limitedFederationMode: false persistence: assets: # -- ReadWriteOnce is more widely supported than ReadWriteMany, but limits @@ -63,8 +75,27 @@ mastodon: endpoint: "" hostname: "" region: "" + permission: "" # -- If you have a caching proxy, enter its base URL here. alias_host: "" + # When uploading data to S3, if the number of bytes to send exceedes + # multipart_threshold then a multi part session is automatically started + # and the data is sent up in chunks. Defaults to 16777216 (16MB). + multipart_threshold: "" + # -- Set this to true if the storage provider uses domain style 'bucket.endpoint' naming + # override_path_style: "true" + deepl: + enabled: false + plan: + apiKeySecretRef: + name: + key: + hcaptcha: + enabled: false + siteId: + secretKeySecretRef: + name: + key: # these must be set manually; autogenerated keys are rotated on each upgrade secrets: secret_key_base: "" @@ -72,10 +103,25 @@ mastodon: vapid: private_key: "" public_key: "" + activeRecordEncryption: + primaryKey: "" + deterministicKey: "" + keyDerivationSalt: "" # -- you can also specify the name of an existing Secret - # with keys SECRET_KEY_BASE and OTP_SECRET and - # VAPID_PRIVATE_KEY and VAPID_PUBLIC_KEY + # with keys: + # - SECRET_KEY_BASE + # - OTP_SECRET + # - VAPID_PRIVATE_KEY + # - VAPID_PUBLIC_KEY + # - ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY + # - ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY + # - ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT existingSecret: "" + + # -- The number of old revisions to keep for each Deployment in Kubernetes. + # See https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#clean-up-policy + revisionHistoryLimit: 2 + sidekiq: # -- Pod security context for all Sidekiq Pods, overwrites .Values.podSecurityContext podSecurityContext: {} @@ -85,6 +131,8 @@ mastodon: resources: {} # -- Affinity for all Sidekiq Deployments unless overwritten, overwrites .Values.affinity affinity: {} + # -- Topology spread constraints for Sidekiq Pods, overwrites .Values.topologySpreadConstraints + topologySpreadConstraints: {} # limits: # cpu: "1" # memory: 768Mi @@ -92,24 +140,35 @@ mastodon: # cpu: 250m # memory: 512Mi workers: - - name: all-queues - # -- Number of threads / parallel sidekiq jobs that are executed per Pod - concurrency: 25 - # -- Number of Pod replicas deployed by the Deployment - replicas: 1 - # -- Resources for this specific deployment to allow optimised scaling, overwrites .Values.mastodon.sidekiq.resources - resources: {} - # -- Affinity for this specific deployment, overwrites .Values.affinity and .Values.mastodon.sidekiq.affinity - affinity: {} - # -- Sidekiq queues for Mastodon that are handled by this worker. See https://docs.joinmastodon.org/admin/scaling/#concurrency - # See https://github.com/mperham/sidekiq/wiki/Advanced-Options#queues for how to weight queues as argument - queues: - - default,8 - - push,6 - - ingress,4 - - mailers,2 - - pull - - scheduler # Make sure the scheduler queue only exists once and with a worker that has 1 replica. + - name: all-queues + # -- Number of threads / parallel sidekiq jobs that are executed per Pod + concurrency: 25 + # -- Number of Pod replicas deployed by the Deployment + replicas: 1 + # -- Resources for this specific deployment to allow optimised scaling, overwrites .Values.mastodon.sidekiq.resources + resources: {} + # -- Affinity for this specific deployment, overwrites .Values.affinity and .Values.mastodon.sidekiq.affinity + affinity: {} + # -- Topology spread constraints for this specific deployment, overwrites .Values.topologySpreadConstraints and .Values.mastodon.sidekiq.topologySpreadConstraints + topologySpreadConstraints: {} + # -- Sidekiq queues for Mastodon that are handled by this worker. See https://docs.joinmastodon.org/admin/scaling/#concurrency + # See https://github.com/mperham/sidekiq/wiki/Advanced-Options#queues for how to weight queues as argument + queues: + - default,8 + - push,6 + - ingress,4 + - mailers,2 + - pull + - scheduler # Make sure the scheduler queue only exists once and with a worker that has 1 replica. + image: + repository: + tag: + # allows you to mount a custom database.yml from a configmap + # please note that we do not advise using a read-only replica for sidekiq workers + customDatabaseConfigYml: + configMapRef: + name: + key: #- name: push-pull # concurrency: 50 # resources: {} @@ -132,8 +191,9 @@ mastodon: ca_file: /etc/ssl/certs/ca-certificates.crt delivery_method: smtp domain: - enable_starttls: 'auto' + enable_starttls: "auto" from_address: notifications@example.com + return_path: openssl_verify_mode: peer port: 587 reply_to: @@ -141,10 +201,13 @@ mastodon: tls: false login: password: - # -- you can also specify the name of an existing Secret - # with the keys login and password + # -- Instead of defining login/password above, you can specify the name of an existing secret here. Login and + # password must be located in keys named `login` and `password` respectively. existingSecret: streaming: + image: + repository: + tag: port: 4000 # -- this should be set manually since os.cpus() returns the number of CPUs on # the node running the pod, which is unrelated to the resources allocated to @@ -157,6 +220,8 @@ mastodon: replicas: 1 # -- Affinity for Streaming Pods, overwrites .Values.affinity affinity: {} + # -- Topology spread constraints for Streaming Pods, overwrites .Values.topologySpreadConstraints + topologySpreadConstraints: {} # -- Pod Security Context for Streaming Pods, overwrites .Values.podSecurityContext podSecurityContext: {} # -- (Streaming Container) Security Context for Streaming Pods, overwrites .Values.securityContext @@ -169,12 +234,22 @@ mastodon: # requests: # cpu: 250m # memory: 128Mi + # -- Self-signed certificate(s) the (Node.js) needs to trust to connect to e.g. the database + extraCerts: {} + # -- Secret containing a key "ca.crt" holding one or more root certificates in PEM format + # existingSecret: + # -- Optional volume name for mounting the .crt file, defaults to "extra-certs" + # name: + # -- Optional sslMode setting. See nodejs's SSL_MODE. Consider "no-verify" + # sslMode: web: port: 3000 # -- Number of Web Pods running replicas: 1 # -- Affinity for Web Pods, overwrites .Values.affinity affinity: {} + # -- Topology spread constraints for Web Pods, overwrites .Values.topologySpreadConstraints + topologySpreadConstraints: {} # -- Pod Security Context for Web Pods, overwrites .Values.podSecurityContext podSecurityContext: {} # -- (Web Container) Security Context for Web Pods, overwrites .Values.securityContext @@ -187,11 +262,56 @@ mastodon: # requests: # cpu: 250m # memory: 768Mi + # -- Puma-specific options. Below values are based on default behavior in + # config/puma.rb when no custom values are provided. + minThreads: "5" + maxThreads: "5" + workers: "2" + persistentTimeout: "20" + image: + repository: + tag: + # allows you to mount a custom database.yml from a configmap + # for example if you want to use a read-only replica + customDatabaseConfigYml: + configMapRef: + name: + key: + + # HTTP cache buster configuration. + # See the documentation for more information about this feature: + # https://docs.joinmastodon.org/admin/config/#http-cache-buster + cacheBuster: + enabled: false + httpMethod: "GET" + # If the cache service requires authentication, specify the header name and + # secret/token here. + authHeader: + authToken: + existingSecret: metrics: statsd: # -- Enable statsd publishing via STATSD_ADDR environment variable address: "" + # -- Alternatively, you can use this to have a statsd_exporter sidecar container running along all Mastodon containers and exposing metrics in OpenMetric/Prometheus format on each pod + # Please note the exporter will not be enabled if metrics.statsd.address is not empty + exporter: + enabled: false + port: 9102 + + # Sets the PREPARED_STATEMENTS environment variable: https://docs.joinmastodon.org/admin/config/#prepared_statements + preparedStatements: true + + + # Specify extra environment variables to be added to all Mastodon pods. + # These can be used for configuration not included in this chart (including configuration for Mastodon varietals.) + extraEnvVars: {} + + # Alternatively specify extra environment variables stored in a ConfigMap. + # The specified ConfigMap should contain the additional environment variables in key-value format. + # extraEnvFrom: + ingress: enabled: true @@ -213,25 +333,54 @@ ingress: hosts: - host: mastodon.local paths: - - path: '/' + - path: "/" tls: - secretName: mastodon-tls hosts: - mastodon.local + # This allows you to have a separate ingress for streaming + # When enabled, the main ingress will no longer handle streaming requests. + # You will also need to configure mastodon.streaming.base_url accordingly + streaming: + enabled: false + annotations: + ingressClassName: + hosts: + - host: streaming.mastodon.local + paths: + - path: "/" + tls: + - secretName: mastodon-tls + hosts: + - streaming.mastodon.local + # -- https://github.com/bitnami/charts/tree/master/bitnami/elasticsearch#parameters elasticsearch: - # `false` will disable full-text search + # Elasticsearch is powering full-text search. It is optional. + + # `false` will not install Elasticsearch as part of this chart # # if you enable ES after the initial install, you will need to manually run # RAILS_ENV=production bundle exec rake chewy:sync # (https://docs.joinmastodon.org/admin/optional/elasticsearch/) - # @ignored enabled: true # @ignored image: tag: 7 + # If you are using an external ES cluster, use `enabled: false` and set the hostname, port, + # and whether the cluster uses TLS. + # hostname: + # port: 9200 + # tls: true + # preset: single_node_cluster + + # This is optional, use it if you ES cluster requires authentication + # user: + # Name of an existing secret with a password key + # existingSecret: + # https://github.com/bitnami/charts/tree/master/bitnami/postgresql#parameters postgresql: # -- disable if you want to use an existing db; in which case the values below @@ -254,6 +403,20 @@ postgresql: # with a key of password set to the password you want existingSecret: "" + # Options for a read-only replica. + # If enabled, mastodon uses existing defaults for postgres for these values as well. + # NOTE: This feature is only available on Mastodon v4.2+ + # Documentation for more information on this feature: + # https://docs.joinmastodon.org/admin/scaling/#read-replicas + readReplica: + hostname: + port: + auth: + database: + username: + password: + existingSecret: + # https://github.com/bitnami/charts/tree/master/bitnami/redis#parameters redis: # disable if you want to use an existing redis instance; in which case the @@ -261,13 +424,15 @@ redis: enabled: true hostname: "" port: 6379 - # -- you must set a password; the password generated by the redis chart will be - # rotated on each upgrade: - password: "" - # you can also specify the name of an existing Secret - # with a key of redis-password set to the password you want - # auth: + auth: + # -- you must set a password; the password generated by the redis chart will be + # rotated on each upgrade: + password: "" + # you can also specify the name of an existing Secret + # with a key of redis-password set to the password you want # existingSecret: "" + replica: + replicaCount: 0 # @ignored service: @@ -360,10 +525,11 @@ externalAuth: ldap: enabled: false # host: myservice.namespace.svc - # port: 389 + # port: 636 # method: simple_tls + # tls_no_verify: true # base: - # bind_on: + # bind_dn: # password: # uid: cn # mail: mail @@ -394,16 +560,25 @@ serviceAccount: # If not set and create is true, a name is generated using the fullname template name: "" +# Custom annotations to apply to all created deployment objects. These can be +# used to help mastodon interact with other services in the cluster. +deploymentAnnotations: {} + # -- Kubernetes manages pods for jobs and pods for deployments differently, so you might # need to apply different annotations to the two different sets of pods. The annotations # set with podAnnotations will be added to all deployment-managed pods. podAnnotations: {} -# -- The annotations set with jobAnnotations will be added to all job pods. +# If set to true, an annotation with the current chart release number will be added to all mastodon pods. This will +# cause all pods to be recreated every `helm upgrade` regardless of whether their config or spec changes. +revisionPodAnnotation: true + +# The annotations set with jobAnnotations will be added to all job pods. jobAnnotations: {} # -- Default resources for all Deployments and jobs unless overwritten -resources: {} +resources: + {} # We usually recommend not to specify default resources and to leave this as a conscious # choice for the user. This also increases chances charts run on environments with little # resources, such as Minikube. If you do want to specify resources, uncomment the following @@ -426,3 +601,15 @@ affinity: {} # -- Timezone for all pods unless overwritten timezone: UTC + +# -- Topology Spread Constraints for all pods unless overwritten +# Please note that you need to use `matchLabelKeys` (Kubernetes 1.25+) if you +# want to spread each deployment independently, or override topologySpreadConstraints +# for each deployment +topologySpreadConstraints: {} + +# Default volume mounts for all pods +volumeMounts: [] + +# Default volumes for all pods +volumes: []