diff --git a/app-of-apps/frigate.yaml b/app-of-apps/frigate.yaml new file mode 100644 index 0000000..c646c4d --- /dev/null +++ b/app-of-apps/frigate.yaml @@ -0,0 +1,16 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: frigate + namespace: argocd + finalizers: + - resources-finalizer.argocd.argoproj.io +spec: + destination: + namespace: frigate + server: https://kubernetes.default.svc + project: default + source: + path: frigate + repoURL: http://gitea.gitea.svc.k8s.undercloud.local:3000/Undercloud/k8s-apps.git + targetRevision: HEAD \ No newline at end of file diff --git a/app-of-apps/home-assistant.yaml b/app-of-apps/home-assistant.yaml new file mode 100644 index 0000000..0a308af --- /dev/null +++ b/app-of-apps/home-assistant.yaml @@ -0,0 +1,16 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: home-assistant + namespace: argocd + finalizers: + - resources-finalizer.argocd.argoproj.io +spec: + destination: + namespace: home-assistant + server: https://kubernetes.default.svc + project: default + source: + path: home-assistant + repoURL: http://gitea.gitea.svc.k8s.undercloud.local:3000/Undercloud/k8s-apps.git + targetRevision: HEAD \ No newline at end of file diff --git a/app-of-apps/stirling.yaml b/app-of-apps/stirling.yaml new file mode 100644 index 0000000..8309205 --- /dev/null +++ b/app-of-apps/stirling.yaml @@ -0,0 +1,16 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: stirling + namespace: argocd + finalizers: + - resources-finalizer.argocd.argoproj.io +spec: + destination: + namespace: stirling + server: https://kubernetes.default.svc + project: default + source: + path: stirling + repoURL: http://gitea.gitea.svc.k8s.undercloud.local:3000/Undercloud/k8s-apps.git + targetRevision: HEAD \ No newline at end of file diff --git a/app-of-apps/wekan.yaml b/app-of-apps/wekan.yaml new file mode 100644 index 0000000..c71bad8 --- /dev/null +++ b/app-of-apps/wekan.yaml @@ -0,0 +1,16 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: wekan + namespace: argocd + finalizers: + - resources-finalizer.argocd.argoproj.io +spec: + destination: + namespace: wekan + server: https://kubernetes.default.svc + project: default + source: + path: wekan + repoURL: http://gitea.gitea.svc.k8s.undercloud.local:3000/Undercloud/k8s-apps.git + targetRevision: HEAD \ No newline at end of file diff --git a/frigate/README.md b/frigate/README.md new file mode 100644 index 0000000..4e1dcb2 --- /dev/null +++ b/frigate/README.md @@ -0,0 +1,111 @@ +# Frigate + +## 🎥 Overview +Frigate is an open-source network video recorder (NVR) with real-time AI-based object detection. +It is designed to work with IP cameras and integrates tightly with Home Assistant to provide smart, event-driven automations. + +## 🚀 What it does +- Records video streams from IP cameras +- Performs real-time object detection (people, animals, vehicles, etc.) +- Generates events and snapshots based on detections +- Provides a web UI for live view, recordings, and review +- Integrates with MQTT and Home Assistant + +## 🌐 Website +- https://frigate.video/ + +## ⚙️ Features +- Real-time object detection using TensorFlow Lite +- Motion detection + object classification +- RTSP camera support +- Event-based recording (not just continuous) +- Timeline and review UI +- MQTT integration for automation +- Multi-camera support + +## 🧠 AI Acceleration +Frigate works best with hardware acceleration: + +- **Google Coral TPU (recommended)** → best performance, low power +- CPU-only → works but limited performance +- GPU acceleration (optional, more complex) + +## 📦 Kubernetes Deployment Notes +- Requires: + - Persistent storage (recordings + config) + - Access to camera streams (RTSP) +- Recommended setup: + - PVC for `/config` and `/media` + - Service + Ingress for web UI +- Optional: + - Device passthrough for Coral TPU: + - `/dev/bus/usb` (USB Coral) +- Considerations: + - High disk I/O (video recording) + - CPU usage if no accelerator is present + +## 📁 Storage Structure +- `/config` → Frigate configuration (YAML) +- `/media` → recordings, clips, snapshots + +## 🔌 Integrations +- **Home Assistant** (native integration) +- MQTT broker (required for event communication) +- RTSP cameras (e.g. Reolink) + +## 🎥 Camera Integration +Typical flow: + +Camera (RTSP) + ↓ +Frigate (detects objects) + ↓ +MQTT (events) + ↓ +Home Assistant (automations, notifications) + +## 🔐 Authentication +- Built-in authentication for UI +- Can be secured behind: + - Reverse proxy (Ingress / NGINX) + - SSO (e.g. Authentik via OAuth2 proxy) + +## ⚠️ Things to know +- Object detection requires tuning for best results +- CPU-only setups may struggle with multiple cameras +- Storage grows quickly → plan retention policies +- Requires stable RTSP streams from cameras + +## 🧠 Why use it +- Local, privacy-friendly camera processing +- Powerful AI detection without cloud dependency +- Deep integration with Home Assistant +- Efficient event-based recording + +## 🔧 Typical Stack in Undercloud +- Frigate → NVR + AI detection +- Home Assistant → automation + UI +- MQTT (Mosquitto) → event bus +- Reolink cameras → video source +- Coral TPU (optional) → AI acceleration + +## 📝 Example Config Snippet +```yaml +mqtt: + host: mqtt.apps.undercloud.dev + +cameras: + living_room: + ffmpeg: + inputs: + - path: rtsp://user:password@camera-ip/stream + roles: + - detect + - record + detect: + enabled: true + objects: + track: + - person + - dog + - cat \ No newline at end of file diff --git a/frigate/frigate.yaml b/frigate/frigate.yaml new file mode 100644 index 0000000..590e370 --- /dev/null +++ b/frigate/frigate.yaml @@ -0,0 +1,135 @@ + +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: frigate-config + namespace: frigate +spec: + accessModes: + - ReadWriteMany + storageClassName: cephfs-hyper + resources: + requests: + storage: 2Gi +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: frigate-media + namespace: frigate +spec: + accessModes: + - ReadWriteMany + storageClassName: cephfs-hyper + resources: + requests: + storage: 100Gi +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: frigate + namespace: frigate +spec: + replicas: 1 + selector: + matchLabels: + app: frigate + template: + metadata: + labels: + app: frigate + spec: + containers: + - name: frigate + image: ghcr.io/blakeblackshear/frigate:stable + imagePullPolicy: IfNotPresent + ports: + - name: https-ui + containerPort: 8971 + protocol: TCP + - name: http-internal + containerPort: 5000 + protocol: TCP + - name: rtsp + containerPort: 8554 + protocol: TCP + - name: webrtc-tcp + containerPort: 8555 + protocol: TCP + - name: webrtc-udp + containerPort: 8555 + protocol: UDP + env: + - name: TZ + value: Europe/Berlin + resources: + requests: + cpu: 500m + memory: 1Gi + limits: + memory: 4Gi + volumeMounts: + - name: config + mountPath: /config + - name: media + mountPath: /media/frigate + - name: cache + mountPath: /tmp/cache + - name: localtime + mountPath: /etc/localtime + readOnly: true + securityContext: + privileged: false + volumes: + - name: config + persistentVolumeClaim: + claimName: frigate-config + - name: media + persistentVolumeClaim: + claimName: frigate-media + - name: cache + emptyDir: + medium: Memory + sizeLimit: 1Gi + - name: localtime + hostPath: + path: /etc/localtime + type: File +--- +apiVersion: v1 +kind: Service +metadata: + name: frigate + namespace: frigate +spec: + ipFamilies: + - IPv6 + - IPv4 + ipFamilyPolicy: PreferDualStack + selector: + app: frigate + ports: + - name: https-ui + port: 8971 + protocol: TCP + targetPort: 8971 + - name: http-internal + port: 5000 + protocol: TCP + targetPort: 5000 + - name: rtsp + port: 8554 + protocol: TCP + targetPort: 8554 + - name: webrtc-tcp + port: 8555 + protocol: TCP + targetPort: 8555 + - name: webrtc-udp + port: 8555 + protocol: UDP + targetPort: 8555 + sessionAffinity: None + type: ClusterIP +--- diff --git a/frigate/ingress.yaml b/frigate/ingress.yaml new file mode 100644 index 0000000..123846e --- /dev/null +++ b/frigate/ingress.yaml @@ -0,0 +1,24 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: frigate + namespace: frigate + annotations: + kubernetes.io/ingress.class: nginx + nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" +spec: + rules: + - host: frigate.apps.undercloud.dev + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: frigate + port: + number: 8971 + tls: + - hosts: + - frigate.apps.undercloud.dev + secretName: frigate-tls \ No newline at end of file diff --git a/frigate/namespace.yaml b/frigate/namespace.yaml new file mode 100644 index 0000000..f814b92 --- /dev/null +++ b/frigate/namespace.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: frigate +--- \ No newline at end of file diff --git a/home-assistant/README.md b/home-assistant/README.md new file mode 100644 index 0000000..8c96c2b --- /dev/null +++ b/home-assistant/README.md @@ -0,0 +1,70 @@ +# Home Assistant + +## 🏠 Overview +Home Assistant is an open-source home automation platform designed to control and monitor smart devices in a unified way. +It allows you to integrate a wide range of hardware (lights, sensors, cameras, locks, etc.) and create automations based on events, schedules, or conditions. + +## 🚀 What it does +- Centralizes smart home devices into a single interface +- Provides powerful automation capabilities (rules, triggers, conditions) +- Supports local-first operation (no cloud required) +- Offers integrations for hundreds of vendors and protocols +- Enables dashboards, notifications, and voice assistant integrations + +## 🌐 Website +- https://www.home-assistant.io/ + +## ⚙️ Features +- Device integration (Wi-Fi, Zigbee, Z-Wave, Bluetooth, etc.) +- Automation engine (YAML or UI-based) +- Real-time monitoring and history +- Mobile app with push notifications +- Add-ons ecosystem (e.g. MQTT, Node-RED, Frigate) + +## 📦 Kubernetes Deployment Notes +- Home Assistant typically requires: + - Persistent storage (for config, database, and integrations) + - Host networking **or** access to local network devices (mDNS, broadcasts) +- Common setup includes: + - PVC for `/config` + - Optional Ingress for web UI access +- Some integrations (e.g. device discovery, Zigbee bridges) may require: + - `hostNetwork: true` + - Additional privileges or device passthrough + +## 🔌 Integrations (Examples) +- Cameras (e.g. Reolink, via RTSP/ONVIF) +- Smart locks (e.g. Nuki via Bridge API) +- MQTT (for IoT devices) +- Media systems (e.g. Apple HomeKit, HomePod) +- Presence detection, sensors, automation triggers + +## 🎥 Camera & AI Integration +- Works well with: + - **Frigate** for object detection (requires Coral or GPU for best performance) +- Typical setup: + - Camera → RTSP → Frigate → MQTT → Home Assistant + +## 🔐 Authentication +- Built-in user management +- Can be integrated with external SSO providers (e.g. Authentik, OAuth2 proxy) +- Supports long-lived access tokens for API access + +## ⚠️ Things to know +- Best experience when running on a local network with low latency +- Some integrations rely on multicast or broadcast → may not work well in strict Kubernetes networking +- Backups are important (configuration stored in `/config`) +- Frequent updates — breaking changes can occur + +## 🧠 Why use it +- Fully local control over smart home devices +- Highly customizable and extensible +- Large community and ecosystem +- Ideal central hub for a self-hosted smart home + +## 🔧 Typical Stack in Undercloud +- Home Assistant → central controller +- Frigate → camera AI / detection +- MQTT (e.g. Mosquitto) → messaging backbone +- Zigbee/Z-Wave bridge → device connectivity +- Nuki Bridge → smart lock integration diff --git a/home-assistant/home-assistant.yaml b/home-assistant/home-assistant.yaml new file mode 100644 index 0000000..dd74606 --- /dev/null +++ b/home-assistant/home-assistant.yaml @@ -0,0 +1,71 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: home-assistant-config + namespace: home-assistant +spec: + accessModes: + - ReadWriteMany + storageClassName: cephfs-hyper + resources: + requests: + storage: 2Gi +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: home-assistant + namespace: home-assistant +spec: + replicas: 1 + selector: + matchLabels: + app: home-assistant + template: + metadata: + labels: + app: home-assistant + spec: + containers: + - name: home-assistant + image: ghcr.io/home-assistant/home-assistant:stable + imagePullPolicy: IfNotPresent + ports: + - containerPort: 8123 + volumeMounts: + - name: config + mountPath: /config + env: + - name: TZ + value: Europe/Berlin + resources: + requests: + cpu: 200m + memory: 512Mi + limits: + memory: 1Gi + volumes: + - name: config + persistentVolumeClaim: + claimName: home-assistant-config +--- +apiVersion: v1 +kind: Service +metadata: + name: home-assistant + namespace: home-assistant +spec: + ipFamilies: + - IPv6 + - IPv4 + ipFamilyPolicy: PreferDualStack + selector: + app: home-assistant + ports: + - name: http + port: 8123 + protocol: TCP + targetPort: 8123 + sessionAffinity: None + type: ClusterIP +--- diff --git a/home-assistant/ingress.yaml b/home-assistant/ingress.yaml new file mode 100644 index 0000000..9ef6d5c --- /dev/null +++ b/home-assistant/ingress.yaml @@ -0,0 +1,23 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: home-assistant + namespace: home-assistant + annotations: + kubernetes.io/ingress.class: nginx +spec: + rules: + - host: home.apps.undercloud.dev + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: home-assistant + port: + number: 8123 + tls: + - hosts: + - home.apps.undercloud.dev + secretName: home-assistant-tls \ No newline at end of file diff --git a/home-assistant/namespace.yaml b/home-assistant/namespace.yaml new file mode 100644 index 0000000..3fd829f --- /dev/null +++ b/home-assistant/namespace.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: home-assistant +--- \ No newline at end of file diff --git a/home-assistant/secrets.yaml b/home-assistant/secrets.yaml new file mode 100644 index 0000000..e69de29 diff --git a/homer/configmaps.yaml b/homer/configmaps.yaml index 428e3e1..3786837 100644 --- a/homer/configmaps.yaml +++ b/homer/configmaps.yaml @@ -200,6 +200,18 @@ data: tag: "authentik" keywords: "auth sso authentik" url: "https://auth.apps.undercloud.dev" + - name: "Home Assistant" + logo: "assets/logos/authentik.png" + subtitle: "SSO" + tag: "home automation" + keywords: "home automation zigbee" + url: "https://home.apps.undercloud.dev" + - name: "Frigate" + logo: "assets/logos/authentik.png" + subtitle: "SSO" + tag: "surveillance" + keywords: "camera surveillance" + url: "https://frigate.apps.undercloud.dev" - name: "Communication" icon: "fas fa-cloud" diff --git a/uptime-kuma/backup.yaml b/uptime-kuma/backup.yaml new file mode 100644 index 0000000..c03f2b0 --- /dev/null +++ b/uptime-kuma/backup.yaml @@ -0,0 +1,90 @@ +apiVersion: velero.io/v1 +kind: Schedule +metadata: + name: uptime-kuma-csi-hourly + namespace: velero +spec: + schedule: "0 15-22 * * *" + useOwnerReferencesInBackup: true + template: + includedNamespaces: ["uptime-kuma"] + ttl: 8h + snapshotVolumes: true + defaultVolumesToFsBackup: false + csiSnapshotTimeout: 10m +--- +apiVersion: velero.io/v1 +kind: Schedule +metadata: + name: uptime-kuma-csi-daily + namespace: velero +spec: + schedule: "0 0 * * *" + useOwnerReferencesInBackup: true + template: + includedNamespaces: ["uptime-kuma"] + ttl: 168h + snapshotVolumes: true + defaultVolumesToFsBackup: false + csiSnapshotTimeout: 10m +--- +apiVersion: velero.io/v1 +kind: Schedule +metadata: + name: uptime-kuma-csi-weekly + namespace: velero +spec: + schedule: "0 0 * * 1" + useOwnerReferencesInBackup: true + template: + includedNamespaces: ["uptime-kuma"] + ttl: 730h + snapshotVolumes: true + defaultVolumesToFsBackup: false + csiSnapshotTimeout: 10m +--- +apiVersion: velero.io/v1 +kind: Schedule +metadata: + name: uptime-kuma-daily + namespace: velero +spec: + schedule: "30 2 * * *" # tous les jours 02:30 + useOwnerReferencesInBackup: true + template: + includedNamespaces: [uptime-kuma] + storageLocation: default + ttl: 336h # ~14 jours + snapshotVolumes: false + defaultVolumesToFsBackup: true + +--- +apiVersion: velero.io/v1 +kind: Schedule +metadata: + name: uptime-kuma-weekly + namespace: velero +spec: + schedule: "0 3 * * 0" # chaque dimanche 03:00 + useOwnerReferencesInBackup: true + template: + includedNamespaces: [uptime-kuma] + storageLocation: default + ttl: 1344h # ~8 semaines + snapshotVolumes: false + defaultVolumesToFsBackup: true +--- +apiVersion: velero.io/v1 +kind: Schedule +metadata: + name: uptime-kuma-monthly + namespace: velero +spec: + schedule: "0 4 1 * *" # 1er du mois 04:00 + useOwnerReferencesInBackup: true + template: + includedNamespaces: [uptime-kuma] + storageLocation: default + ttl: 8760h # ~12 mois + snapshotVolumes: false + defaultVolumesToFsBackup: true