mirror of
https://github.com/shadoll/helm-charts.git
synced 2026-08-28 03:27:08 +00:00
feat: Add persistent volume claim support for backups and update Helm chart version
This commit is contained in:
@@ -0,0 +1,116 @@
|
|||||||
|
# Home Assistant Helm Chart — Issues & Improvements
|
||||||
|
|
||||||
|
## Defaults & Best Practices
|
||||||
|
|
||||||
|
- [ ] **`hostNetwork: true` should default to `false`**
|
||||||
|
`hostNetwork` is only needed for HomeKit/mDNS discovery on the LAN. A clean install should not claim the host network by default. Users who need it can opt in via values.
|
||||||
|
File: `values.yaml` line 12, `deployment.yaml` lines 24-27
|
||||||
|
|
||||||
|
- [ ] **HomeKit should default to disabled**
|
||||||
|
HomeKit is a specific integration, not a core feature. Default `homekit.enabled: false` and let users enable it when needed. Currently exposes port 21063 on every install.
|
||||||
|
File: `values.yaml` lines 16-18, `deployment.yaml` lines 105-109
|
||||||
|
|
||||||
|
- [ ] **Timezone should default to `UTC`**
|
||||||
|
Currently hardcoded to `Europe/Kyiv`. Chart defaults should be locale-neutral. Users override via values for their deployment.
|
||||||
|
File: `values.yaml` line 14
|
||||||
|
|
||||||
|
- [ ] **Resource limits too high for default**
|
||||||
|
CPU limit of 8 cores is excessive for a default install. Consider `cpu: 2` / `memory: 2Gi` as default limits, with `cpu: 100m` / `memory: 256Mi` as requests. Production users can increase as needed.
|
||||||
|
File: `values.yaml` lines 40-46
|
||||||
|
|
||||||
|
- [ ] **`imagePullPolicy: Always` should be `IfNotPresent`**
|
||||||
|
For tagged images (not `latest`), `IfNotPresent` is the Kubernetes convention. `Always` causes unnecessary image pulls on every pod restart.
|
||||||
|
File: `values.yaml` line 5, `deployment.yaml` line 93
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
- [ ] **No `securityContext` defined**
|
||||||
|
The deployment has no pod or container security context. Should add at minimum:
|
||||||
|
```yaml
|
||||||
|
securityContext:
|
||||||
|
runAsNonRoot: false # HA needs root for s6 init
|
||||||
|
# But container-level:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
capabilities:
|
||||||
|
drop: [ALL]
|
||||||
|
add: [NET_BIND_SERVICE] # if needed for homekit
|
||||||
|
```
|
||||||
|
Note: Home Assistant uses s6-overlay which requires root. Full non-root may not be feasible, but `capabilities` should still be restricted.
|
||||||
|
File: `deployment.yaml`
|
||||||
|
|
||||||
|
- [ ] **No `ServiceAccount` created**
|
||||||
|
Chart should create a dedicated ServiceAccount with `automountServiceAccountToken: false` (HA doesn't need Kubernetes API access). This follows the principle of least privilege.
|
||||||
|
Files: new `templates/serviceaccount.yaml`, `deployment.yaml`
|
||||||
|
|
||||||
|
## Reliability
|
||||||
|
|
||||||
|
- [ ] **No liveness/readiness probes**
|
||||||
|
HA exposes HTTP on port 8123. The chart should define probes:
|
||||||
|
```yaml
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: 8123
|
||||||
|
initialDelaySeconds: 60
|
||||||
|
periodSeconds: 30
|
||||||
|
failureThreshold: 5
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: 8123
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
periodSeconds: 10
|
||||||
|
```
|
||||||
|
`initialDelaySeconds` should be generous — HA can take 30-90s to start depending on integrations. Consider making these configurable via values.
|
||||||
|
File: `deployment.yaml`
|
||||||
|
|
||||||
|
## Code Quality
|
||||||
|
|
||||||
|
- [ ] **`busybox:latest` in init containers**
|
||||||
|
Init containers (`init-config`, `init-secrets`, `init-recorder`) use `busybox:latest` which is unpinned and not reproducible. Pin to a specific version, e.g. `busybox:1.37` and make it configurable via values.
|
||||||
|
File: `deployment.yaml` lines 31, 43, 63
|
||||||
|
|
||||||
|
- [ ] **`version-source` annotation in deployment template**
|
||||||
|
The `version-source: github-release:home-assistant/core` annotation is for the `just app` CLI tooling in the k3s repo, not a chart concern. Should be removed from the template and added via HelmRelease annotations or values.
|
||||||
|
File: `deployment.yaml` lines 8-9
|
||||||
|
|
||||||
|
## Future Enhancements
|
||||||
|
|
||||||
|
- [ ] **Auto-generate `http.yaml` from chart values**
|
||||||
|
Same pattern as the recorder init container — generate `/config/http.yaml` and add `http: !include http.yaml` to `configuration.yaml`. This simplifies initial setup since `trusted_proxies` is required for Traefik/ingress to work and the values can be derived from the Kubernetes environment.
|
||||||
|
Generated file example:
|
||||||
|
```yaml
|
||||||
|
server_port: 8123
|
||||||
|
use_x_forwarded_for: true
|
||||||
|
trusted_proxies:
|
||||||
|
- 10.42.0.0/16 # k8s pod CIDR (Traefik)
|
||||||
|
- 10.43.0.0/16 # k8s service CIDR
|
||||||
|
```
|
||||||
|
Values structure:
|
||||||
|
```yaml
|
||||||
|
http:
|
||||||
|
enabled: false
|
||||||
|
port: 8123
|
||||||
|
useXForwardedFor: true
|
||||||
|
trustedProxies: []
|
||||||
|
# - 10.42.0.0/16
|
||||||
|
# - 10.43.0.0/16
|
||||||
|
```
|
||||||
|
File: `values.yaml`, `deployment.yaml` (new init container)
|
||||||
|
|
||||||
|
- [ ] **S3 backup support**
|
||||||
|
Add optional S3 sync as a post-backup step in the CronJob. Write locally to PVC first (fast restore), then push to S3 for disaster recovery. Values structure:
|
||||||
|
```yaml
|
||||||
|
backup:
|
||||||
|
s3:
|
||||||
|
enabled: false
|
||||||
|
endpoint: ""
|
||||||
|
bucket: ""
|
||||||
|
existingSecret: ""
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **NOTES.txt for post-install instructions**
|
||||||
|
Add `templates/NOTES.txt` to display useful info after install (URLs, first-time setup steps, how to access HA).
|
||||||
|
|
||||||
|
- [ ] **Support `topologySpreadConstraints`**
|
||||||
|
For multi-node clusters, allow configuring topology spread via values (though HA is typically single-replica).
|
||||||
@@ -5,5 +5,5 @@ type: application
|
|||||||
annotations:
|
annotations:
|
||||||
version-source: github-release:home-assistant/core
|
version-source: github-release:home-assistant/core
|
||||||
version-pattern: "s|^v||"
|
version-pattern: "s|^v||"
|
||||||
version: 0.1.10
|
version: 0.1.13
|
||||||
appVersion: "2026.3.4"
|
appVersion: "2026.3.4"
|
||||||
|
|||||||
@@ -40,9 +40,14 @@ spec:
|
|||||||
mountPath: /backup
|
mountPath: /backup
|
||||||
volumes:
|
volumes:
|
||||||
- name: backup-storage
|
- name: backup-storage
|
||||||
|
{{- if .Values.backup.persistence.enabled }}
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: {{ .Values.backup.persistence.existingClaim | default (printf "%s-db-backup" (include "home-assistant.fullname" .)) }}
|
||||||
|
{{- else }}
|
||||||
hostPath:
|
hostPath:
|
||||||
path: {{ .Values.backup.storagePath }}
|
path: {{ .Values.backup.storagePath }}
|
||||||
type: DirectoryOrCreate
|
type: DirectoryOrCreate
|
||||||
|
{{- end }}
|
||||||
restartPolicy: OnFailure
|
restartPolicy: OnFailure
|
||||||
{{- if .Values.backup.node }}
|
{{- if .Values.backup.node }}
|
||||||
affinity:
|
affinity:
|
||||||
|
|||||||
@@ -119,6 +119,10 @@ spec:
|
|||||||
- name: media
|
- name: media
|
||||||
mountPath: {{ .Values.persistence.media.mountPath }}
|
mountPath: {{ .Values.persistence.media.mountPath }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
{{- if .Values.persistence.backups.enabled }}
|
||||||
|
- name: backups
|
||||||
|
mountPath: /config/backups
|
||||||
|
{{- end }}
|
||||||
resources:
|
resources:
|
||||||
{{- toYaml .Values.resources | nindent 12 }}
|
{{- toYaml .Values.resources | nindent 12 }}
|
||||||
volumes:
|
volumes:
|
||||||
@@ -144,6 +148,11 @@ spec:
|
|||||||
claimName: {{ .Values.persistence.media.existingClaim | default (printf "%s-media" (include "home-assistant.fullname" .)) }}
|
claimName: {{ .Values.persistence.media.existingClaim | default (printf "%s-media" (include "home-assistant.fullname" .)) }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
{{- if .Values.persistence.backups.enabled }}
|
||||||
|
- name: backups
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: {{ .Values.persistence.backups.existingClaim | default (printf "%s-backups" (include "home-assistant.fullname" .)) }}
|
||||||
|
{{- end }}
|
||||||
{{- if .Values.haSecrets.enabled }}
|
{{- if .Values.haSecrets.enabled }}
|
||||||
- name: ha-secrets
|
- name: ha-secrets
|
||||||
secret:
|
secret:
|
||||||
|
|||||||
@@ -46,4 +46,54 @@ spec:
|
|||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
---
|
||||||
|
{{- if .Values.persistence.backups.enabled }}
|
||||||
|
{{- if eq (.Values.persistence.backups.type | default "pvc") "pvc" }}
|
||||||
|
{{- if not .Values.persistence.backups.existingClaim }}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: {{ include "home-assistant.fullname" . }}-backups
|
||||||
|
{{- if .Values.namespaceOverride }}
|
||||||
|
namespace: {{ .Values.namespaceOverride }}
|
||||||
|
{{- end }}
|
||||||
|
labels:
|
||||||
|
{{- include "home-assistant.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
{{- toYaml (.Values.persistence.backups.accessModes | default (list "ReadWriteOnce")) | nindent 4 }}
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: {{ .Values.persistence.backups.size | default "10Gi" | quote }}
|
||||||
|
{{- if .Values.persistence.backups.storageClass }}
|
||||||
|
storageClassName: {{ .Values.persistence.backups.storageClass | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
---
|
||||||
|
{{- if .Values.backup.enabled }}
|
||||||
|
{{- if .Values.backup.persistence.enabled }}
|
||||||
|
{{- if not .Values.backup.persistence.existingClaim }}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: {{ include "home-assistant.fullname" . }}-db-backup
|
||||||
|
{{- if .Values.namespaceOverride }}
|
||||||
|
namespace: {{ .Values.namespaceOverride }}
|
||||||
|
{{- end }}
|
||||||
|
labels:
|
||||||
|
{{- include "home-assistant.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
{{- toYaml (.Values.backup.persistence.accessModes | default (list "ReadWriteOnce")) | nindent 4 }}
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: {{ .Values.backup.persistence.size | default "10Gi" | quote }}
|
||||||
|
{{- if .Values.backup.persistence.storageClass }}
|
||||||
|
storageClassName: {{ .Values.backup.persistence.storageClass | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|||||||
@@ -48,17 +48,29 @@ resources:
|
|||||||
persistence:
|
persistence:
|
||||||
config:
|
config:
|
||||||
enabled: true
|
enabled: true
|
||||||
type: hostPath
|
type: pvc
|
||||||
hostPath: /srv/data/home-assistant/config
|
|
||||||
mountPath: /config
|
mountPath: /config
|
||||||
size: 10Gi
|
size: 10Gi
|
||||||
accessModes:
|
accessModes:
|
||||||
- ReadWriteOnce
|
- ReadWriteOnce
|
||||||
storageClass: ""
|
storageClass: ""
|
||||||
|
# hostPath: /srv/data/home-assistant/config # only when type: hostPath
|
||||||
media:
|
media:
|
||||||
enabled: true
|
enabled: true
|
||||||
hostPath: /srv/data/home-assistant/media
|
type: pvc
|
||||||
mountPath: /media
|
mountPath: /media
|
||||||
|
size: 5Gi
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
storageClass: ""
|
||||||
|
# hostPath: /srv/data/home-assistant/media # only when type: hostPath
|
||||||
|
backups:
|
||||||
|
enabled: false
|
||||||
|
type: pvc
|
||||||
|
size: 10Gi
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
storageClass: ""
|
||||||
|
|
||||||
haSecrets:
|
haSecrets:
|
||||||
enabled: false
|
enabled: false
|
||||||
@@ -97,6 +109,12 @@ backup:
|
|||||||
storagePath: /storage/backups/postgres
|
storagePath: /storage/backups/postgres
|
||||||
# Node to run backup on (hostname). Overrides global affinity/tolerations.
|
# Node to run backup on (hostname). Overrides global affinity/tolerations.
|
||||||
node: ""
|
node: ""
|
||||||
|
persistence:
|
||||||
|
enabled: false
|
||||||
|
size: 10Gi
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
storageClass: ""
|
||||||
postgres:
|
postgres:
|
||||||
host: postgres-tcp.postgres.svc.cluster.local
|
host: postgres-tcp.postgres.svc.cluster.local
|
||||||
db: homeassistant
|
db: homeassistant
|
||||||
|
|||||||
Reference in New Issue
Block a user