I’ve been using Smartthings as my smart home hub for a while. And I’d like to migrate to something that’s open source (or more importantly, self-hosted). There’s been a few horror stories out there that make me worry about the potential “hostage” situation. (e.g. manufacturers charging a monthly price for the service, or flat-out discontinuing the service).
Hardware
I bought a Dell Wyse N03D Thin Client off eBay at $35 each, complete with power supply, keyboard and mouse. The thin client is definitely not a powerhouse, but it’s dual core x86-64 processor and 4GB of RAM should be plenty sufficient for my use case. To let it connect to Z-Wave and ZigBee devices, I also paired it with a dongle.
Software
OS
The thin client came with Windows 7 Embedded pre-installed, which I absolutely don’t need. I replaced it with a fresh install of Ubuntu Server 20.04 LTS. As the thin client only has 16G of onboard storage, I modified the default partitioning scheme to get more space to the rootfs.
Kubernetes
I chose k3s for this project. It’s small size is a perfect fit. For the installation, running the following snippet is sufficient.
curl -sfL https://get.k3s.io | sh -
Running rancher is always a good idea. To have rancher installed on k3s, add the following manifest to /var/lib/rancher/k3s/server/manifests
--- apiVersion: v1 kind: Namespace metadata: name: cattle-system --- apiVersion: helm.cattle.io/v1 kind: HelmChart metadata: name: rancher namespace: kube-system spec: chart: https://releases.rancher.com/server-charts/stable/rancher-2.5.8.tgz targetNamespace: cattle-system valuesContent: |- hostname: [REDACTED] tls: external replicas: 1
This works because k3s comes with a helm CRD.
Following that, apply the following manifest to get home-assistant and its friends installed.
--- apiVersion: v1 kind: Namespace metadata: name: home-assistant --- apiVersion: v1 kind: Service metadata: namespace: home-assistant name: home-assistant spec: selector: app: home-assistant ports: - name: http protocol: TCP port: 80 targetPort: 8123 --- apiVersion: apps/v1 kind: Deployment metadata: namespace: home-assistant name: home-assistant labels: app: home-assistant spec: replicas: 1 selector: matchLabels: app: home-assistant template: metadata: labels: app: home-assistant spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - homelab-us-east-1-nano-1 containers: - name: home-assistant image: homeassistant/home-assistant:stable ports: - containerPort: 8123 volumeMounts: - mountPath: /config name: config - mountPath: /dev/ttyUSB1 name: zigbee securityContext: privileged: true volumes: - name: config hostPath: path: /etc/home-assistant type: DirectoryOrCreate - name: zigbee hostPath: path: /dev/ttyUSB1 --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: namespace: home-assistant name: home-assistant spec: rules: - host: [REDACTED] http: paths: - pathType: Prefix path: / backend: service: name: home-assistant port: number: 80 --- apiVersion: v1 kind: Service metadata: namespace: home-assistant name: zwavejs2mqtt spec: selector: app: zwavejs2mqtt type: NodePort ports: - name: http protocol: TCP port: 8091 targetPort: 8091 nodePort: 30091 - name: ws protocol: TCP port: 3000 targetPort: 3000 --- apiVersion: apps/v1 kind: Deployment metadata: namespace: home-assistant name: zwavejs2mqtt labels: app: zwavejs2mqtt spec: replicas: 1 selector: matchLabels: app: zwavejs2mqtt template: metadata: labels: app: zwavejs2mqtt spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - homelab-us-east-1-nano-1 containers: - name: zwavejs2mqtt image: zwavejs/zwavejs2mqtt:4.5.1 ports: - containerPort: 8091 - containerPort: 3000 volumeMounts: - mountPath: /usr/src/app/store name: config - mountPath: /dev/ttyUSB0 name: zwave securityContext: privileged: true volumes: - name: config hostPath: path: /etc/zwavejs2mqtt type: DirectoryOrCreate - name: zwave hostPath: path: /dev/ttyUSB0
Done
I also used Cloudflare Argo tunnel to allow me to control my home automation outside of my house.