diff --git a/README.md b/README.md index c2ac174cf9..a82992c979 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,7 @@ If you have a spare domain name you can configure applications to be accessible * [Organizr](https://organizr.app/) - ORGANIZR aims to be your one stop shop for your Servers Frontend. * [overseerr](https://docs.overseerr.dev) - open source software application for managing requests for your media library * [Paperless_ng](https://github.com/jonaswinkler/paperless-ng) - Scan, index and archive all your physical documents +* [Photoprism](https://photoprism.app) - AI-Powered Photos App for the Decentralized Web. Tag and find pictures automatically. * [Piwigo](https://piwigo.org/) - Photo Gallery Software * [Plex](https://www.plex.tv/) - Plex Media Server * [Portainer](https://portainer.io/) - for managing Docker and running custom images diff --git a/nas.yml b/nas.yml index d5680f2a05..16649a0270 100644 --- a/nas.yml +++ b/nas.yml @@ -297,6 +297,10 @@ - role: paperless_ng tags: - paperless_ng + + - role: photoprism + tags: + - photoprism - role: piwigo tags: diff --git a/roles/photoprism/defaults/main.yml b/roles/photoprism/defaults/main.yml new file mode 100644 index 0000000000..a05bdaa184 --- /dev/null +++ b/roles/photoprism/defaults/main.yml @@ -0,0 +1,30 @@ +--- +# Basic options +photoprism_enabled: false +photoprism_site_caption: "AI-Powered Photos App" + +# Directories +photoprism_data_directory: "{{ docker_home }}/photoprism" +photoprism_photos_directory: "{{ photos_root }}" + +# External configuration +photoprism_available_externally: false +photoprism_hostname: photoprism +photoprism_port: 2342 + +# Admin configs +photoprism_admin_user: admin +photoprism_admin_password: insecure + +# Database configs +# You must have the database already running. +# If you don't know how to do it, just leave as it is. +photoprism_database_driver: sqlite +photoprism_database_server: "" +photoprism_database_name: "" +photoprism_database_user: "" +photoprism_database_password: "" + +# Specs +photoprism_memory: 4g +photoprism_container_name: photoprism diff --git a/roles/photoprism/docs/photoprism.md b/roles/photoprism/docs/photoprism.md new file mode 100644 index 0000000000..ca33a96879 --- /dev/null +++ b/roles/photoprism/docs/photoprism.md @@ -0,0 +1,30 @@ +# Photoprism + +Homepage: + +PhotoPrism® is an AI-Powered Photos App for the Decentralized Web. + +It makes use of the latest technologies to tag and find pictures automatically without getting in your way. You can run it at home, on a private server, or in the cloud. + +## Usage + +Set `photoprism_enabled: true` in your `inventories//nas.yml` file. + +The Photoprism web interface can be found at . + +## Specific Configuration + +> Usually Photoprism has some spikes of memory when you are uploading a lot of pictures at the same time. Take that in consideration before deplying it. + +Make sure you change photoprism username and password in your nas.yml config file! + +* photoprism_admin_user: admin +* photoprism_admin_password: insecure + +To run together with a database instead of SQLite, which is recommended by Photoprism, you can change this setup. To do it, you must already have a database running and also specify the following variables in your own nas.yml file: + +* photoprism_database_driver: mariadb/mysql +* photoprism_database_server: "ip/sqlserver" +* photoprism_database_name: "photoprism_db" +* photoprism_database_user: "mydbuser" +* photoprism_database_password: "insecure" diff --git a/roles/photoprism/molecule/default/molecule.yml b/roles/photoprism/molecule/default/molecule.yml new file mode 100644 index 0000000000..c6a3c6c795 --- /dev/null +++ b/roles/photoprism/molecule/default/molecule.yml @@ -0,0 +1,6 @@ +--- +provisioner: + inventory: + group_vars: + all: + photoprism_enabled: true diff --git a/roles/photoprism/molecule/default/side_effect.yml b/roles/photoprism/molecule/default/side_effect.yml new file mode 100644 index 0000000000..8fb42c1af4 --- /dev/null +++ b/roles/photoprism/molecule/default/side_effect.yml @@ -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: + photoprism_enabled: false diff --git a/roles/photoprism/molecule/default/verify.yml b/roles/photoprism/molecule/default/verify.yml new file mode 100644 index 0000000000..291e849ac5 --- /dev/null +++ b/roles/photoprism/molecule/default/verify.yml @@ -0,0 +1,18 @@ +--- +- name: Verify + hosts: all + gather_facts: false + tasks: + - ansible.builtin.include_vars: + file: ../../defaults/main.yml + + - name: Get container state + community.docker.docker_container_info: + name: "{{ photoprism_container_name }}" + register: result + + - name: Check photoprism is running + ansible.builtin.assert: + that: + - result.container['State']['Status'] == "running" + - result.container['State']['Restarting'] == false diff --git a/roles/photoprism/molecule/default/verify_stopped.yml b/roles/photoprism/molecule/default/verify_stopped.yml new file mode 100644 index 0000000000..d1ed3e62d6 --- /dev/null +++ b/roles/photoprism/molecule/default/verify_stopped.yml @@ -0,0 +1,18 @@ +--- +- name: Verify + hosts: all + gather_facts: false + tasks: + - ansible.builtin.include_vars: + file: ../../defaults/main.yml + + - name: Try and stop and remove photoprism + community.docker.docker_container: + name: "{{ photoprism_container_name }}" + state: absent + register: result + + - name: Check photoprism is stopped + ansible.builtin.assert: + that: + - not result.changed diff --git a/roles/photoprism/tasks/main.yml b/roles/photoprism/tasks/main.yml new file mode 100644 index 0000000000..787f707cbf --- /dev/null +++ b/roles/photoprism/tasks/main.yml @@ -0,0 +1,50 @@ +--- +- name: Start Photoprism + block: + - name: Create Photoprism Directories + ansible.builtin.file: + path: "{{ item }}" + state: directory + with_items: + - "{{ photoprism_data_directory }}" + + - name: Photoprism Docker Container + community.docker.docker_container: + name: "{{ photoprism_container_name }}" + image: photoprism/photoprism + pull: true + volumes: + - "/etc/localtime:/etc/localtime:ro" + - "{{ photoprism_data_directory }}/storage:/photoprism/storage:rw" + - "{{ photoprism_photos_directory }}:/photoprism/originals:rw" + env: + PHOTOPRISM_SITE_CAPTION: "{{ photoprism_site_caption }}" + PHOTOPRISM_ADMIN_USER: "{{ photoprism_admin_user }}" + PHOTOPRISM_ADMIN_PASSWORD: "{{ photoprism_admin_password }}" + PHOTOPRISM_SITE_URL: "https://{{ photoprism_hostname }}.{{ ansible_nas_domain }}" + PHOTOPRISM_DATABASE_DRIVER: "{{ photoprism_database_driver }}" + PHOTOPRISM_DATABASE_SERVER: "{{ photoprism_database_server }}" + PHOTOPRISM_DATABASE_NAME: "{{ photoprism_database_name }}" + PHOTOPRISM_DATABASE_USER: "{{ photoprism_database_user }}" + PHOTOPRISM_DATABASE_PASSWORD: "{{ photoprism_database_password }}" + ports: + - "{{ photoprism_port }}:2342" + restart_policy: unless-stopped + memory: "{{ photoprism_memory }}" + labels: + traefik.enable: "{{ photoprism_available_externally | string }}" + traefik.http.routers.photoprism.rule: "Host(`{{ photoprism_hostname }}.{{ ansible_nas_domain }}`)" + traefik.http.routers.photoprism.tls.certresolver: "letsencrypt" + traefik.http.routers.photoprism.tls.domains[0].main: "{{ ansible_nas_domain }}" + traefik.http.routers.photoprism.tls.domains[0].sans: "*.{{ ansible_nas_domain }}" + traefik.http.routers.photoprism.service: "photoprism" + traefik.http.services.photoprism.loadbalancer.server.port: "{{ photoprism_port | string }}" + when: photoprism_enabled is true + +- name: Stop Photoprism + block: + - name: Stop Photoprism + community.docker.docker_container: + name: "{{ photoprism_container_name }}" + state: absent + when: photoprism_enabled is false