homelab/deployment/media/immich.yaml
Dan V deb6c38d7b chore: commit homelab setup — deployment, services, orchestration, skill
- Add .gitignore: exclude compiled binaries, build artifacts, and Helm
  values files containing real secrets (authentik, prometheus)
- Add all Kubernetes deployment manifests (deployment/)
- Add services source code: ha-sync, device-inventory, games-console,
  paperclip, parts-inventory
- Add Ansible orchestration: playbooks, roles, inventory, cloud-init
- Add hardware specs, execution plans, scripts, HOMELAB.md
- Add skills/homelab/SKILL.md + skills/install.sh to preserve Copilot skill
- Remove previously-tracked inventory-cli binary from git index

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-09 08:10:32 +02:00

446 lines
9.7 KiB
YAML

---
# NOTE: Secret 'immich-secret' must be created manually:
# kubectl create secret generic immich-secret \
# --from-literal=db-username=<USER> \
# --from-literal=db-password=<PASS> \
# --from-literal=db-name=immich \
# --from-literal=jwt-secret=<JWT_SECRET> \
# -n media
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
annotations: {}
name: immich-db-v2-pvc
namespace: media
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
storageClassName: nfs-immich
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
annotations: {}
name: immich-library-v2-pvc
namespace: media
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 290Gi
storageClassName: nfs-immich
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
annotations: {}
name: immich-ml-cache-v2-pvc
namespace: media
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 20Gi
storageClassName: nfs-immich
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
annotations: {}
name: immich-valkey-v2-pvc
namespace: media
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: nfs-immich
---
# immich-db: PostgreSQL with pgvecto.rs / vectorchord extensions for AI embeddings
apiVersion: apps/v1
kind: StatefulSet
metadata:
annotations: {}
name: immich-db
namespace: media
spec:
replicas: 1
selector:
matchLabels:
app: immich-db
serviceName: immich-db
template:
metadata:
labels:
app: immich-db
spec:
containers:
- env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
key: db-password
name: immich-secret
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
key: db-username
name: immich-secret
- name: POSTGRES_DB
valueFrom:
secretKeyRef:
key: db-name
name: immich-secret
- name: POSTGRES_INITDB_ARGS
value: --data-checksums
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0
livenessProbe:
exec:
command:
- pg_isready
failureThreshold: 6
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
name: postgres
ports:
- containerPort: 5432
name: postgres
readinessProbe:
exec:
command:
- pg_isready
failureThreshold: 3
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
resources:
limits:
cpu: 500m
memory: 1Gi
requests:
cpu: 100m
memory: 256Mi
volumeMounts:
- mountPath: /var/lib/postgresql/data
name: postgres-data
subPath: postgres
volumes:
- name: postgres-data
persistentVolumeClaim:
claimName: immich-db-v2-pvc
---
apiVersion: v1
kind: Service
metadata:
annotations: {}
name: immich-db
namespace: media
spec:
clusterIP: None
ports:
- name: postgres
port: 5432
targetPort: 5432
selector:
app: immich-db
---
apiVersion: apps/v1
kind: Deployment
metadata:
annotations: {}
name: immich-valkey
namespace: media
spec:
replicas: 1
selector:
matchLabels:
app: immich-valkey
template:
metadata:
labels:
app: immich-valkey
spec:
containers:
- args:
- --save
- '60'
- '1'
- --loglevel
- warning
image: docker.io/valkey/valkey:9.0-alpine
livenessProbe:
failureThreshold: 3
initialDelaySeconds: 10
periodSeconds: 10
tcpSocket:
port: 6379
timeoutSeconds: 5
name: valkey
ports:
- containerPort: 6379
name: redis
readinessProbe:
failureThreshold: 3
initialDelaySeconds: 5
periodSeconds: 10
tcpSocket:
port: 6379
timeoutSeconds: 5
resources:
limits:
cpu: 200m
memory: 256Mi
requests:
cpu: 50m
memory: 64Mi
volumeMounts:
- mountPath: /data
name: data
volumes:
- name: data
persistentVolumeClaim:
claimName: immich-valkey-v2-pvc
---
apiVersion: v1
kind: Service
metadata:
annotations: {}
name: immich-valkey
namespace: media
spec:
ports:
- name: redis
port: 6379
targetPort: 6379
selector:
app: immich-valkey
type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
annotations: {}
name: immich-server
namespace: media
spec:
replicas: 2
selector:
matchLabels:
app: immich-server
template:
metadata:
labels:
app: immich-server
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: immich-server
topologyKey: kubernetes.io/hostname
containers:
- env:
- name: DB_HOSTNAME
value: immich-db
- name: DB_PORT
value: '5432'
- name: DB_USERNAME
valueFrom:
secretKeyRef:
key: db-username
name: immich-secret
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
key: db-password
name: immich-secret
- name: DB_DATABASE_NAME
valueFrom:
secretKeyRef:
key: db-name
name: immich-secret
- name: DB_STORAGE_TYPE
value: HDD
- name: DB_VECTOR_EXTENSION
value: vectorchord
- name: REDIS_HOSTNAME
value: immich-valkey
- name: REDIS_PORT
value: '6379'
- name: IMMICH_MACHINE_LEARNING_URL
value: http://immich-ml:3003
- name: JWT_SECRET
valueFrom:
secretKeyRef:
key: jwt-secret
name: immich-secret
image: ghcr.io/immich-app/immich-server:release
livenessProbe:
failureThreshold: 5
httpGet:
path: /api/server/ping
port: 2283
initialDelaySeconds: 60
periodSeconds: 30
timeoutSeconds: 10
name: immich-server
ports:
- containerPort: 2283
name: http
readinessProbe:
failureThreshold: 3
httpGet:
path: /api/server/ping
port: 2283
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 10
resources:
limits:
cpu: 1000m
memory: 2Gi
requests:
cpu: 250m
memory: 512Mi
volumeMounts:
- mountPath: /usr/src/app/upload
name: library
volumes:
- name: library
persistentVolumeClaim:
claimName: immich-library-v2-pvc
---
apiVersion: v1
kind: Service
metadata:
annotations: {}
name: immich-web
namespace: media
spec:
ports:
- name: http
nodePort: 32283
port: 2283
targetPort: 2283
selector:
app: immich-server
type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
annotations: {}
name: immich-ml
namespace: media
spec:
replicas: 2
selector:
matchLabels:
app: immich-ml
template:
metadata:
labels:
app: immich-ml
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: immich-ml
topologyKey: kubernetes.io/hostname
containers:
- env:
- name: TRANSFORMERS_CACHE
value: /cache
- name: HF_XET_CACHE
value: /cache/huggingface-xet
- name: MPLCONFIGDIR
value: /cache/matplotlib-config
image: ghcr.io/immich-app/immich-machine-learning:release
livenessProbe:
failureThreshold: 5
httpGet:
path: /ping
port: 3003
initialDelaySeconds: 60
periodSeconds: 30
timeoutSeconds: 10
name: machine-learning
ports:
- containerPort: 3003
name: http
readinessProbe:
failureThreshold: 3
httpGet:
path: /ping
port: 3003
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 10
resources:
limits:
cpu: 4000m
memory: 8Gi
requests:
cpu: 500m
memory: 2Gi
volumeMounts:
- mountPath: /cache
name: cache
volumes:
- name: cache
persistentVolumeClaim:
claimName: immich-ml-cache-v2-pvc
---
apiVersion: v1
kind: Service
metadata:
annotations: {}
name: immich-ml
namespace: media
spec:
ports:
- name: http
port: 3003
targetPort: 3003
selector:
app: immich-ml
type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/proxy-body-size: '0'
nginx.ingress.kubernetes.io/proxy-read-timeout: '600'
nginx.ingress.kubernetes.io/proxy-send-timeout: '600'
name: immich
namespace: media
spec:
ingressClassName: nginx
rules:
- host: photos.vandachevici.ro
http:
paths:
- backend:
service:
name: immich-web
port:
number: 2283
path: /
pathType: Prefix
tls:
- hosts:
- photos.vandachevici.ro
secretName: immich-tls