Add new applications: Home Assistant Voice LLMs and Ollama

- Add custom Helm chart for Home Assistant Voice LLMs integration
- Add Ollama configuration for local LLM inference
- Support AI voice assistant capabilities in homelab

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
gilgamezh
2025-07-28 14:13:23 +02:00
parent 0f61ffae27
commit 620d757f8b
9 changed files with 396 additions and 0 deletions
+23
View File
@@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/
+24
View File
@@ -0,0 +1,24 @@
apiVersion: v2
name: home-assistant-voice-llms
description: A Helm chart for Kubernetes
# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.1.0
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "1.16.0"
@@ -0,0 +1,62 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "home-assistant-voice-llms.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "home-assistant-voice-llms.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "home-assistant-voice-llms.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "home-assistant-voice-llms.labels" -}}
helm.sh/chart: {{ include "home-assistant-voice-llms.chart" . }}
{{ include "home-assistant-voice-llms.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "home-assistant-voice-llms.selectorLabels" -}}
app.kubernetes.io/name: {{ include "home-assistant-voice-llms.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "home-assistant-voice-llms.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "home-assistant-voice-llms.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}
@@ -0,0 +1,97 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-faster-whisper
spec:
replicas: {{ .Values.defaults.replicaCount }}
selector:
matchLabels:
app: faster-whisper
template:
metadata:
labels:
app: faster-whisper
spec:
containers:
- name: faster-whisper
image: {{ .Values.defaults.fasterWhisper.image.repository }}:{{ .Values.defaults.fasterWhisper.image.tag }}
imagePullPolicy: {{ .Values.defaults.fasterWhisper.image.pullPolicy }}
env:
- name: PUID
value: "{{ .Values.defaults.fasterWhisper.env.PUID }}"
- name: PGID
value: "{{ .Values.defaults.fasterWhisper.env.PGID }}"
- name: TZ
value: "{{ .Values.defaults.fasterWhisper.env.TZ }}"
- name: WHISPER_MODEL
value: "{{ .Values.defaults.fasterWhisper.env.WHISPER_MODEL }}"
- name: WHISPER_BEAM
value: "{{ .Values.defaults.fasterWhisper.env.WHISPER_BEAM }}"
- name: WHISPER_LANG
value: "{{ .Values.defaults.fasterWhisper.env.WHISPER_LANG }}"
ports:
- containerPort: 10300
volumeMounts:
- mountPath: {{ .Values.defaults.fasterWhisper.volume.mountPath }}
name: config
{{- if .Values.nodeSelector }}
nodeSelector:
{{ toYaml .Values.nodeSelector | indent 8 }}
{{- end }}
volumes:
- name: config
persistentVolumeClaim:
claimName: {{ .Values.defaults.fasterWhisper.volume.claimName }}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-piper
spec:
replicas: {{ .Values.defaults.replicaCount }}
selector:
matchLabels:
app: piper
template:
metadata:
labels:
app: piper
spec:
containers:
- name: piper
image: {{ .Values.defaults.piper.image.repository }}:{{ .Values.defaults.piper.image.tag }}
imagePullPolicy: {{ .Values.defaults.piper.image.pullPolicy }}
env:
- name: PUID
value: "{{ .Values.defaults.piper.env.PUID }}"
- name: PGID
value: "{{ .Values.defaults.piper.env.PGID }}"
- name: TZ
value: "{{ .Values.defaults.piper.env.TZ }}"
- name: PIPER_VOICE
value: "{{ .Values.defaults.piper.env.PIPER_VOICE }}"
- name: PIPER_LENGTH
value: "{{ .Values.defaults.piper.env.PIPER_LENGTH }}"
- name: PIPER_NOISE
value: "{{ .Values.defaults.piper.env.PIPER_NOISE }}"
- name: PIPER_NOISEW
value: "{{ .Values.defaults.piper.env.PIPER_NOISEW }}"
- name: PIPER_SPEAKER
value: "{{ .Values.defaults.piper.env.PIPER_SPEAKER }}"
- name: PIPER_PROCS
value: "{{ .Values.defaults.piper.env.PIPER_PROCS }}"
ports:
- containerPort: 10200
volumeMounts:
- mountPath: {{ .Values.defaults.piper.volume.mountPath }}
name: config
volumes:
- name: config
persistentVolumeClaim:
claimName: {{ .Values.defaults.piper.volume.claimName }}
{{- if .Values.nodeSelector }}
nodeSelector:
{{ toYaml .Values.nodeSelector | indent 8 }}
{{- end }}
@@ -0,0 +1,25 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ .Values.defaults.fasterWhisper.volume.claimName }}
spec:
storageClassName: nfs-client
accessModes:
- ReadWriteOnce
resources:
requests:
storage: {{ .Values.defaults.fasterWhisper.volume.storage }}
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ .Values.defaults.piper.volume.claimName }}
spec:
storageClassName: nfs-client
accessModes:
- ReadWriteOnce
resources:
requests:
storage: {{ .Values.defaults.piper.volume.storage }}
@@ -0,0 +1,25 @@
apiVersion: v1
kind: Service
metadata:
name: {{ .Release.Name }}-faster-whisper
spec:
type: {{ .Values.defaults.fasterWhisper.service.type }}
ports:
- port: {{ .Values.defaults.fasterWhisper.service.port }}
targetPort: 10300
selector:
app: faster-whisper
---
apiVersion: v1
kind: Service
metadata:
name: {{ .Release.Name }}-piper
spec:
type: {{ .Values.defaults.piper.service.type }}
ports:
- port: {{ .Values.defaults.piper.service.port }}
targetPort: 10200
selector:
app: piper
+57
View File
@@ -0,0 +1,57 @@
defaults:
replicaCount: 1
fasterWhisper:
image:
repository: lscr.io/linuxserver/faster-whisper
tag: "2.4.0"
pullPolicy: IfNotPresent
service:
type: LoadBalancer
port: 10300
resources:
limits:
cpu: "3"
memory: "5000Mi"
requests:
cpu: "3"
memory: "2000Mi"
env:
PUID: 1000
PGID: 1000
TZ: Europe/Amsterdam
WHISPER_MODEL: small-int8
WHISPER_BEAM: 1
WHISPER_LANG: en
volume:
mountPath: /config
claimName: faster-whisper-pvc
storage: 1Gi
piper:
image:
repository: lscr.io/linuxserver/piper
tag: "latest"
pullPolicy: IfNotPresent
service:
type: LoadBalancer
port: 10200
resources:
limits:
cpu: "2"
memory: "4000Mi"
requests:
cpu: "1"
memory: "2000Mi"
env:
PUID: 1000
PGID: 1000
TZ: Europe/Amsterdam
PIPER_VOICE: en_US-lessac-medium
PIPER_LENGTH: 1.0
PIPER_NOISE: 0.667
PIPER_NOISEW: 0.333
PIPER_SPEAKER: 0
PIPER_PROCS: 2
volume:
mountPath: /config
claimName: piper-pvc
storage: 1Gi
+61
View File
@@ -0,0 +1,61 @@
defaults:
replicaCount: 1
fasterWhisper:
image:
repository: lscr.io/linuxserver/faster-whisper
tag: "2.5.0"
pullPolicy: Always
service:
type: LoadBalancer
port: 10300
resources:
limits:
cpu: "3"
memory: "4Gi"
requests:
cpu: "3"
memory: "2Gi"
env:
PUID: 1000
PGID: 1000
TZ: Europe/Amsterdam
WHISPER_MODEL: Zoont/faster-whisper-large-v3-turbo-int8-ct2
WHISPER_BEAM: 1
WHISPER_LANG: en
WHISPER_THREADS value: 4
volume:
mountPath: /config
claimName: faster-whisper-pvc
storage: 1Gi
piper:
image:
repository: lscr.io/linuxserver/piper
tag: "1.5.3"
pullPolicy: Always
service:
type: LoadBalancer
port: 10200
resources:
limits:
cpu: "2"
memory: "4000Mi"
requests:
cpu: "1"
memory: "2000Mi"
env:
PUID: 1000
PGID: 1000
TZ: Europe/Amsterdam
PIPER_VOICE: en_US-lessac-medium
PIPER_LENGTH: 1.0
PIPER_NOISE: 0.667
PIPER_NOISEW: 0.333
PIPER_SPEAKER: 0
PIPER_PROCS: 2
volume:
mountPath: /config
claimName: piper-pvc
storage: 1Gi
nodeSelector:
kubernetes.io/arch: amd64
+22
View File
@@ -0,0 +1,22 @@
replicaCount: 1
image:
repository: ollama/ollama
pullPolicy: IfNotPresent
tag: "latest"
# Ollama parameters
ollama:
models:
pull:
- TinyLlama
- llama3.1:8b
# Configure Service
service:
# -- Service type
type: LoadBalancer
# -- Service port
port: 11434
nodeSelector:
kubernetes.io/arch: amd64