Compare commits
14 Commits
59071cbcb5
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 73fe328336 | |||
| a079ae8ffd | |||
| dbecd67471 | |||
| 2881eb1167 | |||
| 755d68a844 | |||
| f40a899200 | |||
| d30aad3058 | |||
| 6149826bc6 | |||
| 0d2b30a83a | |||
| 001e785192 | |||
| 726f3c5bb3 | |||
| 8a9c6760d5 | |||
| 0f51497688 | |||
| dee53f847e |
42
.gitea/workflows/deploy.yaml
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
name: Casa Home Assistant CI/CD Pipeline
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- fix/*
|
||||||
|
- main
|
||||||
|
- master
|
||||||
|
pull_request:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 16 * * 0' # every sunday 4 pm
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: casa-vlan-cicd
|
||||||
|
env:
|
||||||
|
GITHUB_TEMP: ${{ runner.temp }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Fetch limbo public actions
|
||||||
|
env:
|
||||||
|
RUNNER_TEMP: "${{ runner.temp }}"
|
||||||
|
WORKSPACE: "${{ gitea.workspace }}"
|
||||||
|
run: |
|
||||||
|
curl -fsSL https://git.limbosolutions.com/kb/gitea/raw/branch/main/cloud-scripts/setup-limbo-actions.sh | bash 2>&1
|
||||||
|
|
||||||
|
- name: Setup kubectl
|
||||||
|
uses: ./.gitea/limbo_actions/kubectl-setup
|
||||||
|
with:
|
||||||
|
kube_server: ${{ secrets.CASA_VLAN_KUBE_SERVER }}
|
||||||
|
kube_ca_base64: ${{ secrets.CASA_VLAN_KUBE_CA_BASE64 }}
|
||||||
|
kube_token: ${{ secrets.CASA_VLAN_KUBE_TOKEN }}
|
||||||
|
|
||||||
|
- name: Deploy Home Assistant
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
./ops-scripts/apply-app.sh
|
||||||
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
on:
|
|
||||||
push:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 7 * * SUN' # Every Sunday at 07:00
|
|
||||||
jobs:
|
|
||||||
deploy-to-homesrv01:
|
|
||||||
runs-on: "myLimbo-casa-gitea-act-runner"
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: docker compose up
|
|
||||||
run: docker compose up -d --pull always
|
|
||||||
18
README.md
@@ -2,10 +2,9 @@
|
|||||||
|
|
||||||
Welcome to my Home Assistant setup repository.
|
Welcome to my Home Assistant setup repository.
|
||||||
This repository documents and maintains the Home Assistant instance running in my home, hosted on casa server k3s cluster.
|
This repository documents and maintains the Home Assistant instance running in my home, hosted on casa server k3s cluster.
|
||||||
All essential containers, such as MQTT and speech recognition, are hosted on the same server for seamless integration.
|
Related containers, such as MQTT and speech recognition, are hosted on same cluster.
|
||||||
|
|
||||||
<!-- omit in toc -->
|
**Table of Contents:**
|
||||||
## Table of Contents
|
|
||||||
|
|
||||||
- [Devices](#devices)
|
- [Devices](#devices)
|
||||||
- [Broadlink - RM4 Pro](#broadlink---rm4-pro)
|
- [Broadlink - RM4 Pro](#broadlink---rm4-pro)
|
||||||
@@ -37,7 +36,7 @@ All essential containers, such as MQTT and speech recognition, are hosted on the
|
|||||||
|
|
||||||
Using as Ir blaster for living room devices and temperature meter.
|
Using as Ir blaster for living room devices and temperature meter.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
**Integrations:**
|
**Integrations:**
|
||||||
|
|
||||||
@@ -51,7 +50,7 @@ Currently controlling:
|
|||||||
- dining table lights
|
- dining table lights
|
||||||
- office room lights
|
- office room lights
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
**Integrations:**
|
**Integrations:**
|
||||||
|
|
||||||
@@ -68,7 +67,7 @@ Currently controlling:
|
|||||||
- shellyplug-s-80646F80FB14.dev.lan
|
- shellyplug-s-80646F80FB14.dev.lan
|
||||||
- gaia.dev.lan (proxmox server)
|
- gaia.dev.lan (proxmox server)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Devices connected to IOT lan.
|
Devices connected to IOT lan.
|
||||||
|
|
||||||
@@ -102,7 +101,7 @@ Using SONOFF Universal Zigbee 3.0 USB Dongle Plus.
|
|||||||
|
|
||||||
The [broadlink integration](https://www.home-assistant.io/integrations/broadlink) allows you to control and monitor Broadlink universal remotes, smart plugs, power strips, switches and sensors.
|
The [broadlink integration](https://www.home-assistant.io/integrations/broadlink) allows you to control and monitor Broadlink universal remotes, smart plugs, power strips, switches and sensors.
|
||||||
|
|
||||||
.
|
.
|
||||||
|
|
||||||
Devices:
|
Devices:
|
||||||
|
|
||||||
@@ -255,5 +254,6 @@ Home Assistant authenticates with Xbox Live through OAuth2 using the Home Assist
|
|||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
[Check folder setup](./setup).
|
``` bash
|
||||||
|
./ops-scripts/apply-app.sh
|
||||||
|
```
|
||||||
|
|||||||
7
deploy/app/kustomization.yaml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- pvc.yaml
|
||||||
|
- statefulset.yaml
|
||||||
|
generatorOptions:
|
||||||
|
disableNameSuffixHash: true
|
||||||
12
deploy/app/pvc.yaml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: home-assistant-config
|
||||||
|
namespace: home-assistant
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 8Gi
|
||||||
|
storageClassName: local-path
|
||||||
@@ -1,23 +1,3 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Namespace
|
|
||||||
metadata:
|
|
||||||
name: home-assistant
|
|
||||||
---
|
|
||||||
|
|
||||||
apiVersion: v1
|
|
||||||
kind: PersistentVolumeClaim
|
|
||||||
metadata:
|
|
||||||
name: home-assistant-config
|
|
||||||
namespace: home-assistant
|
|
||||||
spec:
|
|
||||||
accessModes:
|
|
||||||
- ReadWriteOnce
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
storage: 8Gi
|
|
||||||
storageClassName: local-path
|
|
||||||
---
|
|
||||||
|
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: StatefulSet
|
kind: StatefulSet
|
||||||
metadata:
|
metadata:
|
||||||
@@ -35,20 +15,31 @@ spec:
|
|||||||
labels:
|
labels:
|
||||||
app: home-assistant
|
app: home-assistant
|
||||||
spec:
|
spec:
|
||||||
|
dnsPolicy: ClusterFirstWithHostNet # ensures pod uses cluster DNS (CoreDNS) for service discovery even with host networking
|
||||||
hostNetwork: true
|
hostNetwork: true
|
||||||
|
nodeName: casa # force deploy to master node cluster
|
||||||
|
tolerations:
|
||||||
|
- key: "node-role.kubernetes.io/control-plane" # allow installation on control-plane
|
||||||
|
operator: "Exists"
|
||||||
|
effect: "NoSchedule"
|
||||||
containers:
|
containers:
|
||||||
- name: home-assistant
|
- name: home-assistant
|
||||||
image: "homeassistant/home-assistant"
|
image: "homeassistant/home-assistant"
|
||||||
|
imagePullPolicy: Always
|
||||||
|
env:
|
||||||
|
- name: TZ
|
||||||
|
value: Europe/Lisbon
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: home-assistant-config
|
- name: home-assistant-config
|
||||||
mountPath: /config
|
mountPath: /config
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
memory: "512Mi"
|
memory: "256Mi"
|
||||||
cpu: "400m"
|
cpu: "400m"
|
||||||
limits:
|
limits:
|
||||||
memory: "700Mi"
|
memory: "724Mi"
|
||||||
cpu: "1000m"
|
cpu: "1000m"
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
- name: home-assistant-config
|
- name: home-assistant-config
|
||||||
persistentVolumeClaim:
|
persistentVolumeClaim:
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: home-assistant-external
|
|
||||||
namespace: home-assistant
|
|
||||||
spec:
|
|
||||||
clusterIP: None
|
|
||||||
ports:
|
|
||||||
- port: 8123
|
|
||||||
protocol: TCP
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Endpoints
|
|
||||||
metadata:
|
|
||||||
name: home-assistant-external
|
|
||||||
namespace: home-assistant
|
|
||||||
subsets:
|
|
||||||
- addresses:
|
|
||||||
- ip: 192.168.14.9 # Replace with your actual external IP
|
|
||||||
ports:
|
|
||||||
- port: 8123
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
|
|
||||||
apiVersion: traefik.io/v1alpha1
|
|
||||||
kind: IngressRoute
|
|
||||||
metadata:
|
|
||||||
name: home-assistant
|
|
||||||
namespace: home-assistant
|
|
||||||
spec:
|
|
||||||
entryPoints:
|
|
||||||
- websecure
|
|
||||||
routes:
|
|
||||||
- match: Host(`casa.limbosolutions.com`)
|
|
||||||
kind: Rule
|
|
||||||
services:
|
|
||||||
- name: home-assistant-external
|
|
||||||
port: 8123
|
|
||||||
- match: Host(`has.casa.limbosolutions.com`)
|
|
||||||
kind: Rule
|
|
||||||
services:
|
|
||||||
- name: home-assistant-external
|
|
||||||
port: 8123
|
|
||||||
tls:
|
|
||||||
secretName: casa-limbosolutions-com-tls
|
|
||||||
51
deploy/infra/README.md
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
# Home Assistant Deploy
|
||||||
|
|
||||||
|
## Namespace
|
||||||
|
|
||||||
|
```bash { cwd=../ terminalRows=15 }
|
||||||
|
# from repo root folder
|
||||||
|
kubectl create namespace home-assistant
|
||||||
|
```
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
### Environments requirements
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
#./deploy/.env
|
||||||
|
|
||||||
|
export ENDPOINT_IP="xxx.xxx.xxx.xxxx"
|
||||||
|
export SERVICE_PORT=xxxx
|
||||||
|
export INGRESS_ROUTES_MATCH="Host(`xxxx`)"
|
||||||
|
export INGRESS_TLS_SECRET_NAME=xxxxxx
|
||||||
|
```
|
||||||
|
|
||||||
|
## Test Templates
|
||||||
|
|
||||||
|
```bash { cwd=../ terminalRows=15 }
|
||||||
|
# from repo root folder
|
||||||
|
source ./deploy/.env \
|
||||||
|
&& cat ./deploy/deployment.yaml \
|
||||||
|
&& envsubst < ./deploy/service.template.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
## Deploy
|
||||||
|
|
||||||
|
```bash { cwd=../ terminalRows=15 }
|
||||||
|
# from repo root folder
|
||||||
|
source ./deploy/.env \
|
||||||
|
&& kubectl apply -f ./deploy/deployment.yaml \
|
||||||
|
&& envsubst < ./deploy/service.template.yaml | kubectl apply -f -
|
||||||
|
```
|
||||||
|
|
||||||
|
## Continuos Deploy
|
||||||
|
|
||||||
|
All Environment variables requirements as set as secrets.
|
||||||
|
|
||||||
|
[gitea workflow](../.gitea/workflows/deploy.yaml)
|
||||||
|
|
||||||
|
## cicd RBAC
|
||||||
|
|
||||||
|
```bash { cwd=../ }
|
||||||
|
kubectl apply -f ./deploy/cicd-rbac.yaml
|
||||||
|
```
|
||||||
34
deploy/infra/cicd-rbac.yaml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
|
||||||
|
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
namespace: home-assistant
|
||||||
|
name: ci-cd
|
||||||
|
rules:
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["pods", "services", "secrets", "configmaps", "persistentvolumeclaims", "endpoints"]
|
||||||
|
verbs: ["get", "watch", "list", "create", "update", "patch", "delete"]
|
||||||
|
- apiGroups: ["apps"]
|
||||||
|
resources: ["deployments", "statefulsets"]
|
||||||
|
verbs: ["get", "watch", "list", "create", "update", "patch", "delete"]
|
||||||
|
- apiGroups: ["networking.k8s.io"]
|
||||||
|
resources: ["ingresses"]
|
||||||
|
verbs: ["get", "watch", "list", "create", "update", "patch", "delete"]
|
||||||
|
- apiGroups: ["traefik.io"]
|
||||||
|
resources: ["ingressroutes"]
|
||||||
|
verbs: ["get", "watch", "list", "create", "update", "patch", "delete"]
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: RoleBinding
|
||||||
|
metadata:
|
||||||
|
name: ci-cd
|
||||||
|
namespace: home-assistant
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: casa-ci-cd
|
||||||
|
namespace: home-assistant
|
||||||
|
roleRef:
|
||||||
|
kind: Role
|
||||||
|
name: ci-cd
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
7
deploy/infra/service-account-secret.yaml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: casa-ci-cd
|
||||||
|
annotations:
|
||||||
|
kubernetes.io/service-account.name: casa-ci-cd
|
||||||
|
type: kubernetes.io/service-account-token
|
||||||
6
deploy/infra/service-account.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: casa-ci-cd
|
||||||
|
namespace: home-assistant
|
||||||
42
deploy/infra/service.template.yaml
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: home-assistant
|
||||||
|
namespace: home-assistant
|
||||||
|
spec:
|
||||||
|
clusterIP: None
|
||||||
|
ports:
|
||||||
|
- port: ${SERVICE_PORT}
|
||||||
|
protocol: TCP
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Endpoints
|
||||||
|
metadata:
|
||||||
|
name: home-assistant
|
||||||
|
namespace: home-assistant
|
||||||
|
subsets:
|
||||||
|
- addresses:
|
||||||
|
- ip: ${ENDPOINT_IP}
|
||||||
|
ports:
|
||||||
|
- port: ${SERVICE_PORT}
|
||||||
|
---
|
||||||
|
|
||||||
|
apiVersion: traefik.io/v1alpha1
|
||||||
|
kind: IngressRoute
|
||||||
|
metadata:
|
||||||
|
name: home-assistant
|
||||||
|
namespace: home-assistant
|
||||||
|
spec:
|
||||||
|
entryPoints:
|
||||||
|
- websecure
|
||||||
|
routes:
|
||||||
|
- match: ${INGRESS_ROUTES_MATCH}
|
||||||
|
kind: Rule
|
||||||
|
services:
|
||||||
|
- name: home-assistant
|
||||||
|
port: ${SERVICE_PORT}
|
||||||
|
tls:
|
||||||
|
secretName: ${INGRESS_TLS_SECRET_NAME}
|
||||||
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.4 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 128 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
55
docs/tests.md
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
# tests
|
||||||
|
|
||||||
|
## logs from loki
|
||||||
|
|
||||||
|
```python
|
||||||
|
# loki-get-last-to-sensor.py
|
||||||
|
import sys, os, requests, datetime, time, json
|
||||||
|
|
||||||
|
url = os.environ.get("LOKI_ADDRESS")
|
||||||
|
|
||||||
|
if not url:
|
||||||
|
print(json.dumps({"state": "error", "log_message": "LOKI_ADDRESS is not set or empty"}))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
query = os.environ.get("LOKI_QUERY")
|
||||||
|
if not query:
|
||||||
|
print(json.dumps({"state": "error", "log_message": "LOKI_ADDRESS is not set or empty"}))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
end = int(time.time()) * 1_000_000_000
|
||||||
|
start = (int(time.time()) - 24*60*60) * 1_000_000_000
|
||||||
|
|
||||||
|
|
||||||
|
params = {
|
||||||
|
"query": query,
|
||||||
|
"limit": 1,
|
||||||
|
"direction": "backward",
|
||||||
|
"start": str(start),
|
||||||
|
"end": str(end),
|
||||||
|
}
|
||||||
|
|
||||||
|
resp = requests.get(url, params=params)
|
||||||
|
data = resp.json()
|
||||||
|
|
||||||
|
try:
|
||||||
|
ns = int(data["data"]["result"][0]["values"][0][0])
|
||||||
|
ts = ns / 1_000_000_000
|
||||||
|
dt = datetime.datetime.fromtimestamp(ts).strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
|
print(json.dumps({
|
||||||
|
"state": dt,
|
||||||
|
}))
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
print(json.dumps({"state": "unknown"}))
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# example of the sensor
|
||||||
|
name: git_limbosolutions_com_last_pbs_backup
|
||||||
|
command: >
|
||||||
|
LOKI_ADDRESS=${LOKI_ADDRESS} LOKI_QUERY="{job=\"git-limbosolutions-com/pbs-backup\"} |= \"INFO: Finished Backup\"" python3 /config/scripts/loki-get-last-to-sensor.py
|
||||||
|
value_template: "{{ value }}"
|
||||||
|
```
|
||||||
5
ops-scripts/apply-app.sh
Executable file
@@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
echo "Executing app deploy."
|
||||||
|
|
||||||
|
kubectl kustomize deploy/app | kubectl apply -f -
|
||||||
5
ops-scripts/apply-infra.sh
Executable file
@@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
echo "Executing infra deploy."
|
||||||
|
|
||||||
|
kubectl kustomize deploy/infra | kubectl apply -f -
|
||||||