From 420cb3f9d989a19ff024ddaf5dcc49267310ff0b Mon Sep 17 00:00:00 2001 From: Anarion Date: Sun, 5 May 2024 14:15:51 +0200 Subject: [PATCH] :sparkles: Add Wanderer --- README.md | 1 + nas.yml | 4 + roles/wanderer/defaults/main.yml | 45 ++++++ roles/wanderer/docs/wanderer.md | 11 ++ roles/wanderer/molecule/default/molecule.yml | 6 + .../wanderer/molecule/default/side_effect.yml | 10 ++ roles/wanderer/molecule/default/verify.yml | 33 ++++ .../molecule/default/verify_stopped.yml | 33 ++++ roles/wanderer/requirements.yml | 1 + roles/wanderer/tasks/main.yml | 142 ++++++++++++++++++ website/docs/applications/other/wanderer.md | 14 ++ 11 files changed, 300 insertions(+) create mode 100644 roles/wanderer/defaults/main.yml create mode 100644 roles/wanderer/docs/wanderer.md create mode 100644 roles/wanderer/molecule/default/molecule.yml create mode 100644 roles/wanderer/molecule/default/side_effect.yml create mode 100644 roles/wanderer/molecule/default/verify.yml create mode 100644 roles/wanderer/molecule/default/verify_stopped.yml create mode 120000 roles/wanderer/requirements.yml create mode 100644 roles/wanderer/tasks/main.yml create mode 100644 website/docs/applications/other/wanderer.md diff --git a/README.md b/README.md index c6be4d950b..793a58c4a9 100644 --- a/README.md +++ b/README.md @@ -190,6 +190,7 @@ If you have a spare domain name you can configure applications to be accessible * [Vaultwarden](https://github.com/dani-garcia/vaultwarden) - Self-Hosting port of password manager * [Virtual Desktop](https://github.com/RattyDAVE/docker-ubuntu-xrdp-mate-custom) - A virtual desktop running on your NAS. * [Wallabag](https://wallabag.org/) - Save and classify articles. Read them later. +* [Wanderer](https://github.com/Flomp/wanderer) - A self-hosted trail database. * [Watchtower](https://github.com/v2tec/watchtower) - Monitor your Docker containers and update them if a new version is available * [Webtrees](https://www.webtrees.net/index.php/en/) - On-line collaborative genealogy application * [Wger](https://wger.de) - Free, open source web application that manages your exercises, workouts and nutrition diff --git a/nas.yml b/nas.yml index 71433ce97f..51f550d5ce 100644 --- a/nas.yml +++ b/nas.yml @@ -746,6 +746,10 @@ tags: - wallabag + - role: wanderer + tags: + - wanderer + - role: watchtower tags: - watchtower diff --git a/roles/wanderer/defaults/main.yml b/roles/wanderer/defaults/main.yml new file mode 100644 index 0000000000..fee25453fc --- /dev/null +++ b/roles/wanderer/defaults/main.yml @@ -0,0 +1,45 @@ +--- +wanderer_enabled: false +wanderer_available_externally: false + +# directories +wanderer_data_directory: "{{ docker_home }}/wanderer" + +# network +wanderer_port: "3015" +wanderer_db_port: "8090" +wanderer_search_port: "7700" +wanderer_hostname: "wanderer" +wanderer_network_name: "wanderer" + +# specs +wanderer_memory: 1g +wanderer_db_memory: 1g +wanderer_search_memory: 1g +wanderer_valhalla_memory: 1g + +# docker +wanderer_container_name: wanderer +wanderer_image_name: "flomp/wanderer-web" +wanderer_image_version: latest +wanderer_db_container_name: wanderer-db +wanderer_db_image_name: "flomp/wanderer-db" +wanderer_db_image_version: "latest" +wanderer_search_container_name: wanderer-search +wanderer_search_image_name: "flomp/wanderer-search" +wanderer_search_image_version: "latest" +wanderer_user_id: "1000" +wanderer_group_id: "1000" + +# wanderer +wanderer_meili_url: "http://{{ wanderer_search_container_name }}:7700" +wanderer_meili_master_key: "vODkljPcfFANYNepCHyDyGjzAMPcdHnrb6X5KyXQPWo" +wanderer_meili_no_analytics: "true" +wanderer_origin: "https://{{ wanderer_hostname }}.{{ ansible_nas_domain }}" +wanderer_body_size_limit: "Infinity" +wanderer_public_pocketbase_url: "http://{{ wanderer_db_container_name }}:{{ wanderer_db_port }}" +wanderer_public_disable_signup: "false" +wanderer_upload_folder: "/app/uploads" +wanderer_upload_user: "" +wanderer_upload_password: "" +wanderer_public_valhalla_url: "https://valhalla1.openstreetmap.de" diff --git a/roles/wanderer/docs/wanderer.md b/roles/wanderer/docs/wanderer.md new file mode 100644 index 0000000000..d51d62dc9d --- /dev/null +++ b/roles/wanderer/docs/wanderer.md @@ -0,0 +1,11 @@ +# Wanderer + +Homepage: [https://github.com/Flomp/wanderer](https://github.com/Flomp/wanderer) + +A self-hosted trail database. + +## Usage + +Set `wanderer_enabled: true` in your `inventories//group_vars/nas.yml` file. + +wanderer web interface can be found at [http://ansible_nas_host_or_ip:3015](http://ansible_nas_host_or_ip:3015). diff --git a/roles/wanderer/molecule/default/molecule.yml b/roles/wanderer/molecule/default/molecule.yml new file mode 100644 index 0000000000..e88eb1220d --- /dev/null +++ b/roles/wanderer/molecule/default/molecule.yml @@ -0,0 +1,6 @@ +--- +provisioner: + inventory: + group_vars: + all: + wanderer_enabled: true diff --git a/roles/wanderer/molecule/default/side_effect.yml b/roles/wanderer/molecule/default/side_effect.yml new file mode 100644 index 0000000000..18fcb2722b --- /dev/null +++ b/roles/wanderer/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: + wanderer_enabled: false diff --git a/roles/wanderer/molecule/default/verify.yml b/roles/wanderer/molecule/default/verify.yml new file mode 100644 index 0000000000..16ed22c79f --- /dev/null +++ b/roles/wanderer/molecule/default/verify.yml @@ -0,0 +1,33 @@ +--- +- name: Verify + hosts: all + gather_facts: false + tasks: + - name: Include vars + ansible.builtin.include_vars: + file: ../../defaults/main.yml + + - name: Get wanderer search container state + community.docker.docker_container: + name: "{{ wanderer_search_container_name }}" + register: result_search + + - name: Get wanderer db container state + community.docker.docker_container: + name: "{{ wanderer_db_container_name }}" + register: result_db + + - name: Get wanderer container state + community.docker.docker_container: + name: "{{ wanderer_container_name }}" + register: result + + - name: Check if wanderer containers are running + ansible.builtin.assert: + that: + - result_search.container['State']['Status'] == "running" + - result_search.container['State']['Restarting'] == false + - result_db.container['State']['Status'] == "running" + - result_db.container['State']['Restarting'] == false + - result.container['State']['Status'] == "running" + - result.container['State']['Restarting'] == false diff --git a/roles/wanderer/molecule/default/verify_stopped.yml b/roles/wanderer/molecule/default/verify_stopped.yml new file mode 100644 index 0000000000..9486dc94b0 --- /dev/null +++ b/roles/wanderer/molecule/default/verify_stopped.yml @@ -0,0 +1,33 @@ +--- +- 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 wanderer search + community.docker.docker_container: + name: "{{ wanderer_db_container_name }}" + state: absent + register: result_search + + - name: Try and stop and remove wanderer db + community.docker.docker_container: + name: "{{ wanderer_db_container_name }}" + state: absent + register: result_db + + - name: Try and stop and remove wanderer + community.docker.docker_container: + name: "{{ wanderer_container_name }}" + state: absent + register: result + + - name: Check if wanderer is stopped + ansible.builtin.assert: + that: + - not result_search.changed + - not result_db.changed + - not result.changed diff --git a/roles/wanderer/requirements.yml b/roles/wanderer/requirements.yml new file mode 120000 index 0000000000..9a736435ab --- /dev/null +++ b/roles/wanderer/requirements.yml @@ -0,0 +1 @@ +../../requirements.yml \ No newline at end of file diff --git a/roles/wanderer/tasks/main.yml b/roles/wanderer/tasks/main.yml new file mode 100644 index 0000000000..350a241d53 --- /dev/null +++ b/roles/wanderer/tasks/main.yml @@ -0,0 +1,142 @@ +--- +- name: Start Wanderer + block: + - name: Create Wanderer Directories + ansible.builtin.file: + path: "{{ item }}" + state: directory + with_items: + - "{{ wanderer_data_directory }}" + + - name: Create Wanderer network + community.docker.docker_network: + name: "{{ wanderer_network_name }}" + + - name: Create Wanderer Search Docker Container + community.docker.docker_container: + name: "{{ wanderer_search_container_name }}" + image: "{{ wanderer_search_image_name }}:{{ wanderer_search_image_version }}" + pull: true + volumes: + - "{{ wanderer_data_directory }}/data/data.ms:/meili_data/data.ms:rw" + networks: + - name: "{{ wanderer_network_name }}" + network_mode: "{{ wanderer_network_name }}" + container_default_behavior: no_defaults + ports: + - "{{ wanderer_search_port }}:7700" + env: + MEILI_URL: "{{ wanderer_meili_url }}" + MEILI_MASTER_KEY: "{{ wanderer_meili_master_key }}" + MEILI_NO_ANALYTICS: "{{ wanderer_meili_no_analytics }}" + labels: + traefik.enable: "false" + restart_policy: always + memory: "{{ wanderer_search_memory }}" + healthcheck: + test: curl --fail http://localhost:7700/health || exit 1 + interval: 15s + retries: 10 + start_period: 20s + timeout: 10s + + - name: Wait until Wanderer Search initializes and is healthy + community.docker.docker_container_info: + name: "{{ wanderer_search_container_name }}" + register: result + until: result.container.State.Health.Status == "healthy" + retries: 20 + delay: 30 + + - name: Create Wanderer Db Docker Container + community.docker.docker_container: + name: "{{ wanderer_db_container_name }}" + image: "{{ wanderer_db_image_name }}:{{ wanderer_db_image_version }}" + pull: true + volumes: + - "{{ wanderer_data_directory }}/data/pb_data:/pb_data:rw" + networks: + - name: "{{ wanderer_network_name }}" + network_mode: "{{ wanderer_network_name }}" + container_default_behavior: no_defaults + ports: + - "{{ wanderer_db_port }}:8090" + env: + MEILI_URL: "{{ wanderer_meili_url }}" + MEILI_MASTER_KEY: "{{ wanderer_meili_master_key }}" + MEILI_NO_ANALYTICS: "{{ wanderer_meili_no_analytics }}" + labels: + traefik.enable: "false" + restart_policy: always + memory: "{{ wanderer_db_memory }}" + + + - name: Wait until Wanderer DB is running + community.docker.docker_container_info: + name: "{{ wanderer_db_container_name }}" + register: result + until: result.container.State.Status == "running" + retries: 20 + delay: 30 + + - name: Create Wanderer Docker Container + community.docker.docker_container: + container_default_behavior: no_defaults + name: "{{ wanderer_container_name }}" + image: "{{ wanderer_image_name }}:{{ wanderer_image_version }}" + pull: true + volumes: + - "{{ wanderer_data_directory }}/data/uploads:/app/uploads:rw" + networks: + - name: "{{ wanderer_network_name }}" + network_mode: "{{ wanderer_network_name }}" + ports: + - "{{ wanderer_port }}:3000" + env: + TZ: "{{ ansible_nas_timezone }}" + PUID: "{{ wanderer_user_id | quote }}" + PGID: "{{ wanderer_group_id | quote }}" + MEILI_URL: "{{ wanderer_meili_url }}" + MEILI_MASTER_KEY: "{{ wanderer_meili_master_key }}" + MEILI_NO_ANALYTICS: "{{ wanderer_meili_no_analytics }}" + ORIGIN: "{{ wanderer_origin }}" + PUBLIC_POCKETBASE_URL: "{{ wanderer_public_pocketbase_url }}" + PUBLIC_DISABLE_SIGNUP: "{{ wanderer_public_disable_signup }}" + UPLOAD_FOLDER: "{{ wanderer_upload_folder }}" + UPLOAD_USER: "{{ wanderer_upload_user }}" + UPLOAD_PASSWORD: "{{ wanderer_upload_password }}" + PUBLIC_VALHALLA_URL: "{{ wanderer_public_valhalla_url }}" + restart_policy: unless-stopped + memory: "{{ wanderer_memory }}" + labels: + traefik.enable: "{{ wanderer_available_externally | string }}" + traefik.http.routers.wanderer.rule: "Host(`{{ wanderer_hostname }}.{{ ansible_nas_domain }}`)" + traefik.http.routers.wanderer.tls.certresolver: "letsencrypt" + traefik.http.routers.wanderer.tls.domains[0].main: "{{ ansible_nas_domain }}" + traefik.http.routers.wanderer.tls.domains[0].sans: "*.{{ ansible_nas_domain }}" + traefik.http.services.wanderer.loadbalancer.server.port: "3000" + healthcheck: + test: curl -ILfSs http://localhost:3000 > /dev/null || exit 1 + interval: 30s + timeout: 15s + retries: 3 + start_period: 30s + when: wanderer_enabled is true + +- name: Stop Wanderer + block: + - name: Stop Wanderer search + community.docker.docker_container: + name: "{{ wanderer_search_container_name }}" + state: absent + + - name: Stop Wanderer db + community.docker.docker_container: + name: "{{ wanderer_db_container_name }}" + state: absent + + - name: Stop Wanderer + community.docker.docker_container: + name: "{{ wanderer_container_name }}" + state: absent + when: wanderer_enabled is false diff --git a/website/docs/applications/other/wanderer.md b/website/docs/applications/other/wanderer.md new file mode 100644 index 0000000000..029b5850c2 --- /dev/null +++ b/website/docs/applications/other/wanderer.md @@ -0,0 +1,14 @@ +--- +title: "Wanderer" +description: "a self-hosted trail database" +--- + +Homepage: [https://github.com/Flomp/wanderer](https://github.com/Flomp/wanderer) + +A self-hosted trail database. + +## Usage + +Set `wanderer_enabled: true` in your `inventories//group_vars/nas.yml` file. + +wanderer web interface can be found at [http://ansible_nas_host_or_ip:3015](http://ansible_nas_host_or_ip:3015).