Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add immich #641

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -46,6 +46,7 @@ If you have a spare domain name you can configure applications to be accessible
* [Heimdall](https://heimdall.site/) - Home server dashboard
* [Home Assistant](https://www.home-assistant.io) - Open source home automation
* [Homebridge](https://github.com/nfarina/homebridge) - Emulate the iOS HomeKit API
* [Immich](https://immich.app/) - Self-hosted photo and video backup solution directly from your mobile phone.
* [Jackett](https://github.com/Jackett/Jackett) - API Support for your favorite torrent trackers
* [Jellyfin](https://jellyfin.github.io) - The Free Software Media System
* [Joomla](https://www.joomla.org/) - Open source content management system
4 changes: 4 additions & 0 deletions nas.yml
Original file line number Diff line number Diff line change
@@ -171,6 +171,10 @@
- homebridge
when: (homebridge_enabled | default(False))

- role: immich
tags:
- immich

- role: jackett
tags:
- jackett
56 changes: 56 additions & 0 deletions roles/immich/defaults/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
immich_enabled: false
immich_available_externally: false

# directories
immich_data_directory: "{{ docker_home }}/immich"
immich_upload_directory: "{{ docker_home }}/immich/upload"

# network
immich_port: "2283"
immich_hostname: "immich"
immich_network_name: "immich"

# specs
immich_postgres_memory: 1g
immich_redis_memory: 1g
immich_typesense_memory: 1g
immich_server_memory: 1g
immich_microservices_memory: 1g
immich_machinelearning_memory: 1g
immich_web_memory: 1g
immich_proxy_memory: 1g

# docker
immich_postgres_container_name: "immich_postgres"
immich_redis_container_name: "immich_redis"
immich_server_container_name: "immich_server"
immich_microservices_container_name: "immich_microservices"
immich_machinelearning_container_name: "immich_machine_learning"

immich_postgres_image: "tensorchord/pgvecto-rs"
immich_postgres_tag: "pg14-v0.2.0"
immich_redis_image: "redis"
immich_redis_tag: "6.2-alpine"
immich_server_image: "ghcr.io/immich-app/immich-server"
immich_server_tag: "{{ immich_version}}"

Check warning on line 36 in roles/immich/defaults/main.yml

GitHub Actions / Lint

jinja[spacing]

Jinja2 spacing could be improved: {{ immich_version}} -> {{ immich_version }}
immich_microservices_image: "ghcr.io/immich-app/immich-server"
immich_microservices_tag: "{{ immich_version}}"

Check warning on line 38 in roles/immich/defaults/main.yml

GitHub Actions / Lint

jinja[spacing]

Jinja2 spacing could be improved: {{ immich_version}} -> {{ immich_version }}
immich_machinelearning_image: "ghcr.io/immich-app/immich-machine-learning"
immich_machinelearning_tag: "{{ immich_version}}"

Check warning on line 40 in roles/immich/defaults/main.yml

GitHub Actions / Lint

jinja[spacing]

Jinja2 spacing could be improved: {{ immich_version}} -> {{ immich_version }}
immich_user_id: "1000"
immich_group_id: "1000"

# database
immich_db_password: "postgres" # $(pwgen -s 40 1)
immich_db_username: "postgres"
immich_db_name: "immich"
immich_db_port: "5432"

# immich
immich_version: "release"
immich_jwt_secret: "verylongandsecrettext"
immich_enable_mapbox: "false"
immich_mapbox_key: ""
immich_upload_location: "./library"
immich_public_login_page_message: "Welcome to Immich!"
15 changes: 15 additions & 0 deletions roles/immich/docs/immich.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Immich

Homepage: [https://immich.app/](https://immich.app/)

Self-hosted photo and video backup solution directly from your mobile phone.

## Usage

Set `immich_enabled: true` in your `inventories/<your_inventory>/nas.yml` file.

Set all `immich_*` variables in `inventories/<your_inventory>/group_vars/all.yml`.

The immich web interface can be found at [http://ansible_nas_host_or_ip:2283](http://ansible_nas_host_or_ip:2283).

Refer to [https://immich.app/docs/install/post-install](https://immich.app/docs/install/post-install) for post-install steps (Registering Admin User, adding users, etc.).
6 changes: 6 additions & 0 deletions roles/immich/molecule/default/molecule.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
provisioner:
inventory:
group_vars:
all:
immich_enabled: true
10 changes: 10 additions & 0 deletions roles/immich/molecule/default/side_effect.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
- name: Stop
hosts: all
become: true
tasks:
- name: "Include {{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }} role"
ansible.builtin.include_role:
name: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}"
vars:
immich_enabled: false
47 changes: 47 additions & 0 deletions roles/immich/molecule/default/verify.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
- name: Verify
hosts: all
gather_facts: false
tasks:
- name: Include vars
ansible.builtin.include_vars:
file: ../../defaults/main.yml

- name: Get Immich Postgres container state
community.docker.docker_container_info:
name: "{{ immich_postgres_container_name }}"
register: result_postgres

- name: Get Immich Redis container state
community.docker.docker_container_info:
name: "{{ immich_redis_container_name }}"
register: result_redis

- name: Get Immich Server container state
community.docker.docker_container_info:
name: "{{ immich_server_container_name }}"
register: result_server

- name: Get Immich Microservies container state
community.docker.docker_container_info:
name: "{{ immich_microservices_container_name }}"
register: result_microservices

- name: Get Immich Machine Learning container state
community.docker.docker_container_info:
name: "{{ immich_machinelearning_container_name }}"
register: result_machinelearning

- name: Check if Immich docker containers are running
ansible.builtin.assert:
that:
- result_postgres.container['State']['Status'] == "running"
- result_postgres.container['State']['Restarting'] == false
- result_redis.container['State']['Status'] == "running"
- result_redis.container['State']['Restarting'] == false
- result_server.container['State']['Status'] == "running"
- result_server.container['State']['Restarting'] == false
- result_microservices.container['State']['Status'] == "running"
- result_microservices.container['State']['Restarting'] == false
- result_machinelearning.container['State']['Status'] == "running"
- result_machinelearning.container['State']['Restarting'] == false
47 changes: 47 additions & 0 deletions roles/immich/molecule/default/verify_stopped.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
- name: Verify
hosts: all
gather_facts: false
tasks:
- name: Include vars
ansible.builtin.include_vars:
file: ../../defaults/main.yml

- name: Try and stop and remove Immich Postgres
community.docker.docker_container:
name: "{{ immich_postgres_container_name }}"
state: absent
register: result_postgres

- name: Try and stop and remove Immich Redis
community.docker.docker_container:
name: "{{ immich_redis_container_name }}"
state: absent
register: result_redis

- name: Try and stop and remove Immich Server
community.docker.docker_container:
name: "{{ immich_server_container_name }}"
state: absent
register: result_server

- name: Try and stop and remove Immich Microservices
community.docker.docker_container:
name: "{{ immich_microservices_container_name }}"
state: absent
register: result_microservices

- name: Try and stop and remove Immich Machine Learning
community.docker.docker_container:
name: "{{ immich_machinelearning_container_name }}"
state: absent
register: result_machinelearning

- name: Check if immich containers are stopped
ansible.builtin.assert:
that:
- not result_postgres.changed
- not result_redis.changed
- not result_server.changed
- not result_microservices.changed
- not result_machinelearning.changed
204 changes: 204 additions & 0 deletions roles/immich/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
---
- name: Start Immich
block:
- name: Create Immich Directory
ansible.builtin.file:
path: "{{ item }}"
state: directory
with_items:
- "{{ immich_data_directory }}"
- "{{ immich_upload_directory }}"

- name: Create Immich network
community.docker.docker_network:
name: "{{ immich_network_name }}"

- name: Immich Postgress Docker Container
community.docker.docker_container:
name: "{{ immich_postgres_container_name }}"
image: "{{ immich_postgres_image }}:{{ immich_postgres_tag }}"
pull: true
volumes:
- "{{ immich_data_directory }}/database:/var/lib/postgresql/data:rw"
networks:
- name: "{{ immich_network_name }}"
network_mode: "{{ immich_network_name }}"
container_default_behavior: no_defaults
env:
POSTGRES_PASSWORD: "{{ immich_db_password }}"
POSTGRES_USER: "{{ immich_db_username }}"
POSTGRES_DB: "{{ immich_db_name }}"
PG_DATA: /var/lib/postgresql/data
labels:
traefik.enable: "false"
restart_policy: always
memory: "{{ immich_postgres_memory }}"
healthcheck:
test: ["CMD-SHELL", "pg_isready -d {{ immich_db_name }} -U {{ immich_db_username }}"]
start_period: 20s
interval: 30s
retries: 5
timeout: 5s

- name: Immich Redis Docker Container
community.docker.docker_container:
name: "{{ immich_redis_container_name }}"
image: "{{ immich_redis_image }}:{{ immich_redis_tag }}"
pull: true
command: --save 60 1 --loglevel warning
volumes:
- "{{ immich_data_directory }}/redis:/data:rw"
networks:
- name: "{{ immich_network_name }}"
labels:
traefik.enable: "false"
restart_policy: always
memory: "{{ immich_redis_memory }}"
healthcheck:
test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
start_period: 20s
interval: 30s
retries: 5
timeout: 3s

- name: Immich Server Docker Container
community.docker.docker_container:
name: "{{ immich_server_container_name }}"
image: "{{ immich_server_image }}:{{ immich_server_tag }}"
pull: true
command: ["start.sh", "immich"]
volumes:
- "{{ immich_data_directory }}/data:/data:rw"
- "{{ immich_upload_directory }}:/usr/src/app/upload:rw"
- /etc/localtime:/etc/localtime:ro
networks:
- name: "{{ immich_network_name }}"
ports:
- "{{ immich_port }}:3001"
env:
TZ: "{{ ansible_nas_timezone }}"
PUID: "{{ immich_user_id | quote }}"
PGID: "{{ immich_group_id | quote }}"
NODE_ENV: "production"
IMMICH_VERSION: "{{ immich_version }}"
REDIS_HOSTNAME: "{{ immich_redis_container_name }}"
DB_HOSTNAME: "{{ immich_postgres_container_name }}"
DB_USERNAME: "{{ immich_db_username }}"
DB_PASSWORD: "{{ immich_db_password }}"
DB_DATABASE_NAME: "{{ immich_db_name }}"
DB_PORT: "{{ immich_db_port }}"
JWT_SECRET: "{{ immich_jwt_secret }}"
ENABLE_MAPBOX: "{{ immich_enable_mapbox }}"
MAPBOX_KEY: "{{ immich_mapbox_key }}"
UPLOAD_LOCATION: "{{ immich_upload_location }}"
PUBLIC_LOGIN_PAGE_MESSAGE: "{{ immich_public_login_page_message }}"
labels:
traefik.enable: "{{ immich_available_externally | string }}"
traefik.http.routers.immich.rule: "Host(`{{ immich_hostname }}.{{ ansible_nas_domain }}`)"
traefik.http.routers.immich.tls.certresolver: "letsencrypt"
traefik.http.routers.immich.tls.domains[0].main: "{{ ansible_nas_domain }}"
traefik.http.routers.immich.tls.domains[0].sans: "*.{{ ansible_nas_domain }}"
traefik.http.services.immich.loadbalancer.server.port: "3001"
restart_policy: unless-stopped
memory: "{{ immich_server_memory }}"

- name: Immich Microservices Docker Container
community.docker.docker_container:
name: "{{ immich_microservices_container_name }}"
image: "{{ immich_microservices_image }}:{{ immich_microservices_tag }}"
pull: true
command: ["start.sh", "microservices"]
volumes:
- "{{ immich_data_directory }}/data:/data:rw"
- "{{ immich_upload_directory }}:/usr/src/app/upload:rw"
- /etc/localtime:/etc/localtime:ro
networks:
- name: "{{ immich_network_name }}"
env:
TZ: "{{ ansible_nas_timezone }}"
PUID: "{{ immich_user_id | quote }}"
PGID: "{{ immich_group_id | quote }}"
NODE_ENV: "production"
IMMICH_VERSION: "{{ immich_version }}"
REDIS_HOSTNAME: "{{ immich_redis_container_name }}"
DB_HOSTNAME: "{{ immich_postgres_container_name }}"
DB_USERNAME: "{{ immich_db_username }}"
DB_PASSWORD: "{{ immich_db_password }}"
DB_DATABASE_NAME: "{{ immich_db_name }}"
DB_PORT: "{{ immich_db_port }}"
JWT_SECRET: "{{ immich_jwt_secret }}"
ENABLE_MAPBOX: "{{ immich_enable_mapbox }}"
MAPBOX_KEY: "{{ immich_mapbox_key }}"
UPLOAD_LOCATION: "{{ immich_upload_location }}"
PUBLIC_LOGIN_PAGE_MESSAGE: "{{ immich_public_login_page_message }}"
labels:
traefik.enable: "false"
restart_policy: unless-stopped
memory: "{{ immich_microservices_memory }}"

- name: Immich Machine Learning Docker Container
community.docker.docker_container:
name: "{{ immich_machinelearning_container_name }}"
image: "{{ immich_machinelearning_image }}:{{ immich_machinelearning_tag }}"
pull: true
volumes:
- "{{ immich_data_directory }}/data:/data:rw"
- "{{ immich_upload_directory }}:/usr/src/app/upload:rw"
- "model-cache:/cache"
networks:
- name: "{{ immich_network_name }}"
env:
TZ: "{{ ansible_nas_timezone }}"
PUID: "{{ immich_user_id | quote }}"
PGID: "{{ immich_group_id | quote }}"
NODE_ENV: "production"
IMMICH_VERSION: "{{ immich_version }}"
REDIS_HOSTNAME: "{{ immich_redis_container_name }}"
DB_HOSTNAME: "{{ immich_postgres_container_name }}"
DB_USERNAME: "{{ immich_db_username }}"
DB_PASSWORD: "{{ immich_db_password }}"
DB_DATABASE_NAME: "{{ immich_db_name }}"
DB_PORT: "{{ immich_db_port }}"
JWT_SECRET: "{{ immich_jwt_secret }}"
ENABLE_MAPBOX: "{{ immich_enable_mapbox }}"
MAPBOX_KEY: "{{ immich_mapbox_key }}"
UPLOAD_LOCATION: "{{ immich_upload_location }}"
PUBLIC_LOGIN_PAGE_MESSAGE: "{{ immich_public_login_page_message }}"
labels:
traefik.enable: "false"
restart_policy: unless-stopped
memory: "{{ immich_machinelearning_memory }}"
when: immich_enabled is true

- name: Stop Immich
block:
- name: Stop Immich Postgres
community.docker.docker_container:
name: "{{ immich_postgres_container_name }}"
state: absent

- name: Stop Immich Redis
community.docker.docker_container:
name: "{{ immich_redis_container_name }}"
state: absent

- name: Stop Immich Server
community.docker.docker_container:
name: "{{ immich_server_container_name }}"
state: absent

- name: Stop Immich Microservices
community.docker.docker_container:
name: "{{ immich_microservices_container_name }}"
state: absent

- name: Stop Immich Machine Learning
community.docker.docker_container:
name: "{{ immich_machinelearning_container_name }}"
state: absent

- name: Delete Immich Network
community.docker.docker_network:
name: "{{ immich_network_name }}"
state: absent
when: immich_enabled is false
17 changes: 17 additions & 0 deletions website/docs/applications/other/immich.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
title: "Immich"
---

Homepage: [https://immich.app/](https://immich.app/)

Self-hosted photo and video backup solution directly from your mobile phone.

## Usage

Set `immich_enabled: true` in your `inventories/<your_inventory>/nas.yml` file.

Set all `immich_*` variables in `inventories/<your_inventory>/group_vars/all.yml`.

The immich web interface can be found at [http://ansible_nas_host_or_ip:2283](http://ansible_nas_host_or_ip:2283).

Refer to [https://immich.app/docs/install/post-install](https://immich.app/docs/install/post-install) for post-install steps (Registering Admin User, adding users, etc.).