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.

Lets Setup NFS first:
- 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.
- 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
|
- 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
|
- 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
|
- 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 !!!