From dc9ee09360510231acc936b7c6eaa317f840cbb1 Mon Sep 17 00:00:00 2001 From: Marty Oehme Date: Fri, 18 Jul 2025 21:53:03 +0200 Subject: [PATCH 1/7] arr: Fix homarr volume mounts --- roles/arr/templates/compose.yaml.jinja | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/roles/arr/templates/compose.yaml.jinja b/roles/arr/templates/compose.yaml.jinja index 802e992..847e366 100644 --- a/roles/arr/templates/compose.yaml.jinja +++ b/roles/arr/templates/compose.yaml.jinja @@ -197,9 +197,9 @@ services: networks: - caddy volumes: - - {{ arrstack_env_dir }}/config/homarr/configs:/app/data/configs - - {{ arrstack_env_dir }}/config/homarr/icons:/app/public/icons - - {{ arrstack_env_dir }}/config/homarr/data:/data + - "{{ arrstack_env_dir }}/config/homarr/configs:/app/data/configs" + - "{{ arrstack_env_dir }}/config/homarr/icons:/app/public/icons" + - "{{ arrstack_env_dir }}/config/homarr/data:/data" - /var/run/docker.sock:/var/run/docker.sock # Optional, only if you want docker integration restart: unless-stopped labels: From 5b7f80bd29098fb8b44ecac3c37213efa0216ac1 Mon Sep 17 00:00:00 2001 From: Marty Oehme Date: Fri, 18 Jul 2025 21:58:32 +0200 Subject: [PATCH 2/7] repo: Rename main playbook to site.yaml --- playbook.yaml => site.yaml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename playbook.yaml => site.yaml (100%) diff --git a/playbook.yaml b/site.yaml similarity index 100% rename from playbook.yaml rename to site.yaml From 8dafc38a83e0cc3a42dc4ade1ab3e4f47be1bb1c Mon Sep 17 00:00:00 2001 From: Marty Oehme Date: Sat, 19 Jul 2025 08:53:51 +0200 Subject: [PATCH 3/7] docker: Tag complete docker playbook as docker If we only tag the geerlingguy docker 'role' as docker we do not always install the necessary python dependencies for later working with ansible docker compose and network roles. Applying the docker tag to them we can target '--tags=docker' on playbook run and be sure that all later roles will have the correct dependencies. --- site.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site.yaml b/site.yaml index 350e0da..a1a8f76 100644 --- a/site.yaml +++ b/site.yaml @@ -16,11 +16,11 @@ # ansible-galaxy install geerlingguy.docker - name: Install docker hosts: instance_system + tags: docker tasks: - name: Install docker and docker compose ansible.builtin.import_role: name: geerlingguy.docker - tags: docker - name: Install docker python requirements ansible.builtin.package: From 6b26ba444b0f16a8bfee5e1ae3d68853bb768cc4 Mon Sep 17 00:00:00 2001 From: Marty Oehme Date: Sat, 19 Jul 2025 08:53:51 +0200 Subject: [PATCH 4/7] restic: Only set backup hostname if we have ansible fact For all backup containers. --- roles/arr/templates/compose.yaml.jinja | 2 +- roles/grocy/templates/compose.yaml.jinja | 2 +- roles/paperless/templates/compose.yaml.jinja | 2 +- roles/restic/templates/compose.yaml.jinja | 16 ++++++++-------- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/roles/arr/templates/compose.yaml.jinja b/roles/arr/templates/compose.yaml.jinja index 847e366..19181dd 100644 --- a/roles/arr/templates/compose.yaml.jinja +++ b/roles/arr/templates/compose.yaml.jinja @@ -293,7 +293,7 @@ services: {% if restic_enable is not undefined and not false and arrstack_restic_enable is not undefined and not false %} backup: image: mazzolino/restic - hostname: "{{ ansible_hostname }}" + hostname: "{{ ansible_hostname | default() }}" environment: TZ: "{{ restic_tz }}" SKIP_INIT: true diff --git a/roles/grocy/templates/compose.yaml.jinja b/roles/grocy/templates/compose.yaml.jinja index e09a343..b3b1cc0 100644 --- a/roles/grocy/templates/compose.yaml.jinja +++ b/roles/grocy/templates/compose.yaml.jinja @@ -19,7 +19,7 @@ services: {% if restic_enable is not undefined and not false and stack_grocy_restic_enable is not undefined and not false %} backup: image: mazzolino/restic - hostname: "{{ ansible_hostname }}" + hostname: "{{ ansible_hostname | default() }}" environment: TZ: "{{ restic_tz }}" SKIP_INIT: true diff --git a/roles/paperless/templates/compose.yaml.jinja b/roles/paperless/templates/compose.yaml.jinja index c698b92..2bf7681 100644 --- a/roles/paperless/templates/compose.yaml.jinja +++ b/roles/paperless/templates/compose.yaml.jinja @@ -68,7 +68,7 @@ services: {% if restic_enable is not undefined and not false and stack_paperless_restic_enable is not undefined and not false %} backup: image: mazzolino/restic - hostname: "{{ ansible_hostname }}" + hostname: "{{ ansible_hostname | default() }}" environment: TZ: "{{ restic_tz }}" BACKUP_CRON: "{{ stack_paperless_restic_cron }}" diff --git a/roles/restic/templates/compose.yaml.jinja b/roles/restic/templates/compose.yaml.jinja index 306c522..65b4c5f 100644 --- a/roles/restic/templates/compose.yaml.jinja +++ b/roles/restic/templates/compose.yaml.jinja @@ -1,7 +1,7 @@ services: prune: image: "mazzolino/restic:{{ restic_version }}" - hostname: "{{ ansible_hostname }}" + hostname: "{{ ansible_hostname | default() }}" networks: - restic_notify environment: @@ -16,15 +16,15 @@ services: AWS_SECRET_ACCESS_KEY: "{{ restic_s3_secret }}" {% if restic_notify_success != None %} POST_COMMANDS_SUCCESS: |- - curl -X POST --data "{\"title\": \"Restic Prune successful\", \"body\": \"{{ ansible_hostname }}\"}" http://notify_success:5000 + curl -X POST --data "{\"title\": \"Restic Prune successful\", \"body\": \"$HOSTNAME\"}" http://notify_success:5000 {% endif %} {% if restic_notify_failure != None %} POST_COMMANDS_FAILURE: |- - curl -X POST --data "{\"title\": \"Restic Prune failed\", \"body\": \"{{ ansible_hostname }}\"}" http://notify_failure:5000 + curl -X POST --data "{\"title\": \"Restic Prune failed\", \"body\": \"$HOSTNAME\"}" http://notify_failure:5000 {% endif %} {% if restic_notify_exit != None %} POST_COMMANDS_EXIT: |- - curl -X POST --data "{\"title\": \"Restic Prune exited\", \"body\": \"{{ ansible_hostname }}\"}" http://notify_exit:5000 + curl -X POST --data "{\"title\": \"Restic Prune exited\", \"body\": \"$HOSTNAME\"}" http://notify_exit:5000 {% endif %} {% if restic_repo is regex('^/.+') %} volumes: @@ -33,7 +33,7 @@ services: check: image: "mazzolino/restic:{{ restic_version }}" - hostname: docker + hostname: "{{ ansible_hostname | default() }}" networks: - restic_notify environment: @@ -48,15 +48,15 @@ services: AWS_SECRET_ACCESS_KEY: "{{ restic_s3_secret }}" {% if restic_notify_success != None %} POST_COMMANDS_SUCCESS: |- - curl -X POST --data "{\"title\": \"Restic Check successful\", \"body\": \"{{ ansible_hostname }}\"}" http://notify_success:5000 + curl -X POST --data "{\"title\": \"Restic Check successful\", \"body\": \"$HOSTNAME\"}" http://notify_success:5000 {% endif %} {% if restic_notify_failure != None %} POST_COMMANDS_FAILURE: |- - curl -X POST --data "{\"title\": \"Restic Check failed\", \"body\": \"{{ ansible_hostname }}\"}" http://notify_failure:5000 + curl -X POST --data "{\"title\": \"Restic Check failed\", \"body\": \"$HOSTNAME\"}" http://notify_failure:5000 {% endif %} {% if restic_notify_exit != None %} POST_COMMANDS_EXIT: |- - curl -X POST --data "{\"title\": \"Restic Check exited\", \"body\": \"{{ ansible_hostname }}\"}" http://notify_exit:5000 + curl -X POST --data "{\"title\": \"Restic Check exited\", \"body\": \"$HOSTNAME\"}" http://notify_exit:5000 {% endif %} {% if restic_repo is regex('^/.+') %} volumes: From 84d7319465b8a29f86445799a0844d3486f9318e Mon Sep 17 00:00:00 2001 From: Marty Oehme Date: Sat, 19 Jul 2025 08:53:51 +0200 Subject: [PATCH 5/7] roles: Set caddy and docker dependency chain Each role (with outward-facing ingress needs) depends on caddy since they depend on the availability of the 'caddy' network which is set in that role. Caddy in turn depends on docker. --- roles/arr/meta/main.yaml | 5 ++--- roles/grocy/meta/main.yaml | 5 ++--- roles/paperless/meta/main.yaml | 5 ++--- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/roles/arr/meta/main.yaml b/roles/arr/meta/main.yaml index a8f4f00..d073d82 100644 --- a/roles/arr/meta/main.yaml +++ b/roles/arr/meta/main.yaml @@ -21,6 +21,5 @@ galaxy_info: # NOTE: A tag is limited to a single word comprised of alphanumeric characters. # Maximum 20 tags per role. -dependencies: [] - # List your role dependencies here, one per line. Be sure to remove the '[]' above, - # if you add dependencies to this list. +dependencies: + - caddy diff --git a/roles/grocy/meta/main.yaml b/roles/grocy/meta/main.yaml index ea68190..2b1493a 100644 --- a/roles/grocy/meta/main.yaml +++ b/roles/grocy/meta/main.yaml @@ -29,6 +29,5 @@ galaxy_info: # NOTE: A tag is limited to a single word comprised of alphanumeric characters. # Maximum 20 tags per role. -dependencies: [] - # List your role dependencies here, one per line. Be sure to remove the '[]' above, - # if you add dependencies to this list. +dependencies: + - caddy diff --git a/roles/paperless/meta/main.yaml b/roles/paperless/meta/main.yaml index ea68190..2b1493a 100644 --- a/roles/paperless/meta/main.yaml +++ b/roles/paperless/meta/main.yaml @@ -29,6 +29,5 @@ galaxy_info: # NOTE: A tag is limited to a single word comprised of alphanumeric characters. # Maximum 20 tags per role. -dependencies: [] - # List your role dependencies here, one per line. Be sure to remove the '[]' above, - # if you add dependencies to this list. +dependencies: + - caddy From c5448b17cc48a7ce2df98d96dd711be17614a39a Mon Sep 17 00:00:00 2001 From: Marty Oehme Date: Sat, 19 Jul 2025 08:53:51 +0200 Subject: [PATCH 6/7] site: Bootstrap python for any target Before running the main site playbook or any other tasks, we ensure that python is installed on any host so we can actually connect with ansible. --- site.yaml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/site.yaml b/site.yaml index a1a8f76..eb20d2e 100644 --- a/site.yaml +++ b/site.yaml @@ -1,4 +1,22 @@ --- +# TODO: Add to bootstrapping role / make less dependent on apt-get & debian (python3) +- name: Bootstrap python everywhere + hosts: all + gather_facts: False + become: true + tags: + - system + - bootstrap + tasks: + - name: check for python + ansible.builtin.raw: python3 --version + changed_when: false + failed_when: false + register: pythoncheck + - name: install debian python + ansible.builtin.raw: apt-get update && apt-get install python3 -y + when: pythoncheck.rc == 127 + - name: Prepare incus server host hosts: host_system tasks: @@ -31,6 +49,7 @@ - python3-requests # for docker network - name: Prepare all docker hosted containers + gather_facts: True hosts: instance_system tags: - containers From 4a5a0beca18a90e94456ec85f058d1993345ef63 Mon Sep 17 00:00:00 2001 From: Marty Oehme Date: Sat, 19 Jul 2025 10:12:56 +0200 Subject: [PATCH 7/7] restic: Fix backup container conditionals Change the inclusion of backup containers so they actually work. They check that restic is enabled globally, and that restic is enabled for the individual stack they belong to. If either of the conditions is not met they do not deploy. This way we can simply enable restic globally with `restic_enable` and by default all stacks will be backed up. But if we want to exclude specific stacks from backups we can do so with the individual `_restic_enable = False` variable. Finally found a good version of doing so with the help of the following medium article: https://medium.com/opsops/is-defined-in-ansible-d490945611ae which basically makes use of default fallbacks instead. --- roles/arr/templates/compose.yaml.jinja | 2 +- roles/grocy/templates/compose.yaml.jinja | 2 +- roles/paperless/templates/compose.yaml.jinja | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/roles/arr/templates/compose.yaml.jinja b/roles/arr/templates/compose.yaml.jinja index 19181dd..c61e3d0 100644 --- a/roles/arr/templates/compose.yaml.jinja +++ b/roles/arr/templates/compose.yaml.jinja @@ -290,7 +290,7 @@ services: caddy: "{{ arrstack_gonic_subdomain }}" caddy.reverse_proxy: "{{ '{{' }}upstreams 80{{ '}}'}}" -{% if restic_enable is not undefined and not false and arrstack_restic_enable is not undefined and not false %} +{% if restic_enable|d(False) == True and arrstack_restic_enable|d(False) == True %} backup: image: mazzolino/restic hostname: "{{ ansible_hostname | default() }}" diff --git a/roles/grocy/templates/compose.yaml.jinja b/roles/grocy/templates/compose.yaml.jinja index b3b1cc0..8b75bd6 100644 --- a/roles/grocy/templates/compose.yaml.jinja +++ b/roles/grocy/templates/compose.yaml.jinja @@ -16,7 +16,7 @@ services: caddy: "{{ stack_grocy_subdomain }}" caddy.reverse_proxy: "{{ '{{' }}upstreams 80{{ '}}'}}" -{% if restic_enable is not undefined and not false and stack_grocy_restic_enable is not undefined and not false %} +{% if restic_enable|d(False) == True and stack_grocy_restic_enable|d(False) == True %} backup: image: mazzolino/restic hostname: "{{ ansible_hostname | default() }}" diff --git a/roles/paperless/templates/compose.yaml.jinja b/roles/paperless/templates/compose.yaml.jinja index 2bf7681..06dc145 100644 --- a/roles/paperless/templates/compose.yaml.jinja +++ b/roles/paperless/templates/compose.yaml.jinja @@ -65,7 +65,7 @@ services: environment: REDIS_ARGS: "--save 60 10" -{% if restic_enable is not undefined and not false and stack_paperless_restic_enable is not undefined and not false %} +{% if restic_enable|d(False) == True and stack_paperless_restic_enable|d(False) == True %} backup: image: mazzolino/restic hostname: "{{ ansible_hostname | default() }}"