Compare commits
21 Commits
master
..
fea4db704f
| Author | SHA1 | Date | |
|---|---|---|---|
| fea4db704f | |||
| 7df670bcc2 | |||
| ac2e287429 | |||
| 74dc2068c8 | |||
| 86687012c9 | |||
| 1c6342b2b5 | |||
| 19c564724f | |||
| 7d50ebaf22 | |||
| 0d193bcc7a | |||
| a295f671e4 | |||
| 5d7bc73f2c | |||
| d35544ca2b | |||
| 10f585819d | |||
| 3a3f64a59b | |||
| 160176f905 | |||
| d8e6d72e25 | |||
| 1b7b53ddd1 | |||
| ac33cbfc6d | |||
| cf4dd050ca | |||
| 473808832b | |||
| f29285d800 |
@@ -0,0 +1,51 @@
|
|||||||
|
name: Setup kubectl
|
||||||
|
description: "Reads kube config from inputs and sets KUBECONFIG"
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
kube_server:
|
||||||
|
description: "Kubernetes API server address"
|
||||||
|
required: true
|
||||||
|
kube_ca_base64:
|
||||||
|
description: "Base64-encoded CA certificate"
|
||||||
|
required: true
|
||||||
|
kube_token:
|
||||||
|
description: "ServiceAccount token"
|
||||||
|
required: true
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: "composite"
|
||||||
|
steps:
|
||||||
|
- name: Create kubeconfig
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -x
|
||||||
|
mkdir -p "${GITHUB_TEMP}/.kube"
|
||||||
|
|
||||||
|
cat <<EOF > "${GITHUB_TEMP}/.kube/config"
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Config
|
||||||
|
clusters:
|
||||||
|
- cluster:
|
||||||
|
certificate-authority-data: ${{ inputs.kube_ca_base64 }}
|
||||||
|
server: ${{ inputs.kube_server }}
|
||||||
|
name: cluster
|
||||||
|
contexts:
|
||||||
|
- context:
|
||||||
|
cluster: cluster
|
||||||
|
namespace: default
|
||||||
|
user: user
|
||||||
|
name: context
|
||||||
|
current-context: context
|
||||||
|
users:
|
||||||
|
- name: user
|
||||||
|
user:
|
||||||
|
token: ${{ inputs.kube_token }}
|
||||||
|
EOF
|
||||||
|
echo "config created - ${GITHUB_TEMP}/.kube/config"
|
||||||
|
ls -lah ${GITHUB_TEMP}/.kube/config
|
||||||
|
echo "KUBECONFIG=${GITHUB_TEMP}/.kube/config" >> "${GITHUB_ENV}"
|
||||||
|
|
||||||
|
# curl -vk \
|
||||||
|
# --cacert ca.crt \
|
||||||
|
# -H "Authorization: Bearer $KUBE_TOKEN" \
|
||||||
|
# https://<server>:6443/version
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
name: Casa Home Assistant CI/CD Pipeline (testing)
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- fix/*
|
||||||
|
- main
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: casa-vlan-cicd
|
||||||
|
env:
|
||||||
|
GITHUB_TEMP: ${{ runner.temp }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup kubectl
|
||||||
|
uses: ./.gitea/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
|
||||||
|
env:
|
||||||
|
ENDPOINT_IP: "${{ secrets.CASA_HOMEASSISTANT_ENDPOINT_IP }}"
|
||||||
|
SERVICE_PORT: "${{ secrets.CASA_HOMEASSISTANT_ENDPOINT_SERVICE_PORT }}"
|
||||||
|
INGRESS_ROUTES_MATCH: "${{ secrets.CASA_HOMEASSISTANT_INGRESS_ROUTES_MATCH }}"
|
||||||
|
INGRESS_TLS_SECRET_NAME: "${{ secrets.CASA_HOMEASSISTANT_INGRESS_TLS_SECRET_NAME }}"
|
||||||
|
run: |
|
||||||
|
#set -x for debugging
|
||||||
|
set -e
|
||||||
|
cd ${{ gitea.workspace }}
|
||||||
|
kubectl apply -f ./deploy/deployment.yaml
|
||||||
|
envsubst < ./deploy/service.template.yaml
|
||||||
|
|
||||||
@@ -2,9 +2,10 @@
|
|||||||
|
|
||||||
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.
|
||||||
Related containers, such as MQTT and speech recognition, are hosted on same cluster.
|
All essential containers, such as MQTT and speech recognition, are hosted on the same server for seamless integration.
|
||||||
|
|
||||||
**Table of Contents:**
|
<!-- omit in toc -->
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
- [Devices](#devices)
|
- [Devices](#devices)
|
||||||
- [Broadlink - RM4 Pro](#broadlink---rm4-pro)
|
- [Broadlink - RM4 Pro](#broadlink---rm4-pro)
|
||||||
@@ -254,8 +255,4 @@ Home Assistant authenticates with Xbox Live through OAuth2 using the Home Assist
|
|||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
Using flux for reconciliation.
|
[Deploy documentation](./deploy/README.md).
|
||||||
|
|
||||||
``` bash
|
|
||||||
./ops-scripts/apply-flux.sh
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
## RBAC
|
||||||
|
|
||||||
|
```bash { cwd=../ }
|
||||||
|
kubectl apply -f ./deploy/rbac.yaml
|
||||||
|
```
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
apiVersion: image.toolkit.fluxcd.io/v1
|
|
||||||
kind: ImagePolicy
|
|
||||||
metadata:
|
|
||||||
name: home-assistant
|
|
||||||
spec:
|
|
||||||
imageRepositoryRef:
|
|
||||||
name: home-assistant
|
|
||||||
filterTags:
|
|
||||||
pattern: '^latest$'
|
|
||||||
policy:
|
|
||||||
alphabetical: {}
|
|
||||||
digestReflectionPolicy: Always
|
|
||||||
interval: 24h
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
apiVersion: image.toolkit.fluxcd.io/v1
|
|
||||||
kind: ImageRepository
|
|
||||||
metadata:
|
|
||||||
name: home-assistant
|
|
||||||
spec:
|
|
||||||
image: homeassistant/home-assistant
|
|
||||||
interval: 72h
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
apiVersion: image.toolkit.fluxcd.io/v1
|
|
||||||
kind: ImageUpdateAutomation
|
|
||||||
metadata:
|
|
||||||
name: home-assistant
|
|
||||||
spec:
|
|
||||||
interval: 72h
|
|
||||||
sourceRef:
|
|
||||||
kind: GitRepository
|
|
||||||
name: home-assistant
|
|
||||||
git:
|
|
||||||
checkout:
|
|
||||||
ref:
|
|
||||||
branch: master
|
|
||||||
commit:
|
|
||||||
author:
|
|
||||||
name: FluxCD
|
|
||||||
email: flux@local
|
|
||||||
messageTemplate: |
|
|
||||||
Update home-assistant image.
|
|
||||||
push:
|
|
||||||
branch: master
|
|
||||||
update:
|
|
||||||
path: ./deploy/app/statefulset.yaml
|
|
||||||
strategy: Setters
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
||||||
kind: Kustomization
|
|
||||||
namespace: home-assistant
|
|
||||||
resources:
|
|
||||||
- pvc.yaml
|
|
||||||
- statefulset.yaml
|
|
||||||
- service.yaml
|
|
||||||
- image-policy.yaml
|
|
||||||
- image-repo.yaml
|
|
||||||
- image-update-automation.yaml
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: PersistentVolumeClaim
|
|
||||||
metadata:
|
|
||||||
name: home-assistant-config
|
|
||||||
spec:
|
|
||||||
accessModes:
|
|
||||||
- ReadWriteOnce
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
storage: 8Gi
|
|
||||||
storageClassName: local-path
|
|
||||||
@@ -1,7 +1,24 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
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:
|
||||||
name: home-assistant
|
name: home-assistant
|
||||||
|
namespace: home-assistant
|
||||||
labels:
|
labels:
|
||||||
app: home-assistant
|
app: home-assistant
|
||||||
spec:
|
spec:
|
||||||
@@ -16,19 +33,17 @@ spec:
|
|||||||
spec:
|
spec:
|
||||||
dnsPolicy: ClusterFirstWithHostNet # ensures pod uses cluster DNS (CoreDNS) for service discovery even with host networking
|
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
|
# delays start so host have time to start on low memory resources
|
||||||
tolerations:
|
# initContainers:
|
||||||
- key: "node-role.kubernetes.io/control-plane" # allow installation on control-plane
|
# - name: delay-start
|
||||||
operator: "Exists"
|
# image: busybox:latest
|
||||||
effect: "NoSchedule"
|
# command: ["sh", "-c", "sleep 60"]
|
||||||
containers:
|
containers:
|
||||||
- name: home-assistant
|
- name: home-assistant
|
||||||
### Maintained by flux - Image Update Automation
|
image: "homeassistant/home-assistant"
|
||||||
image: homeassistant/home-assistant:latest@sha256:aed891b8f801072302815b4b0fab5adb714182967e9d2e2d4a2be558241c73ad # {"$imagepolicy": "home-assistant:home-assistant"}
|
|
||||||
imagePullPolicy: IfNotPresent
|
|
||||||
env:
|
env:
|
||||||
- name: TZ
|
- name: TZ
|
||||||
value: Europe/Lisbon
|
value: Europe/Lisbon # set timezone
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: home-assistant-config
|
- name: home-assistant-config
|
||||||
mountPath: /config
|
mountPath: /config
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
**
|
|
||||||
!.gitignore
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
|
||||||
kind: Kustomization
|
|
||||||
metadata:
|
|
||||||
name: home-assistant
|
|
||||||
spec:
|
|
||||||
interval: 1m
|
|
||||||
sourceRef:
|
|
||||||
kind: GitRepository
|
|
||||||
name: home-assistant
|
|
||||||
path: deploy/app
|
|
||||||
prune: true
|
|
||||||
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
apiVersion: source.toolkit.fluxcd.io/v1
|
|
||||||
kind: GitRepository
|
|
||||||
metadata:
|
|
||||||
name: home-assistant
|
|
||||||
spec:
|
|
||||||
interval: 1m0s
|
|
||||||
url: ssh://git@git.limbosolutions.com:2222/marcio.fernandes/homeAssistant.git
|
|
||||||
ref:
|
|
||||||
branch: master
|
|
||||||
secretRef:
|
|
||||||
name: flux-repo-ssh-credentials
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
||||||
kind: Kustomization
|
|
||||||
namespace: home-assistant
|
|
||||||
resources:
|
|
||||||
- git-repo.yaml
|
|
||||||
- app-sync.yaml
|
|
||||||
secretGenerator:
|
|
||||||
- name: flux-repo-ssh-credentials
|
|
||||||
namespace: home-assistant
|
|
||||||
files:
|
|
||||||
- "identity=./.env.d/flux-repo-ssh-key"
|
|
||||||
- "known_hosts=./.env.d/flux-repo-ssh-known_hosts"
|
|
||||||
- "pubkey=./.env.d/flux-repo-ssh-key.pub"
|
|
||||||
- name: flux-sops-age
|
|
||||||
namespace: home-assistant
|
|
||||||
files:
|
|
||||||
- "age.agekey=./.env.d/age.agekey"
|
|
||||||
generatorOptions:
|
|
||||||
disableNameSuffixHash: true
|
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: casa-ci-cd
|
||||||
|
namespace: home-assistant
|
||||||
@@ -3,10 +3,11 @@ apiVersion: v1
|
|||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: home-assistant
|
name: home-assistant
|
||||||
|
namespace: home-assistant
|
||||||
spec:
|
spec:
|
||||||
clusterIP: None
|
clusterIP: None
|
||||||
ports:
|
ports:
|
||||||
- port: 8123
|
- port: ${SERVICE_PORT}
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -15,25 +16,27 @@ apiVersion: v1
|
|||||||
kind: Endpoints
|
kind: Endpoints
|
||||||
metadata:
|
metadata:
|
||||||
name: home-assistant
|
name: home-assistant
|
||||||
|
namespace: home-assistant
|
||||||
subsets:
|
subsets:
|
||||||
- addresses:
|
- addresses:
|
||||||
- ip: 192.168.14.9
|
- ip: ${ENDPOINT_IP}
|
||||||
ports:
|
ports:
|
||||||
- port: 8123
|
- port: ${SERVICE_PORT}
|
||||||
---
|
---
|
||||||
|
|
||||||
apiVersion: traefik.io/v1alpha1
|
apiVersion: traefik.io/v1alpha1
|
||||||
kind: IngressRoute
|
kind: IngressRoute
|
||||||
metadata:
|
metadata:
|
||||||
name: home-assistant
|
name: home-assistant
|
||||||
|
namespace: home-assistant
|
||||||
spec:
|
spec:
|
||||||
entryPoints:
|
entryPoints:
|
||||||
- websecure
|
- websecure
|
||||||
routes:
|
routes:
|
||||||
- match: Host(`casa.limbosolutions.com`) || Host(`has.casa.limbosolutions.com`)
|
- match: ${INGRESS_ROUTES_MATCH}
|
||||||
kind: Rule
|
kind: Rule
|
||||||
services:
|
services:
|
||||||
- name: home-assistant
|
- name: home-assistant
|
||||||
port: 8123
|
port: ${SERVICE_PORT}
|
||||||
tls:
|
tls:
|
||||||
secretName: casa-limbosolutions-com-tls
|
secretName: ${INGRESS_TLS_SECRET_NAME}
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
# 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 }}"
|
|
||||||
```
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
kubectl kustomize deploy/flux | kubectl apply -f -
|
|
||||||
Reference in New Issue
Block a user