first version
This commit is contained in:
12
README.md
12
README.md
@@ -1,2 +1,12 @@
|
||||
# ansible-role-immich
|
||||
# PeerTube Ansible role
|
||||
|
||||
This is an [Ansible](https://www.ansible.com/) role which installs [Immich](https://immich.app/) to run as a [Docker](https://www.docker.com/) container wrapped in a systemd service.
|
||||
|
||||
This role *implicitly* depends on:
|
||||
|
||||
- [`com.devture.ansible.role.playbook_help`](https://github.com/devture/com.devture.ansible.role.playbook_help)
|
||||
- [`com.devture.ansible.role.systemd_docker_base`](https://github.com/devture/com.devture.ansible.role.systemd_docker_base)
|
||||
|
||||
Check [defaults/main.yml](defaults/main.yml) for the full list of supported options.
|
||||
|
||||
For an Ansible playbook which integrates this role and makes it easier to use, see the [mash-playbook](https://github.com/mother-of-all-self-hosting/mash-playbook).
|
||||
|
||||
90
defaults/main.yml
Normal file
90
defaults/main.yml
Normal file
@@ -0,0 +1,90 @@
|
||||
---
|
||||
|
||||
# Project source code URL: https://github.com/imagegenius/docker-immich
|
||||
|
||||
immich_enabled: true
|
||||
|
||||
immich_identifier: immich
|
||||
|
||||
# latest - Latest Immich release with an Ubuntu base.
|
||||
# noml - Latest Immich release with an Ubuntu base. Machine-learning is completely removed, making it still compatible with hardware accelaration.
|
||||
# alpine - Latest Immich release with an Alpine base. Machine-learning is completely removed, making it a very lightweight image (can have issues with RAW images).
|
||||
immich_version: 'v1.93.3-ig193'
|
||||
immich_distro_variant: noml
|
||||
|
||||
immich_uid: ''
|
||||
immich_gid: ''
|
||||
|
||||
# The hostname at which Immich is served.
|
||||
immich_hostname: ''
|
||||
|
||||
# The path at which Immich is exposed.
|
||||
# This value must either be `/` or not end with a slash (e.g. `/immich`).
|
||||
immich_path_prefix: /
|
||||
|
||||
immich_base_path: "{{ immich_playbook_base_path }}/immich"
|
||||
immich_config_dir_path: "{{ immich_base_path }}/config"
|
||||
immich_photos_dir_path: "{{ immich_base_path }}/photos"
|
||||
immich_import_dir_path: "{{ immich_base_path }}/import"
|
||||
|
||||
immich_systemd_required_services_list: "{{ immich_systemd_required_services_list_default + immich_systemd_required_services_list_auto + immich_systemd_required_services_list_custom }}"
|
||||
immich_systemd_required_services_list_default: ['docker.service']
|
||||
immich_systemd_required_services_list_auto: []
|
||||
immich_systemd_required_services_list_custom: []
|
||||
|
||||
immich_config_database_hostname: ''
|
||||
immich_config_database_port: 5432
|
||||
immich_config_database_name: immich
|
||||
immich_config_database_username: ''
|
||||
immich_config_database_password: ''
|
||||
|
||||
immich_config_machine_learning_workers: ''
|
||||
immich_config_machine_learning_workers_timeout: 120
|
||||
|
||||
# Controls the IMMICH_REDIS_HOSTNAME environment variable
|
||||
immich_config_redis_hostname: ''
|
||||
|
||||
# Controls the IMMICH_LOG_LEVEL environment variable.
|
||||
# Valid values: debug, info, warn, error
|
||||
immich_config_log_level: info
|
||||
|
||||
immich_container_image: "{{ immich_container_image_registry_prefix }}imagegenius/immich:{{ immich_container_image_tag }}"
|
||||
immich_container_image_registry_prefix: ghcr.io/
|
||||
immich_container_image_tag: "{{ immich_distro_variant }}-{{ immich_version }}"
|
||||
immich_container_image_force_pull: "{{ immich_container_image_registry_prefix }}imagegenius/immich:latest"
|
||||
|
||||
# The base container network. It will be auto-created by this role if it doesn't exist already.
|
||||
immich_container_network: "{{ immich_identifier }}"
|
||||
|
||||
# A list of additional container networks that the container would be connected to.
|
||||
# The playbook does not create these networks, so make sure they already exist.
|
||||
# Use this to expose the container to another reverse proxy, which runs in a different container network.
|
||||
immich_container_additional_networks: "{{ immich_container_additional_networks_auto + immich_container_additional_networks_custom }}"
|
||||
immich_container_additional_networks_auto: []
|
||||
immich_container_additional_networks_custom: []
|
||||
|
||||
# immich_container_labels_traefik_enabled controls whether labels to assist a Traefik reverse-proxy will be attached to the container.
|
||||
# See `roles/immich/immich/templates/labels.j2` for details.
|
||||
#
|
||||
# To inject your own other container labels, see `immich_container_labels_additional_labels`.
|
||||
immich_container_labels_traefik_enabled: true
|
||||
immich_container_labels_traefik_docker_network: ''
|
||||
immich_container_labels_traefik_hostname: "{{ immich_hostname }}"
|
||||
# The path prefix must either be `/` or not end with a slash (e.g. `/immich`).
|
||||
immich_container_labels_traefik_path_prefix: "{{ immich_path_prefix }}"
|
||||
immich_container_labels_traefik_rule: "Host(`{{ immich_container_labels_traefik_hostname }}`){% if immich_container_labels_traefik_path_prefix != '/' %} && PathPrefix(`{{ immich_container_labels_traefik_path_prefix }}`){% endif %}"
|
||||
immich_container_labels_traefik_priority: 0
|
||||
immich_container_labels_traefik_entrypoints: web-secure
|
||||
immich_container_labels_traefik_tls: "{{ immich_container_labels_traefik_entrypoints != 'web' }}"
|
||||
immich_container_labels_traefik_tls_certResolver: default # noqa var-naming
|
||||
|
||||
# A list of extra arguments to pass to the container
|
||||
immich_container_extra_arguments: []
|
||||
|
||||
# immich_container_additional_environment_variables contains a multiline string with additional environment variables to pass to the container.
|
||||
#
|
||||
# Example:
|
||||
# immich_container_additional_environment_variables: |
|
||||
# VAR=1
|
||||
# ANOTHER=value
|
||||
immich_container_additional_environment_variables: ''
|
||||
6
justfile
Normal file
6
justfile
Normal file
@@ -0,0 +1,6 @@
|
||||
# show help by default
|
||||
default:
|
||||
@just --list --justfile {{ justfile() }}
|
||||
|
||||
lint:
|
||||
ansible-lint .
|
||||
21
meta/main.yml
Normal file
21
meta/main.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
galaxy_info:
|
||||
author: virt
|
||||
company: virt
|
||||
role_name: immich
|
||||
namespace: mash
|
||||
description: immich
|
||||
platforms:
|
||||
- name: Debian
|
||||
versions:
|
||||
- all
|
||||
- name: Ubuntu
|
||||
versions:
|
||||
- all
|
||||
- name: Archlinux
|
||||
versions:
|
||||
- all
|
||||
- name: EL
|
||||
versions:
|
||||
- 7
|
||||
license: GPL-3.0-or-later
|
||||
min_ansible_version: '2.1'
|
||||
43
tasks/install.yml
Normal file
43
tasks/install.yml
Normal file
@@ -0,0 +1,43 @@
|
||||
---
|
||||
|
||||
- name: Ensure Immich paths exist
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
mode: "0750"
|
||||
owner: "{{ immich_uid }}"
|
||||
group: "{{ immich_gid }}"
|
||||
with_items:
|
||||
- "{{ immich_base_path }}"
|
||||
- "{{ immich_config_dir_path }}"
|
||||
- "{{ immich_photos_dir_path }}"
|
||||
- "{{ immich_import_dir_path }}"
|
||||
|
||||
- name: Ensure Immich support files created
|
||||
ansible.builtin.template:
|
||||
src: "{{ role_path }}/templates/{{ item }}.j2"
|
||||
dest: "{{ immich_base_path }}/{{ item }}"
|
||||
owner: "{{ immich_uid }}"
|
||||
group: "{{ immich_gid }}"
|
||||
mode: 0640
|
||||
with_items:
|
||||
- env
|
||||
- labels
|
||||
|
||||
- name: Ensure Immich container network is created
|
||||
community.general.docker_network:
|
||||
name: "{{ immich_container_network }}"
|
||||
driver: bridge
|
||||
|
||||
- name: Ensure Immich container image is pulled
|
||||
community.docker.docker_image:
|
||||
name: "{{ immich_container_image }}"
|
||||
source: "{{ 'pull' if ansible_version.major > 2 or ansible_version.minor > 7 else omit }}"
|
||||
force_source: "{{ immich_container_image_force_pull if ansible_version.major > 2 or ansible_version.minor >= 8 else omit }}"
|
||||
force: "{{ omit if ansible_version.major > 2 or ansible_version.minor >= 8 else immich_container_image_force_pull }}"
|
||||
|
||||
- name: Ensure Immich systemd service installed
|
||||
ansible.builtin.template:
|
||||
src: "{{ role_path }}/templates/immich.service.j2"
|
||||
dest: "{{ devture_systemd_docker_base_systemd_path }}/{{ immich_identifier }}.service"
|
||||
mode: 0644
|
||||
20
tasks/main.yml
Normal file
20
tasks/main.yml
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
|
||||
- block:
|
||||
- when: immich_enabled | bool
|
||||
ansible.builtin.include_tasks: "{{ role_path }}/tasks/validate_config.yml"
|
||||
|
||||
- when: immich_enabled | bool
|
||||
ansible.builtin.include_tasks: "{{ role_path }}/tasks/install.yml"
|
||||
tags:
|
||||
- setup-all
|
||||
- setup-immich
|
||||
- install-all
|
||||
- install-immich
|
||||
|
||||
- block:
|
||||
- when: not immich_enabled | bool
|
||||
ansible.builtin.include_tasks: "{{ role_path }}/tasks/uninstall.yml"
|
||||
tags:
|
||||
- setup-all
|
||||
- setup-immich
|
||||
25
tasks/uninstall.yml
Normal file
25
tasks/uninstall.yml
Normal file
@@ -0,0 +1,25 @@
|
||||
---
|
||||
|
||||
- name: Check existence of Immich systemd service
|
||||
ansible.builtin.stat:
|
||||
path: "{{ devture_systemd_docker_base_systemd_path }}/{{ immich_identifier }}.service"
|
||||
register: immich_service_stat
|
||||
|
||||
- when: immich_service_stat.stat.exists | bool
|
||||
block:
|
||||
- name: Ensure Immich systemd service is stopped
|
||||
ansible.builtin.service:
|
||||
name: "{{ immich_identifier }}"
|
||||
state: stopped
|
||||
enabled: false
|
||||
daemon_reload: true
|
||||
|
||||
- name: Ensure Immich systemd service does not exists
|
||||
ansible.builtin.file:
|
||||
path: "{{ devture_systemd_docker_base_systemd_path }}/{{ immich_identifier }}.service"
|
||||
state: absent
|
||||
|
||||
- name: Ensure Immich path doesn't exist
|
||||
ansible.builtin.file:
|
||||
path: "{{ immich_base_path }}"
|
||||
state: absent
|
||||
38
tasks/validate_config.yml
Normal file
38
tasks/validate_config.yml
Normal file
@@ -0,0 +1,38 @@
|
||||
---
|
||||
|
||||
- name: Fail if required Immich settings not defined
|
||||
ansible.builtin.fail:
|
||||
msg: >-
|
||||
You need to define a required configuration setting (`{{ item }}`) for using this role.
|
||||
when: "vars[item] | string == ''"
|
||||
with_items:
|
||||
- immich_identifier
|
||||
- immich_uid
|
||||
- immich_gid
|
||||
- immich_container_network
|
||||
- immich_hostname
|
||||
- immich_path_prefix
|
||||
- immich_config_database_hostname
|
||||
- immich_config_database_username
|
||||
- immich_config_database_password
|
||||
- immich_config_redis_hostname
|
||||
|
||||
- when: immich_container_labels_traefik_enabled | bool
|
||||
block:
|
||||
- name: Fail if required Immich Traefik settings not defined
|
||||
ansible.builtin.fail:
|
||||
msg: >-
|
||||
You need to define a required configuration setting (`{{ item }}`).
|
||||
when: "vars[item] == ''"
|
||||
with_items:
|
||||
- immich_container_labels_traefik_hostname
|
||||
- immich_container_labels_traefik_path_prefix
|
||||
|
||||
# We ensure it doesn't end with a slash, because we handle both (slash and no-slash).
|
||||
# Knowing that `immich_container_labels_traefik_path_prefix` does not end with a slash
|
||||
# ensures we know how to set these routes up without having to do "does it end with a slash" checks elsewhere.
|
||||
- name: Fail if immich_container_labels_traefik_path_prefix ends with a slash
|
||||
ansible.builtin.fail:
|
||||
msg: >-
|
||||
immich_container_labels_traefik_path_prefix (`{{ immich_container_labels_traefik_path_prefix }}`) must either be `/` or not end with a slash (e.g. `/immich`).
|
||||
when: "immich_container_labels_traefik_path_prefix != '/' and immich_container_labels_traefik_path_prefix[-1] == '/'"
|
||||
19
templates/env.j2
Normal file
19
templates/env.j2
Normal file
@@ -0,0 +1,19 @@
|
||||
DB_USERNAME={{ immich_config_database_username }}
|
||||
DB_PASSWORD={{ immich_config_database_password }}
|
||||
DB_DATABASE_NAME={{ immich_config_database_name }}
|
||||
IMMICH_DB_SSL=false
|
||||
DB_HOSTNAME={{ immich_config_database_hostname }}
|
||||
DB_PORT={{ immich_config_database_port }}
|
||||
|
||||
REDIS_HOSTNAME={{ immich_config_redis_hostname }}
|
||||
|
||||
PUID={{ immich_uid }}
|
||||
PGID={{ immich_gid }}
|
||||
TZ=Europe/Bratislava
|
||||
|
||||
MACHINE_LEARNING_WORKERS={{ immich_config_machine_learning_workers }}
|
||||
MACHINE_LEARNING_WORKER_TIMEOUT={{ immich_config_machine_learning_workers_timeout }}
|
||||
|
||||
IMMICH_LOG_LEVEL={{ immich_config_log_level }}
|
||||
|
||||
{{ immich_container_additional_environment_variables }}
|
||||
47
templates/immich.service.j2
Normal file
47
templates/immich.service.j2
Normal file
@@ -0,0 +1,47 @@
|
||||
[Unit]
|
||||
Description=Immich ({{ immich_identifier }})
|
||||
{% for service in immich_systemd_required_services_list %}
|
||||
Requires={{ service }}
|
||||
After={{ service }}
|
||||
{% endfor %}
|
||||
DefaultDependencies=no
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Environment="HOME={{ devture_systemd_docker_base_systemd_unit_home_path }}"
|
||||
ExecStartPre=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} stop --time={{ devture_systemd_docker_base_container_stop_grace_time_seconds }} {{ immich_identifier }} 2>/dev/null'
|
||||
ExecStartPre=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} rm {{ immich_identifier }} 2>/dev/null'
|
||||
|
||||
ExecStartPre={{ devture_systemd_docker_base_host_command_docker }} create \
|
||||
--rm \
|
||||
--name={{ immich_identifier }} \
|
||||
--log-driver=none \
|
||||
--network={{ immich_container_network }} \
|
||||
--user={{ immich_uid }}:{{ immich_gid }} \
|
||||
--cap-drop=ALL \
|
||||
--read-only \
|
||||
--env-file={{ immich_base_path }}/env \
|
||||
--label-file={{ immich_base_path }}/labels \
|
||||
--mount type=bind,src={{ immich_config_dir_path }},dst=/config \
|
||||
--mount type=bind,src={{ immich_photos_dir_path }},dst=/photos \
|
||||
--mount type=bind,src={{ immich_import_dir_path }},dst=/import,ro \
|
||||
--tmpfs=/tmp:rw,noexec,nosuid,size=512m \
|
||||
{% for arg in immich_container_extra_arguments %}
|
||||
{{ arg }} \
|
||||
{% endfor %}
|
||||
{{ immich_container_image }}
|
||||
|
||||
{% for network in immich_container_additional_networks %}
|
||||
ExecStartPre={{ devture_systemd_docker_base_host_command_docker }} network connect {{ network }} {{ immich_identifier }}
|
||||
{% endfor %}
|
||||
|
||||
ExecStart={{ devture_systemd_docker_base_host_command_docker }} start --attach {{ immich_identifier }}
|
||||
|
||||
ExecStop=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} stop --time={{ devture_systemd_docker_base_container_stop_grace_time_seconds }} {{ immich_identifier }} 2>/dev/null'
|
||||
ExecStop=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} rm {{ immich_identifier }} 2>/dev/null'
|
||||
Restart=always
|
||||
RestartSec=30
|
||||
SyslogIdentifier={{ immich_identifier }}
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
38
templates/labels.j2
Normal file
38
templates/labels.j2
Normal file
@@ -0,0 +1,38 @@
|
||||
{% if immich_container_labels_traefik_enabled %}
|
||||
traefik.enable=true
|
||||
|
||||
{% if immich_container_labels_traefik_docker_network %}
|
||||
traefik.docker.network={{ immich_container_labels_traefik_docker_network }}
|
||||
{% endif %}
|
||||
|
||||
{% set middlewares = [] %}
|
||||
|
||||
{% if immich_container_labels_traefik_path_prefix != '/' %}
|
||||
traefik.http.middlewares.{{ immich_identifier }}-slashless-redirect.redirectregex.regex=^({{ immich_container_labels_traefik_path_prefix | quote }})$
|
||||
traefik.http.middlewares.{{ immich_identifier }}-slashless-redirect.redirectregex.replacement=${1}/
|
||||
{% set middlewares = middlewares + [immich_identifier + '-slashless-redirect'] %}
|
||||
{% endif %}
|
||||
|
||||
{% if immich_container_labels_traefik_path_prefix != '/' %}
|
||||
traefik.http.middlewares.{{ immich_identifier }}-strip-prefix.stripprefix.prefixes={{ immich_container_labels_traefik_path_prefix }}
|
||||
{% set middlewares = middlewares + [immich_identifier + '-strip-prefix'] %}
|
||||
{% endif %}
|
||||
|
||||
traefik.http.routers.{{ immich_identifier }}.rule={{ immich_container_labels_traefik_rule }}
|
||||
{% if immich_container_labels_traefik_priority | int > 0 %}
|
||||
traefik.http.routers.{{ immich_identifier }}.priority={{ immich_container_labels_traefik_priority }}
|
||||
{% endif %}
|
||||
traefik.http.routers.{{ immich_identifier }}.service={{ immich_identifier }}
|
||||
{% if middlewares | length > 0 %}
|
||||
traefik.http.routers.{{ immich_identifier }}.middlewares={{ middlewares | join(',') }}
|
||||
{% endif %}
|
||||
traefik.http.routers.{{ immich_identifier }}.entrypoints={{ immich_container_labels_traefik_entrypoints }}
|
||||
traefik.http.routers.{{ immich_identifier }}.tls={{ immich_container_labels_traefik_tls | to_json }}
|
||||
{% if immich_container_labels_traefik_tls %}
|
||||
traefik.http.routers.{{ immich_identifier }}.tls.certResolver={{ immich_container_labels_traefik_tls_certResolver }}
|
||||
{% endif %}
|
||||
|
||||
traefik.http.services.{{ immich_identifier }}.loadbalancer.server.port=8080
|
||||
{% endif %}
|
||||
|
||||
{{ immich_container_labels_additional_labels }}
|
||||
Reference in New Issue
Block a user