Zigbee2Mqtt Kubernetes Setup on Ubuntu

Install the k8s cluster if not alreadly installed

1
2
microk8s enable dns storage helm3
microk8s status

Pull the helm chart

1
2
microk8s helm repo add truecharts https://charts.truecharts.org/
microk8s helm pull truecharts/zigbee2mqtt --version 7.0.30

Modify the values.yaml file to set the configuration

1
2
3
tar -xvf ./zigbee2mqtt-*.tgz
cd zigbee2mqtt
cat values.yamls
1
2
3
4
5
6
EXTERNAL_IP: A.B.C.D
EXTERNAL_NETWORK: A.B.C.0
SERVICE_PORT: Port used by the application
ZIGBEE_ADAPTER_IP: Ip address of the zigbee adapter
ZIGBEE_ZIGBEE_ADAPTER_PORT: Port used by the external zigbee adapter
MQTT_PORT: PORT_C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
image:
repository: tccr.io/truecharts/zigbee2mqtt
tag: v1.32.1@sha256:f3bcf64a1a538ce5636b7359bd4f0375f593c9408d561a1add9f3d2bed843bf3
pullPolicy: IfNotPresent
service:
main:
ports:
main:
port: SERVICE_PORT
persistence:
data:
enabled: true
mountPath: "/data"
targetSelectAll: true

portal:
open:
enabled: true
securityContext:
container:
runAsNonRoot: false
readOnlyRootFilesystem: false
runAsUser: 0
runAsGroup: 0
workload:
main:
podSpec:
initContainers:
init-config:
enabled: true
imageSelector: image
type: init
env:
ZIGBEE2MQTT_CONFIG_FRONTEND_PORT: "{{ .Values.service.main.ports.main.port }}"
ZIGBEE2MQTT_CONFIG_EXPIRIMENTAL_NEW_API: "{{ .Values.workload.main.podSpec.containers.main.env.ZIGBEE2MQTT_CONFIG_EXPIRIMENTAL_NEW_API }}"
ZIGBEE2MQTT_CONFIG_PERMIT_JOIN: "{{ .Values.workload.main.podSpec.containers.main.env.ZIGBEE2MQTT_CONFIG_PERMIT_JOIN }}"
ZIGBEE2MQTT_CONFIG_MQTT_SERVER: "{{ .Values.workload.main.podSpec.containers.main.env.ZIGBEE2MQTT_CONFIG_MQTT_SERVER }}"
ZIGBEE2MQTT_CONFIG_MQTT_USER: "{{ .Values.secret.ZIGBEE2MQTT_CONFIG_MQTT_USER }}"
ZIGBEE2MQTT_CONFIG_MQTT_PASSWORD: "{{ .Values.secret.ZIGBEE2MQTT_CONFIG_MQTT_PASSWORD }}"
ZIGBEE2MQTT_CONFIG_MQTT_BASE_TOPIC: "{{ .Values.workload.main.podSpec.containers.main.env.ZIGBEE2MQTT_CONFIG_MQTT_BASE_TOPIC }}"
ZIGBEE2MQTT_CONFIG_SERIAL_PORT: "{{ .Values.workload.main.podSpec.containers.main.env.ZIGBEE2MQTT_CONFIG_SERIAL_PORT }}"
ZIGBEE2MQTT_CONFIG_SERIAL_ADAPTER: "{{ .Values.workload.main.podSpec.containers.main.env.ZIGBEE2MQTT_CONFIG_SERIAL_ADAPTER }}"
USE_CUSTOM_CONFIG_FILE: "{{ .Values.workload.main.podSpec.containers.main.env.USE_CUSTOM_CONFIG_FILE }}"
command:
- /bin/sh
- -c
args:
- >
if [ -f /data/configuration.yaml ] || [ ${USE_CUSTOM_CONFIG_FILE} == true ]; then

echo "Initial configuration exists or User selected to use custom configuration file. Skipping...";
else

echo "Creating initial configuration";
touch /data/configuration.yaml;
echo "# Configuration bellow will be always be overridden" >> /data/configuration.yaml;
echo "# from environment settings on the Scale Apps UI." >> /data/configuration.yaml;
echo "# You however will not see this values change in the file." >> /data/configuration.yaml;
echo "# It's a generated file based on the values provided on initial install." >> /data/configuration.yaml;
echo "##########################################################" >> /data/configuration.yaml;
echo "experimental:" >> /data/configuration.yaml;
echo " new_api: $ZIGBEE2MQTT_CONFIG_EXPIRIMENTAL_NEW_API" >> /data/configuration.yaml;
echo "frontend:" >> /data/configuration.yaml;
echo " port: $ZIGBEE2MQTT_CONFIG_FRONTEND_PORT" >> /data/configuration.yaml;
echo "permit_join: $ZIGBEE2MQTT_CONFIG_PERMIT_JOIN" >> /data/configuration.yaml;
echo "mqtt:" >> /data/configuration.yaml;
echo " server: $ZIGBEE2MQTT_CONFIG_MQTT_SERVER" >> /data/configuration.yaml;
echo " base_topic: $ZIGBEE2MQTT_CONFIG_MQTT_BASE_TOPIC" >> /data/configuration.yaml;
if [ ! -z "$ZIGBEE2MQTT_CONFIG_MQTT_USER" ];
then
echo " user: $ZIGBEE2MQTT_CONFIG_MQTT_USER" >> /data/configuration.yaml;
fi;
if [ ! -z "$ZIGBEE2MQTT_CONFIG_MQTT_PASSWORD" ];
then
echo " password: $ZIGBEE2MQTT_CONFIG_MQTT_PASSWORD" >> /data/configuration.yaml;
fi;
echo "serial:" >> /data/configuration.yaml;
echo " port: $ZIGBEE2MQTT_CONFIG_SERIAL_PORT" >> /data/configuration.yaml;
echo " adapter: $ZIGBEE2MQTT_CONFIG_SERIAL_ADAPTER" >> /data/configuration.yaml;
echo "##########################################################" >> /data/configuration.yaml;
echo 'Initial configuration file created at "/data/configuration.yaml"';
fi;
containers:
main:
env:
ZIGBEE2MQTT_DATA: "/data"
ZIGBEE2MQTT_CONFIG_FRONTEND_PORT: "{{ .Values.service.main.ports.main.port }}"
# User defined
USE_CUSTOM_CONFIG_FILE: false
# This values are required for the autogenerated file to work.
ZIGBEE2MQTT_CONFIG_EXPIRIMENTAL_NEW_API: false
ZIGBEE2MQTT_CONFIG_PERMIT_JOIN: false
ZIGBEE2MQTT_CONFIG_MQTT_SERVER: "mqtt://mosquitto:MQTT_PORT"
ZIGBEE2MQTT_CONFIG_MQTT_BASE_TOPIC: "zigbee2mqtt"
ZIGBEE2MQTT_CONFIG_SERIAL_PORT: "tcp://ZIGBEE_ADAPTER_IP:ZIGBEE_ADAPTER_PORT"
ZIGBEE2MQTT_CONFIG_SERIAL_ADAPTER: "auto"

ZIGBEE2MQTT_CONFIG_MQTT_USER: ""
ZIGBEE2MQTT_CONFIG_MQTT_PASSWORD: ""

Service

zigbee2mqtt-service.yaml

SERVICE_PORT: Port used to access the application
ZIGBEE_ADAPTER_PORT: Port used to allow access to an external zigbee controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: v1
kind: Service
metadata:
name: zigbee2mqtt-service
spec:
type: LoadBalancer
selector:
app.kubernetes.io/name: zigbee2mqtt
ports:
- name: http
protocol: TCP
port: SERVICE_PORT
targetPort: SERVICE_PORT
- name: adapter
protocol: TCP
port: ZIGBEE_ADAPTER_PORT
targetPort: ZIGBEE_ADAPTER_PORT
externalIPs:
- A.B.C.D

Firewall

sudo ufw allow from A.B.C.0/24 to any port ZIGBEE_ADAPTER_PORT proto tcp
sudo ufw allow from A.B.C.0/24 to any port SERVICE_PORT proto tcp

Configuration

https://www.reddit.com/r/homeassistant/comments/zxee4n/zigbee2mqtt_error_failed_to_connect_to_the/