From 540393064d6f2737b95cef81b26dde47326fbec4 Mon Sep 17 00:00:00 2001 From: WrenIX Date: Fri, 26 Jul 2024 02:21:20 +0200 Subject: [PATCH] feat(ntfy): add web push support --- ntfy/Chart.yaml | 2 +- ntfy/README.adoc | 32 ++++++++++++- ntfy/templates/configmap.yaml | 12 ++++- ntfy/templates/deployment.yaml | 2 + ntfy/templates/secret.yaml | 32 +++++++++++++ ntfy/templates/setup/job.yaml | 61 ++++++++++++++++++++++++ ntfy/templates/setup/role.yaml | 22 +++++++++ ntfy/templates/setup/rolebinding.yaml | 19 ++++++++ ntfy/templates/setup/serviceaccount.yaml | 9 ++++ ntfy/values.yaml | 15 ++++++ 10 files changed, 203 insertions(+), 3 deletions(-) create mode 100644 ntfy/templates/secret.yaml create mode 100644 ntfy/templates/setup/job.yaml create mode 100644 ntfy/templates/setup/role.yaml create mode 100644 ntfy/templates/setup/rolebinding.yaml create mode 100644 ntfy/templates/setup/serviceaccount.yaml diff --git a/ntfy/Chart.yaml b/ntfy/Chart.yaml index a220ee4..33ae18b 100644 --- a/ntfy/Chart.yaml +++ b/ntfy/Chart.yaml @@ -3,7 +3,7 @@ name: ntfy description: A Helm chart for Kubernetes icon: https://github.com/binwiederhier/ntfy/raw/main/web/public/static/images/pwa-512x512.png type: application -version: 0.2.0 +version: 0.3.0 # renovate: image=docker.io/binwiederhier/ntfy appVersion: "2.11.0" maintainers: diff --git a/ntfy/README.adoc b/ntfy/README.adoc index af49c20..7778348 100644 --- a/ntfy/README.adoc +++ b/ntfy/README.adoc @@ -2,7 +2,7 @@ = ntfy -image::https://img.shields.io/badge/Version-0.2.0-informational?style=flat-square[Version: 0.2.0] +image::https://img.shields.io/badge/Version-0.3.0-informational?style=flat-square[Version: 0.3.0] image::https://img.shields.io/badge/Version-application-informational?style=flat-square[Type: application] image::https://img.shields.io/badge/AppVersion-2.11.0-informational?style=flat-square[AppVersion: 2.11.0] == Maintainers @@ -157,6 +157,11 @@ helm uninstall ntfy-release | `[]` | +| kubectl.image +| object +| `{"pullPolicy":"IfNotPresent","registry":"docker.io","repository":"bitnami/kubectl","tag":"1.30.3"}` +| image needed for setup (store generated VAPID / WebPush keys) + | nameOverride | string | `""` @@ -392,6 +397,31 @@ helm uninstall ntfy-release | `30` | +| ntfy.webPush.emailAddress +| string +| `""` +| + +| ntfy.webPush.file +| string +| `"/data/webpush.db"` +| + +| ntfy.webPush.keys.create +| bool +| `false` +| + +| ntfy.webPush.keys.private +| string +| `nil` +| + +| ntfy.webPush.keys.public +| string +| `nil` +| + | ntfy.webRoot | string | `"app"` diff --git a/ntfy/templates/configmap.yaml b/ntfy/templates/configmap.yaml index e7bd7d5..87c9066 100644 --- a/ntfy/templates/configmap.yaml +++ b/ntfy/templates/configmap.yaml @@ -83,6 +83,16 @@ data: {{- end }} {{- end }} + # web-push + {{- with .Values.ntfy.webPush }} + {{- with .file }} + NTFY_WEB_PUSH_FILE: {{ . | quote }} + {{- end }} + {{- with .emailAddress }} + NTFY_WEB_PUSH_EMAIL_ADDRESS: {{ . | quote }} + {{- end }} + {{- end }} + {{- with .Values.ntfy.keepaliveInterval }} NTFY_KEEPALIVE_INTERVAL: {{ . | quote }} {{- end }} @@ -131,4 +141,4 @@ data: NTFY_ENABLE_LOGIN: {{ .Values.ntfy.enableLogin | quote }} NTFY_ENABLE_RESERVATIONS: {{ .Values.ntfy.enableReservations | quote }} NTFY_ENABLE_METRICS: {{ .Values.ntfy.metrics.enable | quote }} - NTFY_METRICS_LISTEN_HTTP: ":{{ .Values.ntfy.metrics.port }}" \ No newline at end of file + NTFY_METRICS_LISTEN_HTTP: ":{{ .Values.ntfy.metrics.port }}" diff --git a/ntfy/templates/deployment.yaml b/ntfy/templates/deployment.yaml index 9ea830b..98692e0 100644 --- a/ntfy/templates/deployment.yaml +++ b/ntfy/templates/deployment.yaml @@ -49,6 +49,8 @@ spec: envFrom: - configMapRef: name: {{ include "ntfy.fullname" . }}-env + - secretRef: + name: {{ include "ntfy.fullname" . }}-env {{- with .Values.envFrom }} {{- toYaml . | nindent 12 }} {{- end }} diff --git a/ntfy/templates/secret.yaml b/ntfy/templates/secret.yaml new file mode 100644 index 0000000..32cb8a7 --- /dev/null +++ b/ntfy/templates/secret.yaml @@ -0,0 +1,32 @@ +--- +{{- $fullname := include "ntfy.fullname" . }} +{{- $secretName := printf "%s-env" $fullname }} +{{- $public := .Values.ntfy.webPush.keys.public }} +{{- $private := .Values.ntfy.webPush.keys.private }} + +{{- with (lookup "v1" "Secret" .Release.Namespace $secretName)}} +{{- with get . "data" }} +{{- $public = $public | default (get . "NTFY_WEB_PUSH_PUBLIC_KEY" | b64dec) }} +{{- $private = $private | default (get . "NTFY_WEB_PUSH_PRIVATE_KEY" | b64dec) }} +{{- end }} +{{- end }} + + +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + annotations: + helm.sh/resource-policy: keep + confighash: {{ .Values.ntfy | toYaml | sha256sum | trunc 32 }} + labels: + {{- include "ntfy.labels" . | nindent 4 }} +data: + + # web-push + {{- with $public }} + NTFY_WEB_PUSH_PUBLIC_KEY: {{ . | b64enc }} + {{- end }} + {{- with $private }} + NTFY_WEB_PUSH_PRIVATE_KEY: {{ . | b64enc }} + {{- end }} diff --git a/ntfy/templates/setup/job.yaml b/ntfy/templates/setup/job.yaml new file mode 100644 index 0000000..2050ec8 --- /dev/null +++ b/ntfy/templates/setup/job.yaml @@ -0,0 +1,61 @@ +{{- if .Values.ntfy.webPush.keys.create }} +--- +{{- $fullname := (include "ntfy.fullname" .) }} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ $fullname }}-setup + labels: + {{- include "ntfy.labels" . | nindent 4 }} + app.kubernetes.io/component: setup-job +spec: + template: + metadata: + labels: + {{- include "ntfy.labels" . | nindent 8 }} + app.kubernetes.io/component: setup-job + spec: + restartPolicy: "Never" + serviceAccount: {{ $fullname }}-setup + containers: + - name: upload-config + image: "{{ .Values.kubectl.image.registry }}/{{ .Values.kubectl.image.repository }}:{{ .Values.kubectl.image.tag }}" + command: + - sh + - -c + - | + # check if key already exists + key=$(kubectl get secret {{ $fullname }}-env -o jsonpath="{.data['NTFY_WEB_PUSH_PRIVATE_KEY']}" 2> /dev/null) + [ $? -ne 0 ] && echo "Failed to get existing secret" && exit 1 + [ -n "$key" ] && echo "Config already created, exiting." && exit 0 + # wait for config + while [ ! -f /data/output ]; do + echo "Waiting for config.." + sleep 5; + done + # update secret + public=$(grep -Po 'web-push-public-key: \K[^$]*' /data/output) + private=$(grep -Po 'web-push-private-key: \K[^$]*' /data/output) + kubectl patch secret {{ $fullname }}-env -p '{"data":{"NTFY_WEB_PUSH_PRIVATE_KEY":"'$(echo -n "$private" | base64 -w 0)'","NTFY_WEB_PUSH_PUBLIC_KEY":"'$(echo -n "$public" | base64 -w 0)'"}}' + [ $? -ne 0 ] && echo "Failed to update secret." && exit 1 + echo "VAPID/WebPush successfully setup with public-key: ${public}" + volumeMounts: + - mountPath: /data/ + name: data + readOnly: true + - name: generate-config + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default (printf "v%s" .Chart.AppVersion) }}" + command: + - sh + - -c + - ntfy webpush keys 2> /data/output + volumeMounts: + - mountPath: /data/ + name: data + volumes: + - name: data + emptyDir: {} + parallelism: 1 + completions: 1 + backoffLimit: 1 +{{- end }} diff --git a/ntfy/templates/setup/role.yaml b/ntfy/templates/setup/role.yaml new file mode 100644 index 0000000..23d93da --- /dev/null +++ b/ntfy/templates/setup/role.yaml @@ -0,0 +1,22 @@ +{{- if .Values.ntfy.webPush.keys.create }} +--- +{{- $fullname := (include "ntfy.fullname" .) }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ $fullname }}-setup + labels: + {{- include "ntfy.labels" . | nindent 4 }} + app.kubernetes.io/component: setup-job +rules: + - apiGroups: + - "" + resources: + - secrets + resourceNames: + - {{ $fullname }}-env + verbs: + - get + - update + - patch +{{- end }} diff --git a/ntfy/templates/setup/rolebinding.yaml b/ntfy/templates/setup/rolebinding.yaml new file mode 100644 index 0000000..64eab0f --- /dev/null +++ b/ntfy/templates/setup/rolebinding.yaml @@ -0,0 +1,19 @@ +{{- if .Values.ntfy.webPush.keys.create }} +--- +{{- $fullname := (include "ntfy.fullname" .) }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ $fullname }}-setup + labels: + {{- include "ntfy.labels" . | nindent 4 }} + app.kubernetes.io/component: setup-job +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ $fullname }}-setup +subjects: + - kind: ServiceAccount + name: {{ $fullname }}-setup + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/ntfy/templates/setup/serviceaccount.yaml b/ntfy/templates/setup/serviceaccount.yaml new file mode 100644 index 0000000..1b5d727 --- /dev/null +++ b/ntfy/templates/setup/serviceaccount.yaml @@ -0,0 +1,9 @@ +{{- if .Values.ntfy.webPush.keys.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "ntfy.fullname" . }}-setup + labels: + {{- include "ntfy.labels" . | nindent 4 }} + app.kubernetes.io/component: setup-job +{{- end }} diff --git a/ntfy/values.yaml b/ntfy/values.yaml index 1047f8f..3644059 100644 --- a/ntfy/values.yaml +++ b/ntfy/values.yaml @@ -10,6 +10,14 @@ image: # Overrides the image tag whose default is the chart appVersion. tag: "" +kubectl: + # -- image needed for setup (store generated VAPID / WebPush keys) + image: + registry: docker.io + repository: bitnami/kubectl + pullPolicy: IfNotPresent + tag: 1.30.3 + imagePullSecrets: [] nameOverride: "" fullnameOverride: "" @@ -66,6 +74,13 @@ ntfy: server: domain: null addrPrefix: null + webPush: + keys: + create: false + public: + private: + file: "/data/webpush.db" + emailAddress: "" globalTopicLimit: 15000 visitor: subscriptionLimit: 30