Posts Immich server deployment on kubernetes with NFS
Post
Cancel

Immich server deployment on kubernetes with NFS

In this documentation we have use NFS for volumes for container. We used OpenMediaVault to create NFS. We have used Kubernetes internal dns for communication between services.

Immich Picture

Lets Setup NFS first:

  1. Mount your Hard Drive to OMV, then create or use existing volume for sharing. If you want to learn how to setup NFS from scratch on Ubuntu server then read this article.
  2. Create share folder immich-upload with insecure, rw, subtree_check options. As it will be used by immich server as a root permission you need to give R/W permission:
    1
    
    chmod 777 -R /export/immich-upload
    
  3. Create share folder immich-model-cache with insecure, rw, subtree_check options. As it will be used by immich machine learning as a root permission you need to give R/W permission:
    1
    
    chmod 777 -R /export/immich-model-cache
    
  4. Create share folder immich-pg-data with anongid=999, anonuid=26, insecure, no_root_squash, rw, subtree_check options. As it will be used by immich postgres as a non root permission you need to give R/W permission:
    1
    
    chmod 777 -R /export/immich-pg-data
    
  5. Now NFS setup is complete.

Kubernetes deployment creation:

If you want to install with docker-compose then read this article.

1. Create namespace.yaml namespace for immich deployment.

1
2
3
4
apiVersion: v1
kind: Namespace
metadata:
  name: immich

2. Create postgresql.yaml for immich postgres deployment.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
apiVersion: v1
kind: Secret
metadata:
  name: postgresql-secret
  namespace: immich
type: Opaque
data:
  POSTGRES_USER: cG9zdGdyZXM=
  POSTGRES_PASSWORD: cG9zdGdyZXM=

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: immich-pg-pv
  namespace: immich
spec:
  capacity:
    storage: 4Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Delete
  nfs:
    server: 10.20.1.50
    path: /export/immich-pg-data

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: immich-pg-pvc
  namespace: immich
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 4Gi
  volumeName: immich-pg-pv

---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: postgresql
  name: postgresql
  namespace: immich
spec:
  replicas: 1
  selector:
    matchLabels:
      app: postgresql
  template:
    metadata:
      labels:
        app: postgresql
    spec:
      securityContext:
        runAsUser: 26
        runAsGroup: 999
        fsGroup: 999
      containers:
        - name: postgresql
          image: techthinkerorg/immich-postgres:v1.135.3
          imagePullPolicy: Always
          ports:
            - containerPort: 5432
              name: db-port
          volumeMounts:
            - name: pg-data
              mountPath: /var/lib/postgresql/data
          env:
            - name: POSTGRES_DB
              value: "immich"
            - name: POSTGRES_INITDB_ARGS
              value: "--data-checksums"
          envFrom:
            - secretRef:
                name: postgresql-secret
      volumes:
        - name: pg-data
          persistentVolumeClaim:
            claimName: immich-pg-pvc

---
apiVersion: v1
kind: Service
metadata:
  name: postgresql
  namespace: immich
spec:
  selector:
    app: postgresql
  type: ClusterIP
  ports:
    - name: db-port
      protocol: TCP
      port: 5432
      targetPort: 5432

3. Create redis.yaml for immich redis deployment.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: redis
  name: redis
  namespace: immich
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
        - name: redis
          image: techthinkerorg/immich-redis:v1.135.3
          imagePullPolicy: Always
          readinessProbe:
            exec:
              command:
                - sh
                - -c
                - redis-cli ping || exit 1
            initialDelaySeconds: 30
            periodSeconds: 10
            failureThreshold: 3
          ports:
            - containerPort: 6379
              name: db-port

---
apiVersion: v1
kind: Service
metadata:
  name: redis
  namespace: immich
spec:
  selector:
    app: redis
  type: ClusterIP
  ports:
    - name: db-port
      protocol: TCP
      port: 6379
      targetPort: 6379

4. Create immich-ml.yaml for immich machine learning deployment.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
apiVersion: v1
kind: PersistentVolume
metadata:
  name: immich-model-cache-pv
  namespace: immich
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Delete
  nfs:
    server: 10.20.1.50
    path: /export/immich-model-cache

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: immich-model-cache-pvc
  namespace: immich
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi
  volumeName: immich-model-cache-pv

---
apiVersion: v1
kind: Secret
metadata:
  name: immich-ml-secret
  namespace: immich
type: Opaque
data:
  DB_USERNAME: cG9zdGdyZXM=
  DB_PASSWORD: cG9zdGdyZXM=

---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: immich-ml
  name: immich-ml
  namespace: immich
spec:
  replicas: 1
  selector:
    matchLabels:
      app: immich-ml
  template:
    metadata:
      labels:
        app: immich-ml
    spec:
      securityContext:
        runAsUser: 0
        runAsGroup: 0
        fsGroup: 0
      containers:
        - name: immich-ml
          image: techthinkerorg/immich-machine-learning:v1.135.3
          imagePullPolicy: Always
          ports:
            - containerPort: 3003
              name: ml-port
          volumeMounts:
            - name: model-cache-data
              mountPath: /cache
          env:
            - name: ENABLE_FACE_RECOGNITION
              value: "true"
            - name: ENABLE_OBJECT_RECOGNITION
              value: "true"
            - name: LOG_LEVEL
              value: "DEBUG"
            - name: DB_DATABASE_NAME
              value: "immich"
          envFrom:
            - secretRef:
                name: immich-ml-secret
      volumes:
        - name: model-cache-data
          persistentVolumeClaim:
            claimName: immich-model-cache-pvc

---
apiVersion: v1
kind: Service
metadata:
  name: immich-ml
  namespace: immich
spec:
  selector:
    app: immich-ml
  type: ClusterIP
  ports:
    - name: ml-port
      protocol: TCP
      port: 3003
      targetPort: 3003

5. Create immich-server.yaml for immich server deployment.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
apiVersion: v1
kind: PersistentVolume
metadata:
  name: immich-upload-pv
  namespace: immich
spec:
  capacity:
    storage: 400Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Delete
  nfs:
    server: 10.20.1.50
    path: /export/immich-upload

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: immich-upload-pvc
  namespace: immich
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 400Gi
  volumeName: immich-upload-pv

---
apiVersion: v1
kind: Secret
metadata:
  name: immich-server-secret
  namespace: immich
type: Opaque
data:
  DB_USERNAME: cG9zdGdyZXM=
  DB_PASSWORD: cG9zdGdyZXM=

---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: immich-server
  name: immich-server
  namespace: immich
spec:
  replicas: 1
  selector:
    matchLabels:
      app: immich-server
  template:
    metadata:
      labels:
        app: immich-server
    spec:
      securityContext:
        runAsUser: 0
        runAsGroup: 0
        fsGroup: 0
      containers:
        - name: immich-server
          image: techthinkerorg/immich-server:v1.135.3
          imagePullPolicy: Always
          ports:
            - containerPort: 2283
              name: immich-port
          volumeMounts:
            - name: upload-data
              mountPath: /usr/src/app/upload
          env:
            - name: IMMICH_HOST
              value: "0.0.0.0"
            - name: MACHINE_LEARNING_URL
              value: "http://immich-ml.immich.svc.cluster.local:3003"
            - name: DB_HOSTNAME
              value: "postgresql.immich.svc.cluster.local"
            - name: DB_PORT
              value: "5432"
            - name: DB_DATABASE_NAME
              value: "immich"
            - name: REDIS_HOSTNAME
              value: "redis.immich.svc.cluster.local"
            - name: REDIS_PORT
              value: "6379"
          envFrom:
            - secretRef:
                name: immich-server-secret
      volumes:
        - name: upload-data
          persistentVolumeClaim:
            claimName: immich-upload-pvc

---
apiVersion: v1
kind: Service
metadata:
  name: immich-server
  namespace: immich
spec:
  selector:
    app: immich-server
  type: ClusterIP
  ports:
    - name: immich-port
      protocol: TCP
      port: 80
      targetPort: 2283

Begain Installation

Now we have created all the Kubernetes deployment yaml, we should execute on sequence basis. If you don’t maintain sequence then it might break the deployment. Lets deploy!

1. Deploy namespace and postgresql using kubectl.

1
2
kubectl apply -f namespace.yaml
kubectl apply -f postgresql.yaml

2. Now wait, Check if database is up and running.

1
kubectl get pods -n immich

3. Existing server migration

If you are migrating an existing server then kindly restore your database in this stage.

  • Forward postgresql port in one terminal.
    1
    
    kubectl port-forward svc/postgresql -n immich 5432:5432
    
  • Restore data
    1
    
    psql -h 127.0.0.1 -U postgres -d immich < immich-backup.sql
    
  • Close port forwarding.

4. Now you are ready to deploy other services.

5. Deploy redis

Deploy redis and wait for it to be ready.

1
2
kubectl apply -f redis.yaml
kubectl get pods -n immich

6. Deploy immich and ML server

1
2
kubectl apply -f immich-ml.yaml
kubectl apply -f immich-server.yaml

7. Wait for all pods to be ready.

1
kubectl get pods -n immich

8. Access immich server

  • Forward immich server port in one terminal.
    1
    
    kubectl port-forward svc/immich-server -n immich 8080:80
    
  • Open browser and access immich server at http://localhost:8080
  • Use cloudflare tunnel to access immich server from internet.
    1
    
    http://immich-server.immich.svc.cluster.local
    
  • If you have public ip then expose through ingress.

9. Complete the installation

You are done. Enjoy !!!