commit bfc9c119ecc8c9bc25934136af07e56e53693b91
Author: Tanguy Herbron <tanguy.herbron@outlook.com>
Date:   Mon Feb 24 20:25:38 2025 +0100

    feat: Initial configuration

diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e69de29
diff --git a/manifests/configmap.yaml b/manifests/configmap.yaml
new file mode 100644
index 0000000..16c47ac
--- /dev/null
+++ b/manifests/configmap.yaml
@@ -0,0 +1,210 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: immich-config
+  namespace: immich
+data:
+  immich.json: |
+    {
+      "backup": {
+        "database": {
+          "cronExpression": "0 02 * * *",
+          "enabled": true,
+          "keepLastAmount": 14
+        }
+      },
+      "ffmpeg": {
+        "accel": "disabled",
+        "accelDecode": false,
+        "acceptedAudioCodecs": [
+          "aac",
+          "mp3",
+          "libopus",
+          "pcm_s16le"
+        ],
+        "acceptedContainers": [
+          "mov",
+          "ogg",
+          "webm"
+        ],
+        "acceptedVideoCodecs": [
+          "h264"
+        ],
+        "bframes": -1,
+        "cqMode": "auto",
+        "crf": 23,
+        "gopSize": 0,
+        "maxBitrate": "0",
+        "preferredHwDevice": "auto",
+        "preset": "ultrafast",
+        "refs": 0,
+        "targetAudioCodec": "aac",
+        "targetResolution": "720",
+        "targetVideoCodec": "h264",
+        "temporalAQ": false,
+        "threads": 0,
+        "tonemap": "hable",
+        "transcode": "required",
+        "twoPass": false
+      },
+      "image": {
+        "colorspace": "p3",
+        "extractEmbedded": false,
+        "preview": {
+          "format": "jpeg",
+          "quality": 80,
+          "size": 1440
+        },
+        "thumbnail": {
+          "format": "webp",
+          "quality": 80,
+          "size": 250
+        }
+      },
+      "job": {
+        "backgroundTask": {
+          "concurrency": 5
+        },
+        "faceDetection": {
+          "concurrency": 2
+        },
+        "library": {
+          "concurrency": 5
+        },
+        "metadataExtraction": {
+          "concurrency": 5
+        },
+        "migration": {
+          "concurrency": 5
+        },
+        "notifications": {
+          "concurrency": 5
+        },
+        "search": {
+          "concurrency": 5
+        },
+        "sidecar": {
+          "concurrency": 5
+        },
+        "smartSearch": {
+          "concurrency": 2
+        },
+        "thumbnailGeneration": {
+          "concurrency": 3
+        },
+        "videoConversion": {
+          "concurrency": 1
+        }
+      },
+      "library": {
+        "scan": {
+          "cronExpression": "0 0 * * *",
+          "enabled": true
+        },
+        "watch": {
+          "enabled": false
+        }
+      },
+      "logging": {
+        "enabled": true,
+        "level": "log"
+      },
+      "machineLearning": {
+        "clip": {
+          "enabled": true,
+          "modelName": "ViT-B-32__openai"
+        },
+        "duplicateDetection": {
+          "enabled": true,
+          "maxDistance": 0.01
+        },
+        "enabled": true,
+        "facialRecognition": {
+          "enabled": true,
+          "maxDistance": 0.5,
+          "minFaces": 3,
+          "minScore": 0.7,
+          "modelName": "buffalo_l"
+        },
+        "urls": [
+          "http://immich-svc.immich.svc.cluster.local:3003"
+        ]
+      },
+      "map": {
+        "darkStyle": "https://tiles.immich.cloud/v1/style/dark.json",
+        "enabled": true,
+        "lightStyle": "https://tiles.immich.cloud/v1/style/light.json"
+      },
+      "metadata": {
+        "faces": {
+          "import": false
+        }
+      },
+      "newVersionCheck": {
+        "enabled": true
+      },
+      "notifications": {
+        "smtp": {
+          "enabled": false,
+          "from": "",
+          "replyTo": "",
+          "transport": {
+            "host": "",
+            "ignoreCert": false,
+            "password": "",
+            "port": 587,
+            "username": ""
+          }
+        }
+      },
+      "oauth": {
+        "autoLaunch": false,
+        "autoRegister": true,
+        "buttonText": "Login with OAuth",
+        "clientId": "",
+        "clientSecret": "",
+        "defaultStorageQuota": 0,
+        "enabled": false,
+        "issuerUrl": "",
+        "mobileOverrideEnabled": false,
+        "mobileRedirectUri": "",
+        "profileSigningAlgorithm": "none",
+        "scope": "openid email profile",
+        "signingAlgorithm": "RS256",
+        "storageLabelClaim": "preferred_username",
+        "storageQuotaClaim": "immich_quota"
+      },
+      "passwordLogin": {
+        "enabled": true
+      },
+      "reverseGeocoding": {
+        "enabled": true
+      },
+      "server": {
+        "externalDomain": "",
+        "loginPageMessage": "",
+        "publicUsers": true
+      },
+      "storageTemplate": {
+        "enabled": true,
+        "hashVerificationEnabled": true,
+        "template": "{{y}}/{{dd}}-{{MM}}/{{filename}}"
+      },
+      "templates": {
+        "email": {
+          "albumInviteTemplate": "",
+          "albumUpdateTemplate": "",
+          "welcomeTemplate": ""
+        }
+      },
+      "theme": {
+        "customCss": ""
+      },
+      "trash": {
+        "days": 30,
+        "enabled": true
+      },
+      "user": {
+        "deleteDelay": 7
+      }
+    }
diff --git a/manifests/database-backup.yaml b/manifests/database-backup.yaml
new file mode 100644
index 0000000..70f2e49
--- /dev/null
+++ b/manifests/database-backup.yaml
@@ -0,0 +1,10 @@
+apiVersion: postgresql.cnpg.io/v1
+kind: ScheduledBackup
+metadata:
+  name: immich-db-backup
+  namespace: immich
+spec:
+  schedule: "0 0 0 * * *"
+  backupOwnerReference: self
+  cluster:
+    name: immich-db
diff --git a/manifests/database-ondemand-backup.yaml b/manifests/database-ondemand-backup.yaml
new file mode 100644
index 0000000..0ac8991
--- /dev/null
+++ b/manifests/database-ondemand-backup.yaml
@@ -0,0 +1,8 @@
+apiVersion: postgresql.cnpg.io/v1
+kind: Backup
+metadata:
+  name: gitea-db-ondemand-backup-100225
+  namespace: gitea
+spec:
+  cluster:
+    name: gitea-db
diff --git a/manifests/database-recovery.yaml b/manifests/database-recovery.yaml
new file mode 100644
index 0000000..a8940ac
--- /dev/null
+++ b/manifests/database-recovery.yaml
@@ -0,0 +1,48 @@
+apiVersion: postgresql.cnpg.io/v1
+kind: Cluster
+metadata:
+  name: gitea-db
+  namespace: gitea
+
+spec:
+  instances: 2
+
+  storage:
+    size: 1Gi
+    storageClass: local-path
+
+  bootstrap:
+    recovery:
+      source: gitea-db
+
+  postgresql:
+    pg_hba:
+      - host all all all md5
+
+  externalClusters:
+    - name: gitea-db
+      barmanObjectStore:
+        serverName: gitea-db
+        destinationPath: "s3://halis/cloudnativepg"
+        endpointURL: https://s3.halia.dev
+        s3Credentials:
+          accessKeyId:
+            name: s3-secret
+            key: AWS_ACCESS_KEY_ID
+          secretAccessKey:
+            name: s3-secret
+            key: AWS_SECRET_ACCESS_KEY
+          region:
+            name: s3-secret
+            key: AWS_REGION
+        wal:
+          compression: gzip
+          maxParallel: 8
+
+  resources:
+    requests:
+      cpu: 100m
+      memory: 100Mi
+    limits:
+      cpu: 500m
+      memory: 500Mi
diff --git a/manifests/database.yaml b/manifests/database.yaml
new file mode 100644
index 0000000..8ed693b
--- /dev/null
+++ b/manifests/database.yaml
@@ -0,0 +1,73 @@
+apiVersion: postgresql.cnpg.io/v1
+kind: Cluster
+metadata:
+  name: immich-db
+  namespace: immich
+
+spec:
+  imageName: ghcr.io/tensorchord/cloudnative-pgvecto.rs:16.5-v0.3.0
+  instances: 1
+
+  storage:
+    size: 1Gi
+    storageClass: local-path
+
+  bootstrap:
+    initdb:
+      database: immich
+      owner: immich
+      secret:
+        name: immich-db
+      postInitSQL:
+        - ALTER SYSTEM SET search_path TO "$user", public, vectors;
+        - CREATE EXTENSION IF NOT EXISTS "vectors";
+      dataChecksums: true
+
+  postgresql:
+    pg_hba:
+      - host all all all md5
+    shared_preload_libraries:
+      - "vectors.so"
+    parameters:
+      max_wal_size: 2GB
+      shared_buffers: 512MB
+      wal_compression: on
+
+  backup:
+    barmanObjectStore:
+      destinationPath: "s3://halis/cloudnativepg"
+      endpointURL: https://s3.halia.dev
+      s3Credentials:
+        accessKeyId:
+          name: s3-secret
+          key: AWS_ACCESS_KEY_ID
+        secretAccessKey:
+          name: s3-secret
+          key: AWS_SECRET_ACCESS_KEY
+        region:
+          name: s3-secret
+          key: AWS_REGION
+      wal:
+        compression: gzip
+        maxParallel: 8
+
+  resources:
+    requests:
+      cpu: 100m
+      memory: 512Mi
+    limits:
+      cpu: 500m
+      memory: 1024Mi
+
+  monitoring:
+    enablePodMonitor: true
+
+  affinity:
+    nodeAffinity:
+      requiredDuringSchedulingIgnoredDuringExecution:
+        nodeSelectorTerms:
+          - matchExpressions:
+              - key: kubernetes.io/hostname
+                operator: In
+                values:
+                  - worker-1
diff --git a/manifests/deployment.yaml b/manifests/deployment.yaml
new file mode 100644
index 0000000..fbf881b
--- /dev/null
+++ b/manifests/deployment.yaml
@@ -0,0 +1,78 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+    name: immich
+    namespace: immich
+spec:
+    replicas: 1
+    selector:
+        matchLabels:
+            app: immich
+    template:
+        metadata:
+            labels:
+                app: immich
+        spec:
+            hostname: immich
+            subdomain: immich
+            containers:
+              - name: immich-server
+                image: ghcr.io/immich-app/immich-server:v1.126.1
+                ports:
+                  - containerPort: 2283
+                  - containerPort: 8081
+                    name: metrics
+                env:
+                  - name: IMMICH_TELEMETRY_INCLUDE
+                    value: "all"
+                  - name: IMMICH_CONFIG_FILE
+                    value: "/usr/src/app/config/immich.json"
+                  - name: REDIS_HOSTNAME
+                    value: "redis-svc.immich.svc.cluster.local"
+                  - name: REDIS_PORT
+                    value: "6379"
+                  - name: DB_HOSTNAME
+                    value: "immich-db-rw.immich.svc.cluster.local"
+                  - name: DB_USERNAME
+                    valueFrom:
+                      secretKeyRef:
+                        name: immich-db
+                        key: username
+                  - name: DB_PASSWORD
+                    valueFrom:
+                      secretKeyRef:
+                        name: immich-db
+                        key: password
+                volumeMounts:
+                  - mountPath: "/usr/src/app/upload"
+                    name: immich-upload
+                  - mountPath: "/etc/localtime"
+                    name: localtime
+                    readOnly: true
+                  - mountPath: "/usr/src/app/config/immich.json"
+                    name: immich-config
+                    subPath: immich.json
+              - name: immich-machine-learning
+                image: ghcr.io/immich-app/immich-machine-learning:v1.126.1
+                ports:
+                  - containerPort: 3003
+                volumeMounts:
+                  - mountPath: "/cache"
+                    name: immich-model
+              - name: redis
+                image: redis:7.4.2
+                ports:
+                  - containerPort: 6379
+            volumes:
+              - name: immich-upload
+                persistentVolumeClaim:
+                  claimName: immich-pvc
+              - name: immich-model
+                persistentVolumeClaim:
+                  claimName: immich-model-pvc
+              - name: immich-config
+                configMap:
+                  name: immich-config
+              - name: localtime
+                hostPath:
+                  path: /etc/localtime
diff --git a/manifests/ingress.yaml b/manifests/ingress.yaml
new file mode 100644
index 0000000..b1ea021
--- /dev/null
+++ b/manifests/ingress.yaml
@@ -0,0 +1,29 @@
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+  name: immich-ingress
+  namespace: immich
+  annotations:
+    cert-manager.io/cluster-issuer: letsencrypt-production
+    kubernetes.io/ingress.class: nginx-external
+    acme.cert-manager.io/http01-edit-in-place: "true"
+    nginx.ingress.kubernetes.io/proxy-body-size: "0"
+    nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
+    nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
+spec:
+  tls:
+  - hosts:
+    - photos.halis.io
+    secretName: photos-halis-io-tls
+  ingressClassName: nginx-external
+  rules:
+  - host: photos.halis.io
+    http:
+      paths:
+        - path: /
+          pathType: Prefix
+          backend:
+            service:
+              name: immich-svc
+              port:
+                number: 80
diff --git a/manifests/kustomization.yaml b/manifests/kustomization.yaml
new file mode 100644
index 0000000..47c5f32
--- /dev/null
+++ b/manifests/kustomization.yaml
@@ -0,0 +1,16 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+
+resources:
+  - namespace.yaml
+  - secrets.yaml
+  - database.yaml
+  - deployment.yaml
+  - database-backup.yaml
+  - service.yaml
+  - servicemonitor.yaml
+  - redis-service.yaml
+  - ingress.yaml
+  - configmap.yaml
+  - pvc.yaml
+  - model-pvc.yaml
diff --git a/manifests/model-pvc.yaml b/manifests/model-pvc.yaml
new file mode 100644
index 0000000..2d46aaf
--- /dev/null
+++ b/manifests/model-pvc.yaml
@@ -0,0 +1,15 @@
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+  name: immich-model-pvc
+  namespace: immich
+  labels:
+    recurring-job.longhorn.io/source: enabled
+    recurring-job-group.longhorn.io/standard-pvc: enabled
+spec:
+  accessModes:
+    - ReadWriteOnce
+  resources:
+    requests:
+      storage: 5Gi
+  storageClassName: redundant-storage-class
diff --git a/manifests/namespace.yaml b/manifests/namespace.yaml
new file mode 100644
index 0000000..c796392
--- /dev/null
+++ b/manifests/namespace.yaml
@@ -0,0 +1,4 @@
+apiVersion: v1
+kind: Namespace
+metadata:
+  name: immich
diff --git a/manifests/pvc.yaml b/manifests/pvc.yaml
new file mode 100644
index 0000000..601e4b2
--- /dev/null
+++ b/manifests/pvc.yaml
@@ -0,0 +1,15 @@
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+  name: immich-pvc
+  namespace: immich
+  labels:
+    recurring-job.longhorn.io/source: enabled
+    recurring-job-group.longhorn.io/standard-pvc: enabled
+spec:
+  accessModes:
+    - ReadWriteOnce
+  resources:
+    requests:
+      storage: 100Gi
+  storageClassName: redundant-storage-class
diff --git a/manifests/redis-service.yaml b/manifests/redis-service.yaml
new file mode 100644
index 0000000..54c244c
--- /dev/null
+++ b/manifests/redis-service.yaml
@@ -0,0 +1,15 @@
+apiVersion: v1
+kind: Service
+metadata:
+    name: redis-svc
+    namespace: immich
+    labels:
+      app.kubernetes.io/name: immich
+spec:
+    ports:
+        - name: http
+          port: 6379
+          protocol: TCP
+          targetPort: 6379
+    selector:
+        app: immich
diff --git a/manifests/secrets.yaml b/manifests/secrets.yaml
new file mode 100644
index 0000000..146750f
--- /dev/null
+++ b/manifests/secrets.yaml
@@ -0,0 +1,24 @@
+apiVersion: argoproj.io/v1alpha1
+kind: Application
+metadata:
+  name: immich-secrets
+  namespace: argocd
+  finalizers:
+    - resources-finalizer.argocd.argoproj.io
+spec:
+  project: default
+  source:
+    repoURL: https://git.halis.io/athens-school/k3s-secrets
+    targetRevision: prod-migration
+    path: immich
+  syncPolicy:
+    automated:
+      prune: true
+      selfHeal: true
+    syncOptions:
+      - CreateNamespace=false
+      - ApplyOutOfSyncOnly=true
+      - PruneLast=true
+  destination:
+    server: https://kubernetes.default.svc
+    namespace: immich
diff --git a/manifests/service.yaml b/manifests/service.yaml
new file mode 100644
index 0000000..0c57900
--- /dev/null
+++ b/manifests/service.yaml
@@ -0,0 +1,19 @@
+apiVersion: v1
+kind: Service
+metadata:
+    name: immich-svc
+    namespace: immich
+    labels:
+      app.kubernetes.io/name: immich
+spec:
+    ports:
+        - name: http
+          port: 80
+          protocol: TCP
+          targetPort: 2283
+        - name: ml
+          port: 3003
+          protocol: TCP
+          targetPort: 3003
+    selector:
+        app: immich
diff --git a/manifests/servicemonitor.yaml b/manifests/servicemonitor.yaml
new file mode 100644
index 0000000..199c504
--- /dev/null
+++ b/manifests/servicemonitor.yaml
@@ -0,0 +1,14 @@
+apiVersion: monitoring.coreos.com/v1
+kind: ServiceMonitor
+metadata:
+  name: immich
+  namespace: immich
+  labels:
+    team: core
+spec:
+  selector:
+    matchLabels:
+      app.kubernetes.io/name: immich
+  endpoints:
+    - port: metrics
+      path: /metrics