Files
kube-single-age/clusters/base/apps/immich/helmrelease-server.yaml
T
2026-08-23 12:02:56 +03:00

202 lines
6.6 KiB
YAML

apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: immich-server
namespace: photo
spec:
interval: 30m
chartRef:
kind: OCIRepository
name: immich
driftDetection:
mode: enabled
values:
controllers:
server:
strategy: Recreate
podDisruptionBudget:
maxUnavailable: "0"
initContainers:
fix-permissions:
image:
repository: hectorm/nfs-ganesha
tag: v10
command:
- sh
- -c
- chmod -R a+rwX /disks/library-recent /disks/library-archive
# native sidecar (restartPolicy: Always): mounts the two library
# disks and exposes their union at /disks/merged-library via
# FUSE. It must be up and actually mounted *before* the "app"
# container is created, since HostToContainer propagation only
# relays mounts made *after* the receiving container's own mount
# exists - it won't retroactively pick up a FUSE mount that's
# already there. Running it as a restartPolicy:Always init
# container (started, gated on the startupProbe below, before
# regular containers) guarantees that ordering; a regular sidecar
# container racing "app" on every pod start does not.
mergerfs:
dependsOn:
- fix-permissions
restartPolicy: Always
image:
repository: ghcr.io/hotio/mergerfs
tag: release-v2.42.0
args:
- "-o"
# library-recent listed first: category.create=ff means new
# files created through the merged mount (i.e. new immich
# uploads going forward) land on library-recent by default,
# which is exactly what's wanted for freshly-uploaded photos.
- "allow_other,use_ino,func.create=ff,category.action=all,category.create=ff,category.search=newest"
- "/disks/library-recent:/disks/library-archive"
- "/disks/merged-library"
securityContext:
privileged: true
probes:
startup:
enabled: true
custom: true
spec:
exec:
command:
- sh
- -c
- grep -q fuse.mergerfs /proc/mounts
periodSeconds: 1
timeoutSeconds: 2
failureThreshold: 30
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
memory: 512Mi
containers:
app:
image:
repository: ghcr.io/immich-app/immich-server
# make sure immich-machine-learning version match this
tag: v3.1.0
env:
TZ: Europe/Moscow
DB_HOSTNAME: immich-postgres
DB_PORT: "5432"
DB_USERNAME: postgres
DB_DATABASE_NAME: immich
DB_PASSWORD:
valueFrom:
secretKeyRef:
name: immich-secrets
key: DB_PASSWORD
REDIS_HOSTNAME: immich-redis
REDIS_PORT: "6379"
IMMICH_MACHINE_LEARNING_URL: http://immich-ml:3003
probes:
# first boot runs DB migrations + vector index setup, which
# can take a while - without a startup probe the default
# liveness probe (periodSeconds=10, failureThreshold=3) kills
# the container ~30s in, well before it's finished binding
# the port, causing an endless restart loop.
startup:
enabled: true
spec:
periodSeconds: 5
failureThreshold: 60
liveness:
enabled: true
readiness:
enabled: true
resources:
requests:
cpu: 200m
memory: 512Mi
limits:
memory: 4Gi
service:
app:
controller: server
ports:
http:
port: 2283
ingress:
app:
className: traefik
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: photo.aggtaa.com
paths:
- path: /
pathType: Prefix
service:
identifier: app
port: http
tls:
- secretName: immich-tls
hosts:
- photo.aggtaa.com
persistence:
# Immich's "library" folder, mergerfs-merged from two disks: recent
# files (per the rsync migration's cutoff) and everything else.
# New uploads going forward land on library-recent (see mergerfs
# category.create above). Not reusing the old single 800Gi library
# PVC/PV - this replaces it (that PVC becomes orphaned, retained,
# and unused; clean it up separately if no longer wanted).
library-recent:
type: persistentVolumeClaim
accessMode: ReadWriteOnce
size: 200Gi
storageClass: longhorn-single-replica
retain: true
advancedMounts:
server:
mergerfs:
- path: /disks/library-recent
fix-permissions:
- path: /disks/library-recent
library-archive:
type: persistentVolumeClaim
accessMode: ReadWriteOnce
size: 500Gi
storageClass: longhorn-single-replica
retain: true
advancedMounts:
server:
mergerfs:
- path: /disks/library-archive
fix-permissions:
- path: /disks/library-archive
merged-library:
type: emptyDir
advancedMounts:
server:
mergerfs:
- path: /disks/merged-library
mountPropagation: Bidirectional
app:
- path: /data/library
mountPropagation: HostToContainer
dev-fuse:
type: hostPath
hostPath: /dev/fuse
advancedMounts:
server:
mergerfs:
- path: /dev/fuse
# everything immich keeps outside "library" (backups, encoded-video,
# profile, thumbs, upload) - plain volume, no mergerfs involved.
other:
type: persistentVolumeClaim
accessMode: ReadWriteOnce
size: 200Gi
storageClass: longhorn-single-replica
retain: true
advancedMounts:
server:
app:
- path: /data