1.4.0 Release immich
This commit is contained in:
@@ -76,3 +76,4 @@ version:
|
||||
vaultwarden: "1.35.4"
|
||||
gitea: "1.25.5"
|
||||
redis: "8.6.1"
|
||||
immich: "v2.6.1"
|
||||
|
||||
@@ -39,3 +39,6 @@ storage:
|
||||
label: "APP_DATA"
|
||||
level: "raid10"
|
||||
mount_point: "/home/app/data"
|
||||
|
||||
redis:
|
||||
immich: "6379"
|
||||
|
||||
@@ -177,6 +177,14 @@
|
||||
tags: ["site", "gitea"]
|
||||
tags: ["site", "gitea"]
|
||||
|
||||
- name: Set immich
|
||||
ansible.builtin.include_role:
|
||||
name: "app"
|
||||
tasks_from: "services/set_immich"
|
||||
apply:
|
||||
tags: ["site", "immich"]
|
||||
tags: ["site", "immich"]
|
||||
|
||||
- name: Flush handlers right now
|
||||
ansible.builtin.meta: "flush_handlers"
|
||||
|
||||
|
||||
@@ -20,3 +20,25 @@
|
||||
changed_when: false
|
||||
listen: "notification_restart_gitea"
|
||||
ignore_errors: true # noqa: ignore-errors
|
||||
|
||||
- name: Restart immich
|
||||
ansible.builtin.systemd:
|
||||
name: "immich.service"
|
||||
state: "restarted"
|
||||
enabled: true
|
||||
scope: "user"
|
||||
daemon_reload: true
|
||||
changed_when: false
|
||||
listen: "notification_restart_immich"
|
||||
ignore_errors: true # noqa: ignore-errors
|
||||
|
||||
- name: Restart immich-ml
|
||||
ansible.builtin.systemd:
|
||||
name: "immich-ml.service"
|
||||
state: "restarted"
|
||||
enabled: true
|
||||
scope: "user"
|
||||
daemon_reload: true
|
||||
changed_when: false
|
||||
listen: "notification_restart_immich-ml"
|
||||
ignore_errors: true # noqa: ignore-errors
|
||||
|
||||
120
ansible/roles/app/tasks/services/set_immich.yaml
Normal file
120
ansible/roles/app/tasks/services/set_immich.yaml
Normal file
@@ -0,0 +1,120 @@
|
||||
---
|
||||
- name: Set redis service name
|
||||
ansible.builtin.set_fact:
|
||||
redis_service: "immich"
|
||||
redis_subuid: "100998"
|
||||
|
||||
- name: Create redis_immich directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ node['home_path'] }}/{{ item }}"
|
||||
state: "directory"
|
||||
owner: "{{ redis_subuid }}"
|
||||
group: "svadmins"
|
||||
mode: "0770"
|
||||
loop:
|
||||
- "containers/redis"
|
||||
- "containers/redis/{{ redis_service }}"
|
||||
- "containers/redis/{{ redis_service }}/data"
|
||||
become: true
|
||||
|
||||
- name: Deploy redis config file
|
||||
ansible.builtin.template:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/redis/redis.conf.j2"
|
||||
dest: "{{ node['home_path'] }}/containers/redis/{{ redis_service }}/redis.conf"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "svadmins"
|
||||
mode: "0644"
|
||||
|
||||
- name: Deploy redis container file
|
||||
ansible.builtin.template:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/redis/redis.container.j2"
|
||||
dest: "{{ node['home_path'] }}/.config/containers/systemd/redis_{{ redis_service }}.container"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "svadmins"
|
||||
mode: "0644"
|
||||
register: "is_redis_conf"
|
||||
|
||||
- name: Enable (Restart) redis service
|
||||
ansible.builtin.systemd:
|
||||
name: "redis_{{ redis_service }}.service"
|
||||
state: "restarted"
|
||||
enabled: true
|
||||
daemon_reload: true
|
||||
scope: "user"
|
||||
when: is_redis_conf.changed # noqa: no-handler
|
||||
|
||||
- name: Add user in video, render group
|
||||
ansible.builtin.user:
|
||||
name: "{{ ansible_user }}"
|
||||
state: "present"
|
||||
groups: "video, render"
|
||||
append: true
|
||||
become: true
|
||||
|
||||
- name: Create immich directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ node['home_path'] }}/{{ item }}"
|
||||
state: "directory"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "svadmins"
|
||||
mode: "0770"
|
||||
loop:
|
||||
- "data/containers/immich"
|
||||
- "containers/immich"
|
||||
- "containers/immich/ssl"
|
||||
- "containers/immich/ml"
|
||||
- "containers/immich/ml/cache"
|
||||
|
||||
- name: Deploy root certificate
|
||||
ansible.builtin.copy:
|
||||
content: |
|
||||
{{ hostvars['console']['ca']['root']['crt'] }}
|
||||
dest: "{{ node['home_path'] }}/containers/immich/ssl/ilnmors_root_ca.crt"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "svadmins"
|
||||
mode: "0440"
|
||||
notify: "notification_restart_immich"
|
||||
no_log: true
|
||||
|
||||
- name: Register secret value to podman secret
|
||||
containers.podman.podman_secret:
|
||||
name: "IMMICH_DB_PASSWORD"
|
||||
data: "{{ hostvars['console']['postgresql']['password']['immich'] }}"
|
||||
state: "present"
|
||||
force: true
|
||||
notify: "notification_restart_immich"
|
||||
no_log: true
|
||||
|
||||
- name: Deploy immich.container file
|
||||
ansible.builtin.template:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/immich/immich.container.j2"
|
||||
dest: "{{ node['home_path'] }}/.config/containers/systemd/immich.container"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "svadmins"
|
||||
mode: "0644"
|
||||
notify: "notification_restart_immich"
|
||||
|
||||
- name: Deploy immich-ml.container file
|
||||
ansible.builtin.template:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/immich/immich-ml.container.j2"
|
||||
dest: "{{ node['home_path'] }}/.config/containers/systemd/immich-ml.container"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "svadmins"
|
||||
mode: "0644"
|
||||
notify: "notification_restart_immich-ml"
|
||||
|
||||
- name: Enable immich.service
|
||||
ansible.builtin.systemd:
|
||||
name: "immich.service"
|
||||
state: "started"
|
||||
enabled: true
|
||||
daemon_reload: true
|
||||
scope: "user"
|
||||
|
||||
- name: Enable immich-ml.service
|
||||
ansible.builtin.systemd:
|
||||
name: "immich-ml.service"
|
||||
state: "started"
|
||||
enabled: true
|
||||
daemon_reload: true
|
||||
scope: "user"
|
||||
@@ -11,6 +11,7 @@
|
||||
- "grafana"
|
||||
- "vaultwarden"
|
||||
- "gitea"
|
||||
- "immich"
|
||||
|
||||
- name: Create postgresql directory
|
||||
ansible.builtin.file:
|
||||
@@ -108,7 +109,7 @@
|
||||
group: "svadmins"
|
||||
mode: "0600"
|
||||
|
||||
- name: Deploy resoring data sql files
|
||||
- name: Deploy restoring data sql files
|
||||
ansible.builtin.copy:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/postgresql/init/pg_{{ item }}.sql"
|
||||
dest: "{{ node['home_path'] }}/containers/postgresql/init/{{ index_num + 1 }}_pg_{{ item }}.sql"
|
||||
|
||||
@@ -115,6 +115,7 @@ postgresql:
|
||||
authelia: ENC[AES256_GCM,data:OqyloAADO6KKEaBjGLsJc9GTe77wn6IvA1VCD2dfCWxx+zgzUYh87fK1XX8=,iv:QIOHNTdNnzcY/f3Co8dPdNHykhBnYRhm43nt35hbALM=,tag:DLQq58GrZd+Ul7MSn6s9uQ==,type:str]
|
||||
vaultwarden: ENC[AES256_GCM,data:BPj5eFo54DTZ82n3yTIqEbm7kb/jWT0n2kZY//oV5q48eRch3C2RBuxn/Ko=,iv:DGC4ipHMyVs25gc4sNMt8LN1RsHjiR/b303vgiFoxMY=,tag:k1eb4DoRPLKvvMstSI1faQ==,type:str]
|
||||
gitea: ENC[AES256_GCM,data:l+pBCzyQa3000SE9z1R4htD0V0ONsBtKy92dfgsVYsZ3XlEyVJDIBOsugwM=,iv:5t/oHW1vFAmV/s2Ze/cV9Vuqo96Qu6QvZeRbio7VX2s=,tag:4zeQaXiXIzBpy+tXsxmN7Q==,type:str]
|
||||
immich: ENC[AES256_GCM,data:11jvxTKA/RL0DGL6y2/X092hnDohj6yTrYGK4IVojqBd1gCOBnDvUjgmx14=,iv:oBfHxsx9nxhyKY/WOuWfybxEX2bf+lHEtsaifFRS9lg=,tag:tAfkBdgQ8ZEkLIFcDICKDw==,type:str]
|
||||
#ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment]
|
||||
#
|
||||
#
|
||||
@@ -195,6 +196,16 @@ gitea:
|
||||
#ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment]
|
||||
#
|
||||
#
|
||||
#ENC[AES256_GCM,data:HvMeGuC8JwK50pO1E/nm,iv:5NFTyjesMX0ZnBpH+hEv8jQ0G2NvrDtT23CUyLbQcUo=,tag:qWmPvQpADTeD+W8nWXRQvA==,type:comment]
|
||||
immich:
|
||||
il:
|
||||
password: ENC[AES256_GCM,data:PbDFc4m7rNPPN1mCjcvhbKwf/EbiJxdvO/iMspf9jMuCqQyGv7h6VrZqk98=,iv:hlMAp5wXXkFO9+ekq3A2/ioF/EX8Uau0puhb4TAHkRQ=,tag:pfS0W2JNaFNMpBlKgZ3Pjw==,type:str]
|
||||
oidc:
|
||||
secret: ENC[AES256_GCM,data:9ENcp2Ns21OLXDY05zRoSdP+93EiwSH8MGzZZpxK7sToe4QLUXWt9w6xQIE=,iv:Q/VcnArZHs/J2YLRVFXt3Mp+LYfuq4PD/trqO8Simig=,tag:BY/mOyZpYmoAc7NrASlmSA==,type:str]
|
||||
hash: ENC[AES256_GCM,data:mrML2CWFFtGjq8wfWipVpv+pjJRSHe74VGC7Eoa6588R5C/sCnC3W5aI+dsRCZN3LRCjHAkOJJgjeYrwcXYdKRauXsAYR51dNSsHqqSN3WebLxapRDwcYu5e4j5RN1aPHsysr7GaQ4hhe5rKW4ORCGC3Cp3Ob+LChPy4bdCAZG3bN9k=,iv:Q4hmqhq+dvIr7DxCpcqP4E0NKyFZkOeTnDpGctmCxXM=,tag:/gji6AFkHnYwkQf3FSQUxA==,type:str]
|
||||
#ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment]
|
||||
#
|
||||
#
|
||||
#ENC[AES256_GCM,data:T4Wtn49AAxPd2QUFTR+q,iv:bH5goGWBDqumAat9dUv2OwfCUJUpuVqncTMqMBZUXhI=,tag:G+W6hHA+yftQ+4RJpXrxHg==,type:comment]
|
||||
switch:
|
||||
password: ENC[AES256_GCM,data:qu0f9L7A0eFq/UCpaRs=,iv:W8LLOp3MSfd/+EfNEZNf91K8GgI5eUfVPoWTRES2C0Y=,tag:Q5FlAOfwqwJwPvd7k6i+0g==,type:str]
|
||||
@@ -224,7 +235,7 @@ sops:
|
||||
UmliaFNxVTBqRkI1QWJpWGpTRWxETW8KEY/8AfU73UOzCGhny1cNnd5dCNv7bHXt
|
||||
k+uyWPPi+enFkVaceSwMFrA66uaWWrwAj11sXEB7yzvGFPrnAGezjQ==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2026-03-14T21:11:56Z"
|
||||
mac: ENC[AES256_GCM,data:cTm/Vrukt1cnq5xWmfF7J3xhDrVH94ampOK1IqZgsBICuJgDm6VYbntElCcnrmPE4BrIAFr8SyDQa28QgLf+e2UBn36yVUNZTor1kx24WkMsjj4MIRJRlYSQoFAg1iJSGTshqiwgQQMfj1nOCctLXdNAyQFWHt+E+9zqeXFB/l8=,iv:/dDIeqEW8/T5V8glumE3cTTy9e3bFAvg3GaMHAYkFi0=,tag:7eUKYIkju8wniz+/xmGfgg==,type:str]
|
||||
lastmodified: "2026-03-21T00:50:58Z"
|
||||
mac: ENC[AES256_GCM,data:xLYH+20TGYk0piWG7OaJqysuEc2xlqpKZcvCIKj9xOIgQIXVS8l5YXXAv6c4uen2cNe/0DIWs04Cb6cdItRWWq46jV3F6+u1BOy7mSmQ40nmbKCy+qls8TaYBeqhlrffpy5yYolDdztYqBjZYQDjY6rNXUIp7UU1VJEZkpY96lI=,iv:EZUezHsy6pghcWa/rq5CObaw3CRW7JJB5zdmCp6mIAA=,tag:JJVI0EDuA90uafbLwdn4ww==,type:str]
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.12.1
|
||||
|
||||
32
config/services/containers/app/immich/immich-ml.container.j2
Normal file
32
config/services/containers/app/immich/immich-ml.container.j2
Normal file
@@ -0,0 +1,32 @@
|
||||
[Quadlet]
|
||||
DefaultDependencies=false
|
||||
|
||||
[Unit]
|
||||
Description=Immich Machine Learning
|
||||
|
||||
After=immich.service
|
||||
Wants=immich.service
|
||||
|
||||
[Container]
|
||||
Image=ghcr.io/immich-app/immich-machine-learning:{{ version['containers']['immich'] }}-openvino
|
||||
|
||||
ContainerName=immich-ml
|
||||
HostName=immich-ml
|
||||
|
||||
PublishPort=3003:3003
|
||||
|
||||
# iGPU access for OpenVINO
|
||||
AddDevice=/dev/dri:/dev/dri
|
||||
PodmanArgs=--group-add keep-groups
|
||||
|
||||
Volume=%h/containers/immich/ml/cache:/cache:rw
|
||||
|
||||
Environment="TZ=Asia/Seoul"
|
||||
|
||||
[Service]
|
||||
Restart=always
|
||||
RestartSec=10s
|
||||
TimeoutStopSec=120
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
49
config/services/containers/app/immich/immich.container.j2
Normal file
49
config/services/containers/app/immich/immich.container.j2
Normal file
@@ -0,0 +1,49 @@
|
||||
[Quadlet]
|
||||
DefaultDependencies=false
|
||||
|
||||
[Unit]
|
||||
Description=Immich
|
||||
|
||||
After=redis_immich.service
|
||||
Wants=redis_immich.service
|
||||
|
||||
[Container]
|
||||
Image=ghcr.io/immich-app/immich-server:{{ version['containers']['immich'] }}
|
||||
|
||||
ContainerName=immich
|
||||
HostName=immich
|
||||
|
||||
PublishPort=2283:2283
|
||||
|
||||
# iGPU access
|
||||
AddDevice=/dev/dri:/dev/dri
|
||||
PodmanArgs=--group-add keep-groups
|
||||
|
||||
# Volumes
|
||||
Volume=%h/data/containers/immich:/data:rw
|
||||
Volume=%h/containers/immich/ssl:/etc/ssl/immich:ro
|
||||
|
||||
# Environment
|
||||
Environment="TZ=Asia/Seoul"
|
||||
Environment="REDIS_HOSTNAME=host.containers.internal"
|
||||
Environment="REDIS_PORT={{ hostvars['app']['redis']['immich'] }}"
|
||||
Environment="REDIS_DBINDEX=0"
|
||||
|
||||
# Database
|
||||
Environment="DB_HOSTNAME={{ infra_uri['postgresql']['domain'] }}"
|
||||
Environment="DB_PORT={{ infra_uri['postgresql']['ports']['tcp'] }}"
|
||||
Environment="DB_USERNAME=immich"
|
||||
Environment="DB_DATABASE_NAME=immich_db"
|
||||
Environment="DB_PASSWORD_FILE=/run/secrets/DB_PASSWORD"
|
||||
Environment="DB_SSL_MODE=verify-full"
|
||||
Environment="NODE_EXTRA_CA_CERTS=/etc/ssl/immich/ilnmors_root_ca.crt"
|
||||
Secret=IMMICH_DB_PASSWORD,target=/run/secrets/DB_PASSWORD
|
||||
|
||||
[Service]
|
||||
ExecStartPre=/usr/bin/nc -zv {{ infra_uri['postgresql']['domain'] }} {{ infra_uri['postgresql']['ports']['tcp'] }}
|
||||
Restart=always
|
||||
RestartSec=10s
|
||||
TimeoutStopSec=120
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
@@ -152,3 +152,26 @@ identity_providers:
|
||||
access_token_signed_response_alg: 'none'
|
||||
userinfo_signed_response_alg: 'none'
|
||||
token_endpoint_auth_method: 'client_secret_basic'
|
||||
# https://www.authelia.com/integration/openid-connect/clients/immich/
|
||||
- client_id: 'immich'
|
||||
client_name: 'immich'
|
||||
client_secret: '{{ hostvars['console']['immich']['oidc']['hash'] }}'
|
||||
public: false
|
||||
authorization_policy: 'one_factor'
|
||||
require_pkce: false
|
||||
pkce_challenge_method: ''
|
||||
redirect_uris:
|
||||
- 'https://immich.ilnmors.com/auth/login'
|
||||
- 'https://immich.ilnmors.com/user-settings'
|
||||
- 'app.immich:///oauth-callback'
|
||||
scopes:
|
||||
- 'openid'
|
||||
- 'profile'
|
||||
- 'email'
|
||||
response_types:
|
||||
- 'code'
|
||||
grant_types:
|
||||
- 'authorization_code'
|
||||
access_token_signed_response_alg: 'none'
|
||||
userinfo_signed_response_alg: 'none'
|
||||
token_endpoint_auth_method: 'client_secret_post'
|
||||
|
||||
@@ -40,3 +40,9 @@ gitea.app.ilnmors.internal {
|
||||
header_up Host {http.request.header.X-Forwarded-Host}
|
||||
}
|
||||
}
|
||||
immich.app.ilnmors.internal {
|
||||
import private_tls
|
||||
reverse_proxy host.containers.internal:2283 {
|
||||
header_up Host {http.request.header.X-Forwarded-Host}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,6 +81,15 @@ gitea.ilnmors.com {
|
||||
}
|
||||
}
|
||||
}
|
||||
immich.ilnmors.com {
|
||||
import crowdsec_log
|
||||
route {
|
||||
crowdsec
|
||||
reverse_proxy https://immich.app.ilnmors.internal {
|
||||
header_up Host {http.reverse_proxy.upstream.host}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Internal domain
|
||||
auth.ilnmors.internal {
|
||||
|
||||
86
docs/services/app/immich.md
Normal file
86
docs/services/app/immich.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# immich
|
||||
|
||||
## Prerequisite
|
||||
|
||||
### Create database
|
||||
|
||||
- Create the password with `openssl rand -base64 32`
|
||||
- Save this value in secrets.yaml in `postgresql.password.immich`
|
||||
- Access infra server to create immich_db with `podman exec -it postgresql psql -U postgres`
|
||||
|
||||
```SQL
|
||||
CREATE USER immich WITH PASSWORD 'postgresql.password.immich';
|
||||
CREATE DATABASE immich_db;
|
||||
ALTER DATABASE immich_db OWNER TO immich;
|
||||
\connect immich_db
|
||||
CREATE EXTENSION IF NOT EXISTS vchord CASCADE;
|
||||
CREATE EXTENSION IF NOT EXISTS cube CASCADE;
|
||||
CREATE EXTENSION IF NOT EXISTS earthdistance CASCADE;
|
||||
\dx
|
||||
-- Check the extension is activated with `\dx`
|
||||
-- postgresql image is built with `pgvector` and `vectorchord` already
|
||||
```
|
||||
|
||||
### Create oidc secret and hash
|
||||
|
||||
- Create the secret with `openssl rand -base64 32`
|
||||
- access to auth vm
|
||||
- `podman exec -it authelia sh`
|
||||
- `authelia crypto hash generate pbkdf2 --password 'immich.oidc.secret'`
|
||||
- Save this value in secrets.yaml in `immich.oidc.secret` and `immich.oidc.hash`
|
||||
|
||||
### Create admin password
|
||||
|
||||
- Create the secret with `openssl rand -base64 32`
|
||||
- Save this value in secrets.yaml in `immich.il.password`
|
||||
-
|
||||
### Add postgresql dump backup list
|
||||
|
||||
- [set_postgresql.yaml](../../../ansible/roles/infra/tasks/services/set_postgresql.yaml)
|
||||
|
||||
```yaml
|
||||
- name: Set connected services list
|
||||
ansible.builtin.set_fact:
|
||||
connected_services:
|
||||
- ...
|
||||
- "immich"
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Access to immich
|
||||
|
||||
- https://immich.ilnmors.com
|
||||
- Getting started
|
||||
- admin E-mail
|
||||
- admin password
|
||||
- admin name
|
||||
- Theme
|
||||
- language
|
||||
- Server privacy
|
||||
- map
|
||||
- version check
|
||||
- User privacy
|
||||
- google cast \(disable\)
|
||||
- Storage template
|
||||
- `{{y}}/{{MM}}/{{y}}{{MM}}{{dd}}_{{hh}}{{mm}}{{ss}}`
|
||||
- Backups
|
||||
- Mobile App
|
||||
- Done
|
||||
|
||||
### Oauth configuration
|
||||
|
||||
- Administartion: Authentication Settings: OAuth: Enable
|
||||
- Issuer URL: https://auth.example.com/.well-known/openid-configuration
|
||||
- Client ID: immich
|
||||
- Client Secret: immich.oidc.secret
|
||||
- Scope: openid profile email
|
||||
- Button Text: Login with Authelia
|
||||
- Auto Register: Enable if desired
|
||||
|
||||
### Machine learning configuration
|
||||
|
||||
- Administration: Machine Learning Settings: Enable
|
||||
- URL: http://host.containers.internal:3003
|
||||
- **!CAUTION!**
|
||||
- immich-ml should contain `-openvino` to use GPU for machine learning.
|
||||
Reference in New Issue
Block a user