1 Commits

Author SHA1 Message Date
Paul Payne
a663746686 Add homeassistant app. 2025-08-16 07:55:10 -07:00
22 changed files with 399 additions and 159 deletions

View File

@@ -0,0 +1,37 @@
apiVersion: batch/v1
kind: Job
metadata:
name: homeassistant-config-setup
spec:
template:
spec:
restartPolicy: Never
containers:
- name: config-setup
image: busybox:1.35
command: ['sh', '-c']
args:
- |
# Wait for config file to exist
while [ ! -f /config/configuration.yaml ]; do
sleep 5
done
# Add HTTP config if not present
if ! grep -q "use_x_forwarded_for" /config/configuration.yaml; then
echo "" >> /config/configuration.yaml
echo "# HTTP configuration for reverse proxy support" >> /config/configuration.yaml
echo "http:" >> /config/configuration.yaml
echo " use_x_forwarded_for: true" >> /config/configuration.yaml
echo " trusted_proxies:" >> /config/configuration.yaml
echo " - 10.0.0.0/8" >> /config/configuration.yaml
echo " - 172.16.0.0/12" >> /config/configuration.yaml
echo " - 192.168.0.0/16" >> /config/configuration.yaml
fi
volumeMounts:
- mountPath: /config
name: homeassistant-config
volumes:
- name: homeassistant-config
persistentVolumeClaim:
claimName: homeassistant-pvc

View File

@@ -0,0 +1,88 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: homeassistant
spec:
replicas: 1
selector:
matchLabels:
component: homeassistant
strategy:
type: Recreate
template:
metadata:
labels:
component: homeassistant
spec:
# hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
initContainers:
- name: config-setup
image: busybox:1.35
command: ['sh', '-c']
args:
- |
# Create initial config if it doesn't exist
if [ ! -f /config/configuration.yaml ]; then
cat > /config/configuration.yaml << 'EOF'
# Loads default set of integrations. Do not remove.
default_config:
# Load frontend themes from the themes folder
frontend:
themes: !include_dir_merge_named themes
automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml
# HTTP configuration for reverse proxy support
http:
use_x_forwarded_for: true
trusted_proxies:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
EOF
fi
volumeMounts:
- mountPath: /config
name: homeassistant-config
containers:
- name: homeassistant
image: "{{ .apps.homeassistant.image }}"
ports:
- containerPort: 8123
protocol: TCP
env:
- name: TZ
value: "{{ .apps.homeassistant.timezone }}"
volumeMounts:
- mountPath: /config
name: homeassistant-config
readOnly: false
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "2Gi"
cpu: "2"
livenessProbe:
httpGet:
path: /
port: 8123
initialDelaySeconds: 30
periodSeconds: 30
timeoutSeconds: 10
readinessProbe:
httpGet:
path: /
port: 8123
initialDelaySeconds: 15
periodSeconds: 15
timeoutSeconds: 5
volumes:
- name: homeassistant-config
persistentVolumeClaim:
claimName: homeassistant-pvc

View File

@@ -0,0 +1,23 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: homeassistant-public
# annotations:
# external-dns.alpha.kubernetes.io/target: "{{ .apps.homeassistant.domain }}"
# external-dns.alpha.kubernetes.io/cloudflare-proxied: "false"
spec:
rules:
- host: "{{ .apps.homeassistant.domain }}"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: homeassistant
port:
number: 8123
tls:
- secretName: "{{ .apps.homeassistant.tlsKey }}"
hosts:
- "{{ .apps.homeassistant.domain }}"

View File

@@ -1,16 +1,16 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: homepage
namespace: homeassistant
labels:
- includeSelectors: true
pairs:
app: homepage
app: homeassistant
managedBy: kustomize
partOf: wild-cloud
resources:
- namespace.yaml
- service-account.yaml
- deployment.yaml
- service.yaml
- ingress.yaml
- configmap.yaml
- pvc.yaml

View File

@@ -0,0 +1,13 @@
name: homeassistant
install: true
description: Home Assistant is an open source home automation platform that puts local control and privacy first.
version: 2025.1.0
icon: https://brands.home-assistant.io/homeassistant/logo.png
requires: []
defaultConfig:
image: ghcr.io/home-assistant/home-assistant:stable
timezone: UTC
storage: 50Gi
domain: hass.{{ .cloud.internalDomain }}
tlsSecretName: wildcard-internal-wild-cloud-tls
requiredSecrets: []

View File

@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: homeassistant

View File

@@ -0,0 +1,11 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: homeassistant-pvc
spec:
storageClassName: longhorn
accessModes:
- ReadWriteOnce
resources:
requests:
storage: {{ .apps.homeassistant.storage }}

View File

@@ -0,0 +1,12 @@
apiVersion: v1
kind: Service
metadata:
name: homeassistant
spec:
ports:
- name: http
port: 8123
targetPort: 8123
protocol: TCP
selector:
component: homeassistant

View File

@@ -1,2 +0,0 @@
# Homepage

View File

@@ -1,63 +0,0 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: homepage-config
namespace: homepage
labels:
app: homepage
managedBy: kustomize
partOf: wild-cloud
data:
bookmarks.yaml: |
- Developer:
- Github:
- abbr: GH
href: https://github.com/
kubernetes.yaml: |
mode: cluster
services.yaml: |
- Wild Cloud Services:
- Traefik Dashboard:
href: https://traefik.example.com
description: Traefik reverse proxy dashboard
- Longhorn:
href: https://longhorn.example.com
description: Distributed storage management
settings.yaml: |
title: Wild Cloud Dashboard
theme: dark
layout:
- Wild Cloud Services:
style: row
columns: 2
widgets.yaml: |
- kubernetes:
cluster:
show: true
cpu: true
memory: true
showLabel: true
label: "cluster"
nodes:
show: true
cpu: true
memory: true
showLabel: true
- resources:
backend: resources
expanded: true
cpu: true
memory: true
network: default
- search:
provider: duckduckgo
target: _blank
docker.yaml: |
# Docker configuration for homepage
# This file is required by the homepage application
custom.css: |
/* Custom CSS for homepage */
/* Add your custom styles here */
custom.js: |
// Custom JavaScript for homepage
// Add your custom scripts here

View File

@@ -1,37 +0,0 @@
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: homepage
spec:
replicas: 1
selector:
matchLabels:
app: homepage
template:
metadata:
labels:
app: homepage
spec:
serviceAccountName: homepage
containers:
- name: homepage
image: "{{ .apps.homepage.image }}"
ports:
- containerPort: 3000
name: http
env:
- name: HOMEPAGE_ALLOWED_HOSTS
value: "{{ .apps.homepage.domain }}"
volumeMounts:
- name: config
mountPath: /app/config
readOnly: true
- name: logs
mountPath: /app/config/logs
volumes:
- name: config
configMap:
name: homepage-config
- name: logs
emptyDir: {}

View File

@@ -1,12 +0,0 @@
name: homepage
install: true
description: Homepage is a modern, fully static, fast, secure fully proxied, highly customizable application dashboard with integrations for over 100 services.
version: 1.0.0
icon: https://gethomepage.dev/favicon.ico
requires: []
defaultConfig:
image: ghcr.io/gethomepage/homepage:latest
domain: homepage.{{ .cloud.internalDomain }}
port: 3000
tlsSecretName: wildcard-internal-wild-cloud-tls
requiredSecrets: []

View File

@@ -1,8 +0,0 @@
apiVersion: v1
kind: Namespace
metadata:
name: homepage
labels:
app: homepage
managedBy: kustomize
partOf: wild-cloud

View File

@@ -1,9 +0,0 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: homepage
namespace: homepage
labels:
app: homepage
managedBy: kustomize
partOf: wild-cloud

View File

@@ -1,17 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: homepage
namespace: homepage
labels:
app: homepage
managedBy: kustomize
partOf: wild-cloud
spec:
type: ClusterIP
ports:
- port: 3000
targetPort: http
name: http
selector:
app: homepage

View File

@@ -0,0 +1,12 @@
# Config
JELLYFIN_DOMAIN=jellyfin.$DOMAIN
JELLYFIN_CONFIG_STORAGE=1Gi
JELLYFIN_CACHE_STORAGE=10Gi
JELLYFIN_MEDIA_STORAGE=100Gi
TZ=UTC
# Docker Images
JELLYFIN_IMAGE=jellyfin/jellyfin:latest
# Jellyfin Configuration
JELLYFIN_PublishedServerUrl=https://jellyfin.$DOMAIN

View File

@@ -0,0 +1,49 @@
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: jellyfin
spec:
replicas: 1
selector:
matchLabels:
app: jellyfin
strategy:
type: Recreate
template:
metadata:
labels:
app: jellyfin
spec:
containers:
- image: jellyfin/jellyfin:latest
name: jellyfin
ports:
- containerPort: 8096
protocol: TCP
envFrom:
- configMapRef:
name: config
env:
- name: TZ
valueFrom:
configMapKeyRef:
key: TZ
name: config
volumeMounts:
- mountPath: /config
name: jellyfin-config
- mountPath: /cache
name: jellyfin-cache
- mountPath: /media
name: jellyfin-media
volumes:
- name: jellyfin-config
persistentVolumeClaim:
claimName: jellyfin-config-pvc
- name: jellyfin-cache
persistentVolumeClaim:
claimName: jellyfin-cache-pvc
- name: jellyfin-media
persistentVolumeClaim:
claimName: jellyfin-media-pvc

View File

@@ -2,23 +2,23 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: homepage-public
name: jellyfin-public
annotations:
external-dns.alpha.kubernetes.io/target: "{{ .apps.homepage.domain }}"
external-dns.alpha.kubernetes.io/target: your.jellyfin.domain
external-dns.alpha.kubernetes.io/cloudflare-proxied: "false"
spec:
rules:
- host: "{{ .apps.homepage.domain }}"
- host: your.jellyfin.domain
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: homepage
name: jellyfin
port:
number: 3000
number: 8096
tls:
- secretName: wildcard-wild-cloud-tls
- secretName: wildcard-internal-wild-cloud-tls
hosts:
- "{{ .apps.homepage.domain }}"
- your.jellyfin.domain

View File

@@ -0,0 +1,82 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: jellyfin
labels:
- includeSelectors: true
pairs:
app: jellyfin
managedBy: kustomize
partOf: wild-cloud
resources:
- deployment.yaml
- ingress.yaml
- namespace.yaml
- pvc.yaml
- service.yaml
configMapGenerator:
- name: config
envs:
- config/config.env
replacements:
- source:
kind: ConfigMap
name: config
fieldPath: data.DOMAIN
targets:
- select:
kind: Ingress
name: jellyfin-public
fieldPaths:
- metadata.annotations.[external-dns.alpha.kubernetes.io/target]
- source:
kind: ConfigMap
name: config
fieldPath: data.JELLYFIN_DOMAIN
targets:
- select:
kind: Ingress
name: jellyfin-public
fieldPaths:
- spec.rules.0.host
- spec.tls.0.hosts.0
- source:
kind: ConfigMap
name: config
fieldPath: data.JELLYFIN_CONFIG_STORAGE
targets:
- select:
kind: PersistentVolumeClaim
name: jellyfin-config-pvc
fieldPaths:
- spec.resources.requests.storage
- source:
kind: ConfigMap
name: config
fieldPath: data.JELLYFIN_CACHE_STORAGE
targets:
- select:
kind: PersistentVolumeClaim
name: jellyfin-cache-pvc
fieldPaths:
- spec.resources.requests.storage
- source:
kind: ConfigMap
name: config
fieldPath: data.JELLYFIN_MEDIA_STORAGE
targets:
- select:
kind: PersistentVolumeClaim
name: jellyfin-media-pvc
fieldPaths:
- spec.resources.requests.storage
- source:
kind: ConfigMap
name: config
fieldPath: data.JELLYFIN_IMAGE
targets:
- select:
kind: Deployment
name: jellyfin
fieldPaths:
- spec.template.spec.containers.0.image

View File

@@ -0,0 +1,5 @@
---
apiVersion: v1
kind: Namespace
metadata:
name: jellyfin

37
apps/jellyfin/pvc.yaml Normal file
View File

@@ -0,0 +1,37 @@
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: jellyfin-config-pvc
namespace: jellyfin
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: jellyfin-cache-pvc
namespace: jellyfin
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: jellyfin-media-pvc
namespace: jellyfin
spec:
accessModes:
- ReadWriteMany
storageClassName: nfs
resources:
requests:
storage: 100Gi

View File

@@ -0,0 +1,15 @@
---
apiVersion: v1
kind: Service
metadata:
name: jellyfin
namespace: jellyfin
labels:
app: jellyfin
spec:
ports:
- port: 8096
targetPort: 8096
protocol: TCP
selector:
app: jellyfin