--- # NOTE: Secret 'immich-secret' must be created manually: # kubectl create secret generic immich-secret \ # --from-literal=db-username= \ # --from-literal=db-password= \ # --from-literal=db-name=immich \ # --from-literal=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