Immich: Add Immich installer configuration
Change-Id: I88796e42d0b0b14d84b094d4a1c5213b43c56f2a
diff --git a/core/installer/app_repository.go b/core/installer/app_repository.go
index e0f97fc..cc3a35a 100644
--- a/core/installer/app_repository.go
+++ b/core/installer/app_repository.go
@@ -24,6 +24,7 @@
// "values-tmpl/coder.cue",
"values-tmpl/url-shortener.cue",
"values-tmpl/matrix.cue",
+ "values-tmpl/immich.cue",
"values-tmpl/vaultwarden.cue",
"values-tmpl/etherpad.cue",
// "values-tmpl/open-project.cue",
diff --git a/core/installer/values-tmpl/immich.cue b/core/installer/values-tmpl/immich.cue
new file mode 100644
index 0000000..6635d8b
--- /dev/null
+++ b/core/installer/values-tmpl/immich.cue
@@ -0,0 +1,343 @@
+import (
+ "encoding/yaml"
+ "encoding/json"
+)
+
+input: {
+ network: #Network @name(Network)
+ subdomain: string @name(Subdomain)
+ mapEnabled: bool | *false @name(Map)
+ storageSize: string | *"10Gi" @name(Storage Size)
+}
+
+_domain: "\(input.subdomain).\(input.network.domain)"
+url: "https://\(_domain)"
+
+name: "Immich"
+namespace: "app-immich"
+readme: "Self-hosted photo and video management solution"
+description: "Easily back up, organize, and manage your photos on your own server. Immich helps you browse, search and organize your photos and videos with ease, without sacrificing your privacy."
+icon: """
+<svg width='50px' height='50px' version="1.1" id="Flower" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ viewBox="0 0 792 792" style="enable-background:new 0 0 792 792;" xml:space="preserve">
+<style type="text/css">
+ .st0{fill:#FA2921;}
+ .st1{fill:#ED79B5;}
+ .st2{fill:#FFB400;}
+ .st3{fill:#1E83F7;}
+ .st4{fill:#18C249;}
+</style>
+<g id="Flower_00000077325900055813483940000000694823054982625702_">
+ <path class="st0" d="M375.48,267.63c38.64,34.21,69.78,70.87,89.82,105.42c34.42-61.56,57.42-134.71,57.71-181.3
+ c0-0.33,0-0.63,0-0.91c0-68.94-68.77-95.77-128.01-95.77s-128.01,26.83-128.01,95.77c0,0.94,0,2.2,0,3.72
+ C300.01,209.24,339.15,235.47,375.48,267.63z"/>
+ <path class="st1" d="M164.7,455.63c24.15-26.87,61.2-55.99,103.01-80.61c44.48-26.18,88.97-44.47,128.02-52.84
+ c-47.91-51.76-110.37-96.24-154.6-110.91c-0.31-0.1-0.6-0.19-0.86-0.28c-65.57-21.3-112.34,35.81-130.64,92.15
+ c-18.3,56.34-14.04,130.04,51.53,151.34C162.05,454.77,163.25,455.16,164.7,455.63z"/>
+ <path class="st2" d="M681.07,302.19c-18.3-56.34-65.07-113.45-130.64-92.15c-0.9,0.29-2.1,0.68-3.54,1.15
+ c-3.75,35.93-16.6,81.27-35.96,125.76c-20.59,47.32-45.84,88.27-72.51,118c69.18,13.72,145.86,12.98,190.26-1.14
+ c0.31-0.1,0.6-0.2,0.86-0.28C695.11,432.22,699.37,358.52,681.07,302.19z"/>
+ <path class="st3" d="M336.54,510.71c-11.15-50.39-14.8-98.36-10.7-138.08c-64.03,29.57-125.63,75.23-153.26,112.76
+ c-0.19,0.26-0.37,0.51-0.53,0.73c-40.52,55.78-0.66,117.91,47.27,152.72c47.92,34.82,119.33,53.54,159.86-2.24
+ c0.56-0.76,1.3-1.78,2.19-3.01C363.28,602.32,347.02,558.08,336.54,510.71z"/>
+ <path class="st4" d="M617.57,482.52c-35.33,7.54-82.42,9.33-130.72,4.66c-51.37-4.96-98.11-16.32-134.63-32.5
+ c8.33,70.03,32.73,142.73,59.88,180.6c0.19,0.26,0.37,0.51,0.53,0.73c40.52,55.78,111.93,37.06,159.86,2.24
+ c47.92-34.82,87.79-96.95,47.27-152.72C619.2,484.77,618.46,483.75,617.57,482.52z"/>
+</g>
+</svg>"""
+
+out: {
+ ingress: {
+ immich: {
+ auth: enabled: false
+ network: input.network
+ subdomain: input.subdomain
+ service: {
+ name: "immich-server"
+ port: _httpPort
+ }
+ }
+ }
+
+ // TODO(gio): configure busybox
+ images: {
+ immich: {
+ registry: "ghcr.io"
+ repository: "immich-app"
+ name: "immich-server"
+ tag: "v1.135.3"
+ pullPolicy: "IfNotPresent"
+ }
+ ml: {
+ registry: "ghcr.io"
+ repository: "immich-app"
+ name: "immich-machine-learning"
+ tag: "v1.135.3"
+ pullPolicy: "IfNotPresent"
+ }
+ }
+
+ charts: {
+ immich: {
+ kind: "GitRepository"
+ address: "https://code.v1.dodo.cloud/helm-charts"
+ branch: "main"
+ path: "charts/immich"
+ }
+ oauth2Client: {
+ kind: "GitRepository"
+ address: "https://code.v1.dodo.cloud/helm-charts"
+ branch: "main"
+ path: "charts/oauth2-client"
+ }
+ resourceRenderer: {
+ kind: "GitRepository"
+ address: "https://code.v1.dodo.cloud/helm-charts"
+ branch: "main"
+ path: "charts/resource-renderer"
+ }
+ }
+
+ volume: immich: size: input.storageSize
+
+ _httpPort: 2283
+ _oauth2ClientSecretName: "oauth2-client"
+
+ helm: {
+ "oauth2-client": {
+ chart: charts.oauth2Client
+ info: "Creating OAuth2 client"
+ // TODO(gio): remove once hydra maester is installed as part of dodo itself
+ dependsOn: [{
+ name: "auth"
+ namespace: "\(global.namespacePrefix)core-auth"
+ }]
+ values: {
+ name: "\(release.namespace)-immich"
+ secretName: _oauth2ClientSecretName
+ grantTypes: ["authorization_code"]
+ responseTypes: ["code"]
+ scope: "openid profile email groups"
+ redirectUris: [
+ "app.immich:///oauth-callback",
+ "https://\(_domain)/auth/login",
+ "https://\(_domain)/user-settings",
+ ]
+ tokenEndpointAuthMethod: "client_secret_post"
+ hydraAdmin: "http://hydra-admin.\(global.namespacePrefix)core-auth.svc.cluster.local"
+ }
+ }
+ "config-renderer": {
+ chart: charts.resourceRenderer
+ info: "Generating Immich configuration"
+ values: {
+ name: "config-renderer"
+ secretName: _oauth2ClientSecretName
+ resourceTemplate: yaml.Marshal({
+ apiVersion: "v1"
+ kind: "ConfigMap"
+ metadata: {
+ name: _immichConfigMapName
+ namespace: "\(release.namespace)"
+ }
+ data: {
+ "immich-config.json": json.Marshal({
+ {
+ "ffmpeg": {
+ "crf": 23
+ "threads": 0
+ "preset": "ultrafast"
+ "targetVideoCodec": "h264"
+ "acceptedVideoCodecs": ["h264"]
+ "targetAudioCodec": "aac"
+ "acceptedAudioCodecs": ["aac", "mp3", "libopus", "pcm_s16le"]
+ "acceptedContainers": ["mov", "ogg", "webm"]
+ "targetResolution": "720"
+ "maxBitrate": "0"
+ "bframes": -1
+ "refs": 0
+ "gopSize": 0
+ "temporalAQ": false
+ "cqMode": "auto"
+ "twoPass": false
+ "preferredHwDevice": "auto"
+ "transcode": "required"
+ "tonemap": "hable"
+ "accel": "disabled"
+ "accelDecode": false
+ }
+ "backup": {
+ "database": {
+ "enabled": true
+ "cronExpression": "0 02 * * *"
+ "keepLastAmount": 14
+ }
+ }
+ "job": {
+ "backgroundTask": {
+ "concurrency": 5
+ }
+ "smartSearch": {
+ "concurrency": 2
+ }
+ "metadataExtraction": {
+ "concurrency": 5
+ }
+ "faceDetection": {
+ "concurrency": 2
+ }
+ "search": {
+ "concurrency": 5
+ }
+ "sidecar": {
+ "concurrency": 5
+ }
+ "library": {
+ "concurrency": 5
+ }
+ "migration": {
+ "concurrency": 5
+ }
+ "thumbnailGeneration": {
+ "concurrency": 3
+ }
+ "videoConversion": {
+ "concurrency": 1
+ }
+ "notifications": {
+ "concurrency": 5
+ }
+ }
+ "logging": {
+ "enabled": true
+ "level": "log"
+ }
+ "machineLearning": {
+ "enabled": true
+ "urls": ["http://immich-machine-learning:3003"]
+ "clip": {
+ "enabled": true
+ "modelName": "ViT-B-32__openai"
+ }
+ "duplicateDetection": {
+ "enabled": true
+ "maxDistance": 0.01
+ }
+ "facialRecognition": {
+ "enabled": true
+ "modelName": "buffalo_l"
+ "minScore": 0.7
+ "maxDistance": 0.5
+ "minFaces": 3
+ }
+ }
+ "map": {
+ "enabled": input.mapEnabled
+ "lightStyle": "https://tiles.immich.cloud/v1/style/light.json"
+ "darkStyle": "https://tiles.immich.cloud/v1/style/dark.json"
+ }
+ "reverseGeocoding": {
+ "enabled": true
+ }
+ "metadata": {
+ "faces": {
+ "import": false
+ }
+ }
+ "oauth": {
+ "autoLaunch": true
+ "autoRegister": true
+ "buttonText": "Login with dodo"
+ "clientId": "{{ .client_id }}"
+ "clientSecret": "{{ .client_secret }}"
+ "defaultStorageQuota": null
+ "enabled": true
+ "issuerUrl": "https://hydra.\(networks.public.domain)"
+ "mobileOverrideEnabled": false
+ "mobileRedirectUri": ""
+ "scope": "openid email profile"
+ "signingAlgorithm": "RS256"
+ "profileSigningAlgorithm": "none"
+ "storageLabelClaim": "preferred_username"
+ "storageQuotaClaim": "immich_quota"
+ }
+ "passwordLogin": {
+ "enabled": false
+ }
+ "storageTemplate": {
+ "enabled": false
+ "hashVerificationEnabled": true
+ "template": "{{`{{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}}`}}"
+ }
+ "image": {
+ "thumbnail": {
+ "format": "webp"
+ "size": 250
+ "quality": 80
+ }
+ "preview": {
+ "format": "jpeg"
+ "size": 1440
+ "quality": 80
+ }
+ "colorspace": "p3"
+ "extractEmbedded": false
+ }
+ "newVersionCheck": {
+ "enabled": true
+ }
+ "trash": {
+ "enabled": true
+ "days": 30
+ }
+ "theme": {
+ "customCss": ""
+ }
+ "library": {
+ "scan": {
+ "enabled": true
+ "cronExpression": "0 0 * * *"
+ }
+ "watch": {
+ "enabled": false
+ }
+ }
+ "server": {
+ "externalDomain": "https://\(_domain)"
+ "loginPageMessage": ""
+ }
+ "notifications": {
+ "smtp": {
+ "enabled": false
+ "from": ""
+ "replyTo": ""
+ "transport": {
+ "ignoreCert": false
+ "host": ""
+ "port": 587
+ "username": ""
+ "password": ""
+ }
+ }
+ }
+ "user": {
+ "deleteDelay": 7
+ }
+ }})
+ }
+ })
+ }
+ }
+ immich: {
+ chart: charts.immich
+ info: "Installing Immich server"
+ values: {
+ image: tag: "v1.135.3"
+ immich: existingConfiguration: _immichConfigMapName
+ persistence: library: existingClaim: "immich"
+ }
+ }
+ }
+}
+
+_immichConfigMapName: "immich-config"