chore(immich): hardening of security according to audit report by Polaris
This commit is contained in:
parent
556acce1b2
commit
d3dca67841
6 changed files with 204 additions and 24 deletions
|
@ -2,10 +2,11 @@ apiVersion: v2
|
||||||
name: immich
|
name: immich
|
||||||
description: |
|
description: |
|
||||||
High-performance self-hosted photo and video management
|
High-performance self-hosted photo and video management
|
||||||
|
# renovate: image=ghcr.io/immich-app/immich-server
|
||||||
appVersion: 1.105.1
|
appVersion: 1.105.1
|
||||||
type: application
|
type: application
|
||||||
icon: https://avatars.githubusercontent.com/u/109746326?s=200&v=4
|
icon: https://avatars.githubusercontent.com/u/109746326?s=200&v=4
|
||||||
version: 0.1.16
|
version: 1.0.0
|
||||||
maintainers:
|
maintainers:
|
||||||
- name: Tommy Skaug
|
- name: Tommy Skaug
|
||||||
email: tommy@skaug.me
|
email: tommy@skaug.me
|
||||||
|
|
78
charts/immich/ci/pluto-values.yaml
Normal file
78
charts/immich/ci/pluto-values.yaml
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
config:
|
||||||
|
externalUrl: https://photos.example.com/
|
||||||
|
machineLearningUrl: http://immich-machine-learning.home.svc.cluster.local:3003
|
||||||
|
|
||||||
|
image:
|
||||||
|
repository: ghcr.io/immich-app/immich-server
|
||||||
|
|
||||||
|
envSecretName: immich-secret
|
||||||
|
|
||||||
|
library:
|
||||||
|
persistence:
|
||||||
|
existingClaim: immich
|
||||||
|
configuration:
|
||||||
|
trash:
|
||||||
|
enabled: false
|
||||||
|
days: 30
|
||||||
|
storageTemplate:
|
||||||
|
enabled: true
|
||||||
|
template: "{{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}}"
|
||||||
|
|
||||||
|
microservices:
|
||||||
|
securityContext: {}
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: "3Gi"
|
||||||
|
cpu: "1000m"
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 100Mi
|
||||||
|
|
||||||
|
server:
|
||||||
|
securityContext: {}
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: "3Gi"
|
||||||
|
cpu: "1000m"
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 100Mi
|
||||||
|
|
||||||
|
machineLearning:
|
||||||
|
persistence:
|
||||||
|
accessMode: ReadWriteOnce
|
||||||
|
size: 5Gi
|
||||||
|
image:
|
||||||
|
repository: ghcr.io/immich-app/immich-machine-learning
|
||||||
|
tag: v1.120.1
|
||||||
|
securityContext: {}
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: "3Gi"
|
||||||
|
cpu: "1000m"
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 100Mi
|
||||||
|
|
||||||
|
initContainers:
|
||||||
|
dbInit:
|
||||||
|
image:
|
||||||
|
repository: ghcr.io/onedr0p/postgres-init
|
||||||
|
tag: "16"
|
||||||
|
existingSecretName: immich-postgres-init-secret
|
||||||
|
pgvecto:
|
||||||
|
image:
|
||||||
|
repository: tensorchord/pgvecto-rs
|
||||||
|
tag: "pg16-v0.2.1-rootless"
|
||||||
|
existingSecretName: immich-postgres-init-secret
|
||||||
|
|
||||||
|
metrics:
|
||||||
|
enabled: true
|
||||||
|
port: 9001
|
||||||
|
|
||||||
|
redis:
|
||||||
|
host: dragonfly.databases.svc.cluster.local
|
||||||
|
port: 6397
|
||||||
|
|
||||||
|
postgres:
|
||||||
|
host: postgres-pgvectors-rw.databases.svc.cluster.local
|
|
@ -1,4 +1,3 @@
|
||||||
---
|
|
||||||
apiVersion: batch/v1
|
apiVersion: batch/v1
|
||||||
kind: Job
|
kind: Job
|
||||||
metadata:
|
metadata:
|
||||||
|
@ -9,22 +8,37 @@ spec:
|
||||||
template:
|
template:
|
||||||
spec:
|
spec:
|
||||||
restartPolicy: Never
|
restartPolicy: Never
|
||||||
|
automountServiceAccountToken: false
|
||||||
|
priorityClassName: "high-priority"
|
||||||
containers:
|
containers:
|
||||||
- name: general-db-init
|
- name: general-db-init
|
||||||
image: "{{ .Values.initContainers.dbInit.image.repository }}:{{ .Values.initContainers.dbInit.image.tag }}"
|
image: "{{ .Values.initContainers.dbInit.image.repository }}:{{ .Values.initContainers.dbInit.image.tag }}"
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
env:
|
env:
|
||||||
- name: INIT_POSTGRES_HOST
|
- name: INIT_POSTGRES_HOST
|
||||||
value: {{ .Values.postgres.host }}
|
value: {{ .Values.postgres.host }}
|
||||||
envFrom:
|
envFrom:
|
||||||
- secretRef:
|
- secretRef:
|
||||||
name: {{ .Values.initContainers.dbInit.existingSecretName }}
|
name: {{ .Values.initContainers.dbInit.existingSecretName }}
|
||||||
|
securityContext:
|
||||||
|
runAsUser: 1000
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "512Mi"
|
||||||
|
cpu: "250m"
|
||||||
|
limits:
|
||||||
|
memory: "1Gi"
|
||||||
|
cpu: "500m"
|
||||||
- name: pgvecto-db-init
|
- name: pgvecto-db-init
|
||||||
command: [ "bin/sh", "-c", "psql -a -f /initdb/create-extensions.sql" ]
|
command: [ "bin/sh", "-c", "psql -a -f /initdb/create-extensions.sql" ]
|
||||||
image: "{{ .Values.initContainers.pgvecto.image.repository }}:{{ .Values.initContainers.pgvecto.image.tag }}"
|
image: "{{ .Values.initContainers.pgvecto.image.repository }}:{{ .Values.initContainers.pgvecto.image.tag }}"
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: pgvector-initdb
|
- name: pgvector-initdb
|
||||||
mountPath: /initdb
|
mountPath: /initdb
|
||||||
readOnly: false
|
readOnly: true
|
||||||
env:
|
env:
|
||||||
- name: PGPASSWORD
|
- name: PGPASSWORD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
|
@ -40,8 +54,19 @@ spec:
|
||||||
key: INIT_POSTGRES_DBNAME
|
key: INIT_POSTGRES_DBNAME
|
||||||
- name: PGHOST
|
- name: PGHOST
|
||||||
value: {{ .Values.postgres.host }}
|
value: {{ .Values.postgres.host }}
|
||||||
|
securityContext:
|
||||||
|
runAsUser: 1000
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "512Mi"
|
||||||
|
cpu: "250m"
|
||||||
|
limits:
|
||||||
|
memory: "1Gi"
|
||||||
|
cpu: "500m"
|
||||||
volumes:
|
volumes:
|
||||||
- name: pgvector-initdb
|
- name: pgvector-initdb
|
||||||
configMap:
|
configMap:
|
||||||
name: {{ include "immich.fullname" . }}-pgvector-initdb
|
name: {{ include "immich.fullname" . }}-pgvector-initdb
|
||||||
backoffLimit: 3
|
backoffLimit: 3
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
---
|
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
|
@ -17,14 +16,30 @@ spec:
|
||||||
labels:
|
labels:
|
||||||
app: {{ include "immich.fullname" . }}-machine-learning
|
app: {{ include "immich.fullname" . }}-machine-learning
|
||||||
spec:
|
spec:
|
||||||
|
priorityClassName: "high-priority"
|
||||||
|
automountServiceAccountToken: false
|
||||||
|
topologySpreadConstraints:
|
||||||
|
- maxSkew: 1
|
||||||
|
topologyKey: "topology.kubernetes.io/zone"
|
||||||
|
whenUnsatisfiable: DoNotSchedule
|
||||||
|
labelSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: {{ include "immich.fullname" . }}-machine-learning
|
||||||
securityContext:
|
securityContext:
|
||||||
{{- toYaml .Values.machineLearning.securityContext | nindent 8 }}
|
runAsUser: 1000
|
||||||
|
runAsNonRoot: true
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
containers:
|
containers:
|
||||||
- name: immich-machine-learning
|
- name: immich-machine-learning
|
||||||
env:
|
env:
|
||||||
{{- include "immich.envs" . | nindent 10 }}
|
{{- include "immich.envs" . | nindent 10 }}
|
||||||
image: {{ .Values.machineLearning.image.repository }}:{{ .Values.machineLearning.image.tag }}
|
image: {{ .Values.machineLearning.image.repository }}:{{ .Values.machineLearning.image.tag }}
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: Always
|
||||||
|
securityContext:
|
||||||
|
runAsUser: 1000
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
failureThreshold: 3
|
failureThreshold: 3
|
||||||
httpGet:
|
httpGet:
|
||||||
|
@ -35,9 +50,9 @@ spec:
|
||||||
successThreshold: 1
|
successThreshold: 1
|
||||||
timeoutSeconds: 1
|
timeoutSeconds: 1
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 3003
|
- containerPort: 3003
|
||||||
name: http
|
name: http
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
failureThreshold: 3
|
failureThreshold: 3
|
||||||
httpGet:
|
httpGet:
|
||||||
|
@ -52,10 +67,20 @@ spec:
|
||||||
terminationMessagePath: /dev/termination-log
|
terminationMessagePath: /dev/termination-log
|
||||||
terminationMessagePolicy: File
|
terminationMessagePolicy: File
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- mountPath: /cache
|
- mountPath: /cache
|
||||||
name: cache
|
name: cache
|
||||||
serviceAccountName: {{ include "immich.fullname" . }}
|
serviceAccountName: {{ include "immich.fullname" . }}
|
||||||
volumes:
|
volumes:
|
||||||
- name: cache
|
- name: cache
|
||||||
persistentVolumeClaim:
|
persistentVolumeClaim:
|
||||||
claimName: {{ include "immich.fullname" . }}-machine-learning-cache
|
claimName: {{ include "immich.fullname" . }}-machine-learning-cache
|
||||||
|
---
|
||||||
|
apiVersion: policy/v1
|
||||||
|
kind: PodDisruptionBudget
|
||||||
|
metadata:
|
||||||
|
name: {{ include "immich.fullname" . }}-machine-learning-pdb
|
||||||
|
spec:
|
||||||
|
minAvailable: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: {{ include "immich.fullname" . }}-machine-learning
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
---
|
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
|
@ -15,9 +14,20 @@ spec:
|
||||||
labels:
|
labels:
|
||||||
app: {{ include "immich.fullname" . }}-microservices
|
app: {{ include "immich.fullname" . }}-microservices
|
||||||
spec:
|
spec:
|
||||||
|
priorityClassName: "high-priority"
|
||||||
|
automountServiceAccountToken: false
|
||||||
|
topologySpreadConstraints:
|
||||||
|
- maxSkew: 1
|
||||||
|
topologyKey: "topology.kubernetes.io/zone"
|
||||||
|
whenUnsatisfiable: DoNotSchedule
|
||||||
|
labelSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: {{ include "immich.fullname" . }}-microservices
|
||||||
securityContext:
|
securityContext:
|
||||||
{{- toYaml .Values.microservices.securityContext | nindent 8 }}
|
runAsUser: 1000
|
||||||
automountServiceAccountToken: true
|
runAsNonRoot: true
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
containers:
|
containers:
|
||||||
- name: immich-microservices
|
- name: immich-microservices
|
||||||
args:
|
args:
|
||||||
|
@ -27,7 +37,11 @@ spec:
|
||||||
env:
|
env:
|
||||||
{{- include "immich.envs" . | nindent 10 }}
|
{{- include "immich.envs" . | nindent 10 }}
|
||||||
image: {{ .Values.image.repository }}:v{{ .Chart.AppVersion }}
|
image: {{ .Values.image.repository }}:v{{ .Chart.AppVersion }}
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: Always
|
||||||
|
securityContext:
|
||||||
|
runAsUser: 1000
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
failureThreshold: 3
|
failureThreshold: 3
|
||||||
periodSeconds: 10
|
periodSeconds: 10
|
||||||
|
@ -65,3 +79,13 @@ spec:
|
||||||
- name: library
|
- name: library
|
||||||
persistentVolumeClaim:
|
persistentVolumeClaim:
|
||||||
claimName: {{ .Values.library.persistence.existingClaim }}
|
claimName: {{ .Values.library.persistence.existingClaim }}
|
||||||
|
---
|
||||||
|
apiVersion: policy/v1
|
||||||
|
kind: PodDisruptionBudget
|
||||||
|
metadata:
|
||||||
|
name: {{ include "immich.fullname" . }}-microservices-pdb
|
||||||
|
spec:
|
||||||
|
minAvailable: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: {{ include "immich.fullname" . }}-microservices
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
---
|
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
|
@ -15,8 +14,22 @@ spec:
|
||||||
labels:
|
labels:
|
||||||
app: {{ include "immich.fullname" . }}-server
|
app: {{ include "immich.fullname" . }}-server
|
||||||
spec:
|
spec:
|
||||||
|
priorityClassName: "high-priority"
|
||||||
|
automountServiceAccountToken: false
|
||||||
|
topologySpreadConstraints:
|
||||||
|
- maxSkew: 1
|
||||||
|
topologyKey: "topology.kubernetes.io/zone"
|
||||||
|
whenUnsatisfiable: DoNotSchedule
|
||||||
|
labelSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: {{ include "immich.fullname" . }}-server
|
||||||
securityContext:
|
securityContext:
|
||||||
{{- toYaml .Values.server.securityContext | nindent 8 }}
|
runAsUser: 1000
|
||||||
|
runAsNonRoot: true
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
|
capabilities:
|
||||||
|
drop: ["ALL"]
|
||||||
containers:
|
containers:
|
||||||
- name: immich-server
|
- name: immich-server
|
||||||
args:
|
args:
|
||||||
|
@ -26,7 +39,11 @@ spec:
|
||||||
env:
|
env:
|
||||||
{{- include "immich.envs" . | nindent 10 }}
|
{{- include "immich.envs" . | nindent 10 }}
|
||||||
image: {{ .Values.image.repository }}:v{{ .Chart.AppVersion }}
|
image: {{ .Values.image.repository }}:v{{ .Chart.AppVersion }}
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: Always
|
||||||
|
securityContext:
|
||||||
|
runAsUser: 1000
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
failureThreshold: 3
|
failureThreshold: 3
|
||||||
httpGet:
|
httpGet:
|
||||||
|
@ -64,3 +81,13 @@ spec:
|
||||||
- name: library
|
- name: library
|
||||||
persistentVolumeClaim:
|
persistentVolumeClaim:
|
||||||
claimName: {{ .Values.library.persistence.existingClaim }}
|
claimName: {{ .Values.library.persistence.existingClaim }}
|
||||||
|
---
|
||||||
|
apiVersion: policy/v1
|
||||||
|
kind: PodDisruptionBudget
|
||||||
|
metadata:
|
||||||
|
name: {{ include "immich.fullname" . }}-server-pdb
|
||||||
|
spec:
|
||||||
|
minAvailable: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: {{ include "immich.fullname" . }}-server
|
||||||
|
|
Loading…
Reference in a new issue