From 739a59fa0227524ef55236d349b8709c33216a0e Mon Sep 17 00:00:00 2001 From: "azykov@mail.ru" Date: Tue, 21 Jul 2026 22:13:15 +0300 Subject: [PATCH] mosquitto --- clusters/base/apps/mosquitto/chart/Chart.yaml | 6 ++ .../mosquitto/chart/templates/_helpers.tpl | 14 ++++ .../mosquitto/chart/templates/configmap.yaml | 22 ++++++ .../mosquitto/chart/templates/service.yaml | 25 +++++++ .../chart/templates/statefulset.yaml | 70 +++++++++++++++++++ .../base/apps/mosquitto/chart/values.yaml | 38 ++++++++++ clusters/base/apps/mosquitto/helmrelease.yaml | 50 +++++++++++++ .../base/apps/mosquitto/kustomization.yaml | 5 ++ clusters/base/apps/mosquitto/secret.enc.yaml | 22 ++++++ clusters/base/namespaces/mqtt.yaml | 4 ++ clusters/home/apps/kustomization.yaml | 1 + clusters/home/apps/mosquitto.yaml | 18 +++++ clusters/home/namespaces/kustomization.yaml | 1 + 13 files changed, 276 insertions(+) create mode 100644 clusters/base/apps/mosquitto/chart/Chart.yaml create mode 100644 clusters/base/apps/mosquitto/chart/templates/_helpers.tpl create mode 100644 clusters/base/apps/mosquitto/chart/templates/configmap.yaml create mode 100644 clusters/base/apps/mosquitto/chart/templates/service.yaml create mode 100644 clusters/base/apps/mosquitto/chart/templates/statefulset.yaml create mode 100644 clusters/base/apps/mosquitto/chart/values.yaml create mode 100644 clusters/base/apps/mosquitto/helmrelease.yaml create mode 100644 clusters/base/apps/mosquitto/kustomization.yaml create mode 100644 clusters/base/apps/mosquitto/secret.enc.yaml create mode 100644 clusters/base/namespaces/mqtt.yaml create mode 100644 clusters/home/apps/mosquitto.yaml diff --git a/clusters/base/apps/mosquitto/chart/Chart.yaml b/clusters/base/apps/mosquitto/chart/Chart.yaml new file mode 100644 index 0000000..8105adf --- /dev/null +++ b/clusters/base/apps/mosquitto/chart/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: mosquitto +description: Single-node Eclipse Mosquitto MQTT broker for homelab IoT +type: application +version: 0.1.0 +appVersion: "2" diff --git a/clusters/base/apps/mosquitto/chart/templates/_helpers.tpl b/clusters/base/apps/mosquitto/chart/templates/_helpers.tpl new file mode 100644 index 0000000..f7502f4 --- /dev/null +++ b/clusters/base/apps/mosquitto/chart/templates/_helpers.tpl @@ -0,0 +1,14 @@ +{{- define "mosquitto.fullname" -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- define "mosquitto.labels" -}} +app.kubernetes.io/name: mosquitto +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{- define "mosquitto.selectorLabels" -}} +app.kubernetes.io/name: mosquitto +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} diff --git a/clusters/base/apps/mosquitto/chart/templates/configmap.yaml b/clusters/base/apps/mosquitto/chart/templates/configmap.yaml new file mode 100644 index 0000000..e1542f1 --- /dev/null +++ b/clusters/base/apps/mosquitto/chart/templates/configmap.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "mosquitto.fullname" . }}-config + labels: + {{- include "mosquitto.labels" . | nindent 4 }} +data: + mosquitto.conf: | + persistence true + persistence_location /mosquitto/data/ + log_dest stdout + + listener {{ .Values.service.mqttPort }} + allow_anonymous false + password_file /mosquitto/secrets/{{ .Values.auth.secretKey }} + + {{- if .Values.websockets.enabled }} + listener {{ .Values.websockets.port }} + protocol websockets + allow_anonymous false + password_file /mosquitto/secrets/{{ .Values.auth.secretKey }} + {{- end }} diff --git a/clusters/base/apps/mosquitto/chart/templates/service.yaml b/clusters/base/apps/mosquitto/chart/templates/service.yaml new file mode 100644 index 0000000..c73c45d --- /dev/null +++ b/clusters/base/apps/mosquitto/chart/templates/service.yaml @@ -0,0 +1,25 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "mosquitto.fullname" . }} + labels: + {{- include "mosquitto.labels" . | nindent 4 }} + {{- if .Values.service.loadBalancerPool }} + loadBalancerPool: {{ .Values.service.loadBalancerPool }} + {{- end }} +spec: + type: {{ .Values.service.type }} + {{- if .Values.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.service.loadBalancerIP }} + {{- end }} + selector: + {{- include "mosquitto.selectorLabels" . | nindent 4 }} + ports: + - name: mqtt + port: {{ .Values.service.mqttPort }} + targetPort: mqtt + {{- if .Values.websockets.enabled }} + - name: ws + port: {{ .Values.websockets.port }} + targetPort: ws + {{- end }} diff --git a/clusters/base/apps/mosquitto/chart/templates/statefulset.yaml b/clusters/base/apps/mosquitto/chart/templates/statefulset.yaml new file mode 100644 index 0000000..f3d7fe9 --- /dev/null +++ b/clusters/base/apps/mosquitto/chart/templates/statefulset.yaml @@ -0,0 +1,70 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "mosquitto.fullname" . }} + labels: + {{- include "mosquitto.labels" . | nindent 4 }} +spec: + serviceName: {{ include "mosquitto.fullname" . }} + replicas: 1 + selector: + matchLabels: + {{- include "mosquitto.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "mosquitto.selectorLabels" . | nindent 8 }} + spec: + securityContext: + runAsUser: {{ .Values.securityContext.runAsUser }} + runAsGroup: {{ .Values.securityContext.runAsGroup }} + fsGroup: {{ .Values.securityContext.runAsGroup }} + containers: + - name: mosquitto + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: mqtt + containerPort: {{ .Values.service.mqttPort }} + {{- if .Values.websockets.enabled }} + - name: ws + containerPort: {{ .Values.websockets.port }} + {{- end }} + env: + - name: MOSQUITTO_UNSAFE_ALLOW_SYMLINKS + value: "1" + volumeMounts: + - name: config + mountPath: /mosquitto/config + - name: secrets + mountPath: /mosquitto/secrets + readOnly: true + {{- if .Values.persistence.enabled }} + - name: data + mountPath: /mosquitto/data + {{- end }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumes: + - name: config + configMap: + name: {{ include "mosquitto.fullname" . }}-config + - name: secrets + secret: + secretName: {{ .Values.auth.existingSecret }} + defaultMode: 0400 + {{- if not .Values.persistence.enabled }} + - name: data + emptyDir: {} + {{- end }} + {{- if .Values.persistence.enabled }} + volumeClaimTemplates: + - metadata: + name: data + spec: + accessModes: ["ReadWriteOnce"] + storageClassName: {{ .Values.persistence.storageClassName }} + resources: + requests: + storage: {{ .Values.persistence.size }} + {{- end }} \ No newline at end of file diff --git a/clusters/base/apps/mosquitto/chart/values.yaml b/clusters/base/apps/mosquitto/chart/values.yaml new file mode 100644 index 0000000..507742a --- /dev/null +++ b/clusters/base/apps/mosquitto/chart/values.yaml @@ -0,0 +1,38 @@ +image: + repository: eclipse-mosquitto + tag: "2" + pullPolicy: IfNotPresent + +# not really needed, as StatefulSet has hardcoded "replicas: 1" +replicaCount: 1 + +securityContext: + runAsUser: 1883 + runAsGroup: 1883 + +persistence: + enabled: true + size: 1Gi + +service: + type: LoadBalancer + mqttPort: 1883 + loadBalancerPool: "mqtt" + # or loadBalancerIP: X.X.X.X + +auth: + # Mount a Secret with a pre-generated mosquitto passwd file instead of + # putting credentials in values.yaml / git. See README for how to create it. + existingSecret: mosquitto-passwd + secretKey: passwd + +websockets: + enabled: false + port: 9001 + +resources: + requests: + cpu: 50m + memory: 32Mi + limits: + memory: 128Mi diff --git a/clusters/base/apps/mosquitto/helmrelease.yaml b/clusters/base/apps/mosquitto/helmrelease.yaml new file mode 100644 index 0000000..3d6f107 --- /dev/null +++ b/clusters/base/apps/mosquitto/helmrelease.yaml @@ -0,0 +1,50 @@ +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: mosquitto + namespace: mqtt +spec: + interval: 30m + chart: + spec: + chart: ./clusters/base/apps/mosquitto/chart + sourceRef: + kind: GitRepository + name: flux-system + namespace: flux-system + reconcileStrategy: Revision + values: + image: + repository: eclipse-mosquitto + tag: "2" + pullPolicy: IfNotPresent + + replicaCount: 1 + + securityContext: + runAsUser: 1883 + runAsGroup: 1883 + + persistence: + enabled: true + size: 1Gi + + service: + type: LoadBalancer + mqttPort: 1883 + loadBalancerPool: "mqtt" + + auth: + existingSecret: mosquitto-passwd + secretKey: passwd + + websockets: + enabled: false + port: 9001 + + resources: + requests: + cpu: 50m + memory: 32Mi + limits: + memory: 128Mi diff --git a/clusters/base/apps/mosquitto/kustomization.yaml b/clusters/base/apps/mosquitto/kustomization.yaml new file mode 100644 index 0000000..c43cb47 --- /dev/null +++ b/clusters/base/apps/mosquitto/kustomization.yaml @@ -0,0 +1,5 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - secret.enc.yaml + - helmrelease.yaml diff --git a/clusters/base/apps/mosquitto/secret.enc.yaml b/clusters/base/apps/mosquitto/secret.enc.yaml new file mode 100644 index 0000000..21c0853 --- /dev/null +++ b/clusters/base/apps/mosquitto/secret.enc.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +kind: Secret +metadata: + name: mosquitto-passwd + namespace: mqtt +stringData: + passwd: ENC[AES256_GCM,data:YpTczjZ73h4Td+TmEZIgil9DN7WfVwBsi75F/t3D1oWGjGsifklnRsZUJqXiXyUwIxTxlFiWgfb01LjmILE0nB9rxoEbFdrASaLgtnCoYz/fvSZLqwCK+FSSub3+r0nJTNvxzD+bC/av8JEPNDW/8CSrHMrTrVCcLhAchOAvviRLgO18862XWcvPh1plO8luaZG38cuh+VbKKwidkwozc6B7Ghys5NfZuB1rP4vLZ6/f1PzcFRugtJ0fzzl/BA==,iv:9FKm4V/lYXott/6aVBKg4g8GtzVqgT/xndj0CKqMm+Y=,tag:41gCVbrK6Rp2IvVUt98Hpw==,type:str] +sops: + age: + - enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBMZ0xBSDQrY01xRDhwbkJp + STd0SG9MSFF2eURhVGtOS0ZyNmNrV1VqNW5vCm9kTDZWSDU1NkpoWitPNW4yY1Zj + M01yYkRGYkxLaGpIOG45ZG9Vb3VIeGMKLS0tIFA2L0FseTZNUERuTXRXcEI1bkhv + UGZha2lMZDZDbHhZdEdPYnNiTUJVNmsKRXTg0i7XdYVSZWrFww3SzJOYsU/4ZXoW + Xs1vTTO5DP5qIfLbAQUGr/jg7uu6Wm4zFCOZIURqXxU2Ws/W/3J3Wg== + -----END AGE ENCRYPTED FILE----- + recipient: age14x4jjs2fwdgw28g2pkr6jyj2yzmwc544xwmaaglrxwz5e99seutqtr8jv5 + encrypted_regex: ^(data|stringData)$ + lastmodified: "2026-07-21T19:09:49Z" + mac: ENC[AES256_GCM,data:qecTVUaC/3j/oP1DVnXEKV9Ub+k5gvGHfteol4W5I3gq8IB2YYZ+vfuinPVJJeSsN5HvK62ftnIgRNu0dtzDOrnuZENczEMwPrOz90RCUbX7WBeKh23KZ8gSSw2MBn6gsDsz1gXFWENIyjQTJFZ4qAJY6jfeH2IFC9RkpoU3j14=,iv:ksLG/aHHBAkl6aA52Xufs2vijZlpsaXccoxheYV3Gm4=,tag:4YiaPGMBWSWhVBO1tNF6vQ==,type:str] + version: 3.13.2 diff --git a/clusters/base/namespaces/mqtt.yaml b/clusters/base/namespaces/mqtt.yaml new file mode 100644 index 0000000..c90566e --- /dev/null +++ b/clusters/base/namespaces/mqtt.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: mqtt diff --git a/clusters/home/apps/kustomization.yaml b/clusters/home/apps/kustomization.yaml index e82be45..0d428d1 100644 --- a/clusters/home/apps/kustomization.yaml +++ b/clusters/home/apps/kustomization.yaml @@ -5,3 +5,4 @@ resources: - zigbee2mqtt.yaml - radicale.yaml - authelia.yaml + - mosquitto.yaml diff --git a/clusters/home/apps/mosquitto.yaml b/clusters/home/apps/mosquitto.yaml new file mode 100644 index 0000000..191b163 --- /dev/null +++ b/clusters/home/apps/mosquitto.yaml @@ -0,0 +1,18 @@ +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: mosquitto + namespace: flux-system +spec: + interval: 10m + sourceRef: + kind: GitRepository + name: flux-system + path: ./clusters/base/apps/mosquitto + prune: true + wait: true + retryInterval: 5s + decryption: + provider: sops + secretRef: + name: sops-age diff --git a/clusters/home/namespaces/kustomization.yaml b/clusters/home/namespaces/kustomization.yaml index 3273773..8e6ffad 100644 --- a/clusters/home/namespaces/kustomization.yaml +++ b/clusters/home/namespaces/kustomization.yaml @@ -7,3 +7,4 @@ resources: - ../../base/namespaces/longhorn-system.yaml - ../../base/namespaces/auth.yaml - ../../base/namespaces/metallb-system.yaml + - ../../base/namespaces/mqtt.yaml