From c4ae24dd0273fc0dd7b37bdc420e97a1f014ba24 Mon Sep 17 00:00:00 2001 From: sHa Date: Mon, 7 Sep 2026 01:05:50 +0300 Subject: [PATCH] Add eWeLink CUBE OS chart Bridges eWeLink Wi-Fi and Zigbee devices into Matter (HomeKit, Google Home, Alexa, Home Assistant). Uses a Multus macvlan interface instead of hostNetwork, since CUBE OS hardcodes host port 80/1883 which would otherwise collide with Traefik on the same node. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01BU7b2w8XZPbD7uXRfjKwcm --- cubeos/Chart.yaml | 9 ++++ cubeos/templates/deployment.yaml | 82 ++++++++++++++++++++++++++++++++ cubeos/templates/ingress.yaml | 27 +++++++++++ cubeos/templates/pvc.yaml | 18 +++++++ cubeos/templates/service.yaml | 16 +++++++ cubeos/values.yaml | 69 +++++++++++++++++++++++++++ 6 files changed, 221 insertions(+) create mode 100644 cubeos/Chart.yaml create mode 100644 cubeos/templates/deployment.yaml create mode 100644 cubeos/templates/ingress.yaml create mode 100644 cubeos/templates/pvc.yaml create mode 100644 cubeos/templates/service.yaml create mode 100644 cubeos/values.yaml diff --git a/cubeos/Chart.yaml b/cubeos/Chart.yaml new file mode 100644 index 0000000..7486e82 --- /dev/null +++ b/cubeos/Chart.yaml @@ -0,0 +1,9 @@ +apiVersion: v2 +name: cubeos +description: eWeLink CUBE OS - bridges eWeLink Wi-Fi and Zigbee devices into Matter +type: application +version: 0.1.0 +appVersion: "2.13.1" +annotations: + version-source: github-release:eWeLinkCUBE/CUBE-OS + version-pattern: "s|^v||" diff --git a/cubeos/templates/deployment.yaml b/cubeos/templates/deployment.yaml new file mode 100644 index 0000000..57a3262 --- /dev/null +++ b/cubeos/templates/deployment.yaml @@ -0,0 +1,82 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }} + labels: + app.kubernetes.io/name: {{ .Chart.Name }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + app: {{ .Release.Name }} + template: + metadata: + labels: + app: {{ .Release.Name }} + {{- if .Values.macvlan.enabled }} + annotations: + k8s.v1.cni.cncf.io/networks: '[{"name":"{{ .Values.macvlan.networkName }}","ips":["{{ required "macvlan.ip is required" .Values.macvlan.ip }}/{{ .Values.macvlan.prefixLength }}"]}]' + {{- end }} + spec: + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: {{ .Chart.Name }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + securityContext: + privileged: {{ .Values.security.privileged }} + env: + - name: TZ + value: {{ .Values.timezone | quote }} + ports: + - name: http + containerPort: 80 + protocol: TCP + - name: mqtt + containerPort: 1883 + protocol: TCP + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumeMounts: + - name: data + mountPath: /data + {{- if .Values.dbus.enabled }} + - name: dbus + mountPath: /host_dbus/system_bus_socket + readOnly: true + {{- end }} + {{- if .Values.zigbee.enabled }} + - name: zigbee-dongle + mountPath: {{ .Values.zigbee.devicePath }} + {{- end }} + volumes: + - name: data + persistentVolumeClaim: + claimName: {{ .Values.persistence.existingClaim | default (printf "%s-data" .Release.Name) }} + {{- if .Values.dbus.enabled }} + - name: dbus + hostPath: + path: /run/dbus/system_bus_socket + type: Socket + {{- end }} + {{- if .Values.zigbee.enabled }} + - name: zigbee-dongle + hostPath: + path: {{ .Values.zigbee.devicePath }} + type: CharDevice + {{- end }} diff --git a/cubeos/templates/ingress.yaml b/cubeos/templates/ingress.yaml new file mode 100644 index 0000000..9eca732 --- /dev/null +++ b/cubeos/templates/ingress.yaml @@ -0,0 +1,27 @@ +{{- range $name, $config := .Values.ingresses }} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ $.Release.Name }}-{{ $name }} + {{- with $config.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + rules: + - host: {{ $config.host }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ $.Release.Name }} + port: + number: {{ $.Values.service.port }} + {{- with $config.tls }} + tls: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/cubeos/templates/pvc.yaml b/cubeos/templates/pvc.yaml new file mode 100644 index 0000000..c50ea39 --- /dev/null +++ b/cubeos/templates/pvc.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ .Release.Name }}-data + labels: + app.kubernetes.io/name: {{ .Chart.Name }} + app.kubernetes.io/instance: {{ .Release.Name }} +spec: + accessModes: + {{- toYaml .Values.persistence.accessModes | nindent 4 }} + {{- with .Values.persistence.storageClass }} + storageClassName: {{ . }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size }} +{{- end }} diff --git a/cubeos/templates/service.yaml b/cubeos/templates/service.yaml new file mode 100644 index 0000000..ef6cea2 --- /dev/null +++ b/cubeos/templates/service.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }} + labels: + app.kubernetes.io/name: {{ .Chart.Name }} + app.kubernetes.io/instance: {{ .Release.Name }} +spec: + type: {{ .Values.service.type }} + selector: + app: {{ .Release.Name }} + ports: + - name: http + port: {{ .Values.service.port }} + targetPort: http + protocol: TCP diff --git a/cubeos/values.yaml b/cubeos/values.yaml new file mode 100644 index 0000000..7b38d4e --- /dev/null +++ b/cubeos/values.yaml @@ -0,0 +1,69 @@ +# Default values for eWeLink CUBE OS Helm Chart +image: + repository: ghcr.io/ewelinkcube/cube-os + pullPolicy: IfNotPresent + +timezone: "Europe/Kyiv" + +# CUBE OS hard-requires host-level network access for LAN device discovery, +# Matter mDNS advertisement, and its embedded MQTT broker. Instead of +# hostNetwork (which would collide with any other host-port-80 service on +# the node, e.g. Traefik), this chart attaches a Multus macvlan interface +# giving the pod its own dedicated LAN IP. The web UI (port 80) is reachable +# both directly on that macvlan IP and via the normal ClusterIP Service +# below (for Traefik ingress) -- the container binds 0.0.0.0 so both work. +# MQTT (1883) is LAN-facing only, reachable via the macvlan IP. +macvlan: + enabled: true + networkName: cubeos-macvlan + ip: "" + prefixLength: 22 + +# hostPath mounts (device passthrough) aren't enough on their own -- the +# cgroup device allowlist still blocks open() on a raw device/socket unless +# the container is privileged. Vendor docs list --privileged as required. +security: + privileged: true + +# D-Bus is only needed for CUBE OS's Matter Hub (controller) and eWeLink +# Remote (Pilot) features; skip it for basic Wi-Fi/Zigbee-to-Matter bridging. +dbus: + enabled: false + +# Zigbee dongle passthrough (optional, needs its own dedicated dongle -- +# can't be shared with another app's exclusive serial access). +zigbee: + enabled: false + devicePath: "" + +persistence: + enabled: true + existingClaim: "" + storageClass: local-path + accessModes: + - ReadWriteOnce + size: 2Gi + +resources: + requests: + cpu: "100m" + memory: "256Mi" + limits: + cpu: "2" + memory: "1Gi" + +service: + type: ClusterIP + port: 80 + +nodeSelector: {} +tolerations: [] +affinity: {} + +ingresses: {} + # https: + # host: cubeos.example.com + # annotations: {} + # tls: + # - hosts: + # - cubeos.example.com