infra(sys-service): centralize async control + pre-deploy backup safeguard

- Added MODE_BACKUP to trigger backup before the rest of the deployment

- sys-ctl-bkp-docker-2-loc: force linear sync and force flush when MODE_BACKUP is true

- Unified name resolution via system_service_name across handlers and tasks

- Introduced system_service_force_linear_sync and system_service_force_flush (rename from system_force_flush)

- Drive async/poll via system_service_async/system_service_poll using omit when disabled

- Propagated per-role overrides (cleanup, repair, cert tasks) for clarity and safety

- Minor formatting and consistency cleanups

Why: Ensure the backup runs before the deployment routine to safeguard data integrity.

Refs: Conversation https://chatgpt.com/share/68de4c41-b6e4-800f-85cd-ce6949097b5e
Signed-off-by: Kevin Veen-Birkenbach <kevin@veen.world>
This commit is contained in:
2025-10-02 11:58:23 +02:00
parent 8beda2d45d
commit 23353ac878
17 changed files with 72 additions and 52 deletions

View File

@@ -7,3 +7,4 @@ MODE_DEBUG: false # This enables debugging in ansible an
MODE_RESET: false # Cleans up all Infinito.Nexus files. It's necessary to run to whole playbook and not particial roles when using this function. MODE_RESET: false # Cleans up all Infinito.Nexus files. It's necessary to run to whole playbook and not particial roles when using this function.
MODE_CLEANUP: "{{ MODE_DEBUG | bool }}" # Cleanup unused files and configurations MODE_CLEANUP: "{{ MODE_DEBUG | bool }}" # Cleanup unused files and configurations
MODE_ASSERT: "{{ MODE_DEBUG | bool }}" # Executes validation tasks during the run. MODE_ASSERT: "{{ MODE_DEBUG | bool }}" # Executes validation tasks during the run.
MODE_BACKUP: true # Executes the Backup before the deployment

View File

@@ -5,21 +5,23 @@
- sys-ctl-alm-telegram - sys-ctl-alm-telegram
- sys-ctl-alm-email - sys-ctl-alm-email
vars: vars:
flush_handlers: true flush_handlers: true
system_service_timer_enabled: false system_service_timer_enabled: false
system_service_copy_files: true system_service_copy_files: true
system_service_tpl_exec_start: "{{ system_service_script_exec }} %I" system_service_tpl_exec_start: "{{ system_service_script_exec }} %I"
system_service_tpl_on_failure: "" system_service_tpl_on_failure: ""
system_service_force_linear_sync: false
- name: "Include core service for '{{ system_service_id }}'" - name: "Include core service for '{{ system_service_id }}'"
include_role: include_role:
name: sys-service name: sys-service
vars: vars:
flush_handlers: true flush_handlers: true
system_service_timer_enabled: false system_service_timer_enabled: false
system_service_copy_files: true system_service_copy_files: true
system_service_tpl_exec_start: "{{ system_service_script_exec }} %I" system_service_tpl_exec_start: "{{ system_service_script_exec }} %I"
system_service_tpl_on_failure: "" # No on failure needed, because it's anyhow the default on failure procedure system_service_tpl_on_failure: "" # No on failure needed, because it's anyhow the default on failure procedure
system_service_force_linear_sync: false
- name: Assert '{{ system_service_id }}' - name: Assert '{{ system_service_id }}'
block: block:

View File

@@ -19,6 +19,8 @@
vars: vars:
system_service_copy_files: false system_service_copy_files: false
system_service_timer_enabled: true system_service_timer_enabled: true
system_service_force_linear_sync: true
system_service_force_flush: "{{ MODE_BACKUP | bool }}"
system_service_on_calendar: "{{ SYS_SCHEDULE_BACKUP_DOCKER_TO_LOCAL }}" system_service_on_calendar: "{{ SYS_SCHEDULE_BACKUP_DOCKER_TO_LOCAL }}"
system_service_tpl_exec_start_pre: '/usr/bin/python {{ PATH_SYSTEM_LOCK_SCRIPT }} {{ SYS_SERVICE_GROUP_MANIPULATION | join(" ") }} --ignore {{ SYS_SERVICE_BACKUP_DOCKER_2_LOC }} --timeout "{{ SYS_TIMEOUT_BACKUP_SERVICES }}"' system_service_tpl_exec_start_pre: '/usr/bin/python {{ PATH_SYSTEM_LOCK_SCRIPT }} {{ SYS_SERVICE_GROUP_MANIPULATION | join(" ") }} --ignore {{ SYS_SERVICE_BACKUP_DOCKER_2_LOC }} --timeout "{{ SYS_TIMEOUT_BACKUP_SERVICES }}"'
system_service_tpl_exec_start: "/bin/sh -c '{{ BKP_DOCKER_2_LOC_EXEC }}'" system_service_tpl_exec_start: "/bin/sh -c '{{ BKP_DOCKER_2_LOC_EXEC }}'"

View File

@@ -12,6 +12,7 @@
system_service_tpl_exec_start: dockreap --no-confirmation system_service_tpl_exec_start: dockreap --no-confirmation
system_service_tpl_exec_start_pre: "" # Anonymous volumes can allways be removed. It isn't necessary to wait for any service to stop. system_service_tpl_exec_start_pre: "" # Anonymous volumes can allways be removed. It isn't necessary to wait for any service to stop.
system_service_copy_files: false system_service_copy_files: false
system_service_force_linear_sync: false
- include_tasks: utils/run_once.yml - include_tasks: utils/run_once.yml
when: when:

View File

@@ -20,6 +20,7 @@
system_service_tpl_exec_start: "{{ system_service_script_exec }} --backups-folder-path {{ BACKUPS_FOLDER_PATH }} --maximum-backup-size-percent {{SIZE_PERCENT_MAXIMUM_BACKUP}}" system_service_tpl_exec_start: "{{ system_service_script_exec }} --backups-folder-path {{ BACKUPS_FOLDER_PATH }} --maximum-backup-size-percent {{SIZE_PERCENT_MAXIMUM_BACKUP}}"
system_service_tpl_exec_start_pre: '/usr/bin/python {{ PATH_SYSTEM_LOCK_SCRIPT }} {{ SYS_SERVICE_GROUP_MANIPULATION | join(" ") }} --ignore {{ SYS_SERVICE_GROUP_CLEANUP | join(" ") }} --timeout "{{ SYS_TIMEOUT_BACKUP_SERVICES }}"' system_service_tpl_exec_start_pre: '/usr/bin/python {{ PATH_SYSTEM_LOCK_SCRIPT }} {{ SYS_SERVICE_GROUP_MANIPULATION | join(" ") }} --ignore {{ SYS_SERVICE_GROUP_CLEANUP | join(" ") }} --timeout "{{ SYS_TIMEOUT_BACKUP_SERVICES }}"'
system_service_copy_files: true system_service_copy_files: true
system_service_force_linear_sync: false
- include_tasks: utils/run_once.yml - include_tasks: utils/run_once.yml
vars: vars:

View File

@@ -14,6 +14,7 @@
- include_role: - include_role:
name: sys-service name: sys-service
vars: vars:
system_service_timer_enabled: true system_service_timer_enabled: true
system_service_on_calendar: "{{ SYS_SCHEDULE_CLEANUP_CERTS }}" system_service_on_calendar: "{{ SYS_SCHEDULE_CLEANUP_CERTS }}"
system_service_copy_files: false system_service_copy_files: false
system_service_force_linear_sync: false

View File

@@ -14,3 +14,4 @@
system_service_tpl_on_failure: "{{ SYS_SERVICE_ON_FAILURE_COMPOSE }}" system_service_tpl_on_failure: "{{ SYS_SERVICE_ON_FAILURE_COMPOSE }}"
system_service_tpl_exec_start: "{{ system_service_script_exec }} {{ SIZE_PERCENT_CLEANUP_DISC_SPACE }}" system_service_tpl_exec_start: "{{ system_service_script_exec }} {{ SIZE_PERCENT_CLEANUP_DISC_SPACE }}"
system_service_tpl_exec_start_pre: '/usr/bin/python {{ PATH_SYSTEM_LOCK_SCRIPT }} {{ SYS_SERVICE_GROUP_MANIPULATION | join(" ") }} --ignore {{ SYS_SERVICE_GROUP_CLEANUP | join(" ") }} --timeout "{{ SYS_TIMEOUT_BACKUP_SERVICES }}"' system_service_tpl_exec_start_pre: '/usr/bin/python {{ PATH_SYSTEM_LOCK_SCRIPT }} {{ SYS_SERVICE_GROUP_MANIPULATION | join(" ") }} --ignore {{ SYS_SERVICE_GROUP_CLEANUP | join(" ") }} --timeout "{{ SYS_TIMEOUT_BACKUP_SERVICES }}"'
system_service_force_linear_sync: false

View File

@@ -21,5 +21,5 @@
system_service_tpl_on_failure: "{{ SYS_SERVICE_ON_FAILURE_COMPOSE }}" system_service_tpl_on_failure: "{{ SYS_SERVICE_ON_FAILURE_COMPOSE }}"
system_service_tpl_exec_start_pre: '/usr/bin/python {{ PATH_SYSTEM_LOCK_SCRIPT }} {{ SYS_SERVICE_GROUP_MANIPULATION | join(" ") }} --ignore {{ SYS_SERVICE_GROUP_CLEANUP| join(" ") }} --timeout "{{ SYS_TIMEOUT_CLEANUP_SERVICES }}"' system_service_tpl_exec_start_pre: '/usr/bin/python {{ PATH_SYSTEM_LOCK_SCRIPT }} {{ SYS_SERVICE_GROUP_MANIPULATION | join(" ") }} --ignore {{ SYS_SERVICE_GROUP_CLEANUP| join(" ") }} --timeout "{{ SYS_TIMEOUT_CLEANUP_SERVICES }}"'
system_service_tpl_exec_start: '/bin/sh -c "{{ CLEANUP_FAILED_BACKUPS_PKG }} --all --workers {{ CLEANUP_FAILED_BACKUPS_WORKERS }} --yes"' system_service_tpl_exec_start: '/bin/sh -c "{{ CLEANUP_FAILED_BACKUPS_PKG }} --all --workers {{ CLEANUP_FAILED_BACKUPS_WORKERS }} --yes"'
system_service_force_linear_sync: false
- include_tasks: utils/run_once.yml - include_tasks: utils/run_once.yml

View File

@@ -8,8 +8,9 @@
- include_role: - include_role:
name: sys-service name: sys-service
vars: vars:
system_service_state: restarted system_service_state: restarted
system_service_on_calendar: "{{ SYS_SCHEDULE_MAINTANANCE_LETSENCRYPT_DEPLOY }}" system_service_on_calendar: "{{ SYS_SCHEDULE_MAINTANANCE_LETSENCRYPT_DEPLOY }}"
persistent: "true" persistent: "true"
system_service_timer_enabled: true system_service_timer_enabled: true
system_service_tpl_on_failure: "{{ SYS_SERVICE_ON_FAILURE_COMPOSE }}" system_service_tpl_on_failure: "{{ SYS_SERVICE_ON_FAILURE_COMPOSE }}"
system_service_force_linear_sync: false

View File

@@ -15,8 +15,9 @@
- include_role: - include_role:
name: sys-service name: sys-service
vars: vars:
system_service_copy_files: false system_service_copy_files: false
system_service_on_calendar: "{{ SYS_SCHEDULE_MAINTANANCE_LETSENCRYPT_RENEW }}" system_service_on_calendar: "{{ SYS_SCHEDULE_MAINTANANCE_LETSENCRYPT_RENEW }}"
persistent: true persistent: true
system_service_timer_enabled: true system_service_timer_enabled: true
system_service_tpl_on_failure: "{{ SYS_SERVICE_ON_FAILURE_COMPOSE }}" system_service_tpl_on_failure: "{{ SYS_SERVICE_ON_FAILURE_COMPOSE }}"
system_service_force_linear_sync: false

View File

@@ -12,9 +12,10 @@
- include_role: - include_role:
name: sys-service name: sys-service
vars: vars:
system_service_suppress_flush: true # It takes a super long time - Better wait for failure of timed service instead of executing it on every play system_service_suppress_flush: true # It takes a super long time - Better wait for failure of timed service instead of executing it on every play
system_service_copy_files: false system_service_copy_files: false
system_service_on_calendar: "{{ SYS_SCHEDULE_REPAIR_BTRFS_AUTO_BALANCER }}" system_service_on_calendar: "{{ SYS_SCHEDULE_REPAIR_BTRFS_AUTO_BALANCER }}"
system_service_timer_enabled: true system_service_timer_enabled: true
system_service_tpl_on_failure: "{{ SYS_SERVICE_ON_FAILURE_COMPOSE }}" system_service_tpl_on_failure: "{{ SYS_SERVICE_ON_FAILURE_COMPOSE }}"
system_service_tpl_exec_start: "/bin/sh -c 'btrfs-auto-balancer 90 10'" system_service_tpl_exec_start: "/bin/sh -c 'btrfs-auto-balancer 90 10'"
system_service_force_linear_sync: true

View File

@@ -12,5 +12,6 @@
system_service_tpl_exec_start: '{{ system_service_script_exec }} {{ PATH_DOCKER_COMPOSE_INSTANCES }}' system_service_tpl_exec_start: '{{ system_service_script_exec }} {{ PATH_DOCKER_COMPOSE_INSTANCES }}'
system_service_tpl_exec_start_post: "/usr/bin/systemctl start {{ SYS_SERVICE_CLEANUP_ANONYMOUS_VOLUMES }}" system_service_tpl_exec_start_post: "/usr/bin/systemctl start {{ SYS_SERVICE_CLEANUP_ANONYMOUS_VOLUMES }}"
system_service_tpl_on_failure: "{{ SYS_SERVICE_ON_FAILURE_COMPOSE }}" system_service_tpl_on_failure: "{{ SYS_SERVICE_ON_FAILURE_COMPOSE }}"
system_service_force_linear_sync: true
- include_tasks: utils/run_once.yml - include_tasks: utils/run_once.yml

View File

@@ -10,5 +10,6 @@
system_service_tpl_exec_start_pre: "/usr/bin/python {{ PATH_SYSTEM_LOCK_SCRIPT }} {{ SYS_SERVICE_GROUP_MANIPULATION | join(' ') }} --ignore {{ SYS_SERVICE_GROUP_CLEANUP| join(' ') }} {{ SYS_SERVICE_REPAIR_DOCKER_SOFT }} --timeout '{{ SYS_TIMEOUT_DOCKER_RPR_SOFT }}'" system_service_tpl_exec_start_pre: "/usr/bin/python {{ PATH_SYSTEM_LOCK_SCRIPT }} {{ SYS_SERVICE_GROUP_MANIPULATION | join(' ') }} --ignore {{ SYS_SERVICE_GROUP_CLEANUP| join(' ') }} {{ SYS_SERVICE_REPAIR_DOCKER_SOFT }} --timeout '{{ SYS_TIMEOUT_DOCKER_RPR_SOFT }}'"
system_service_tpl_exec_start: > system_service_tpl_exec_start: >
/bin/sh -c '{{ system_service_script_exec }} --manipulation-string "{{ SYS_SERVICE_GROUP_MANIPULATION | join(" ") }}" {{ PATH_DOCKER_COMPOSE_INSTANCES }}' /bin/sh -c '{{ system_service_script_exec }} --manipulation-string "{{ SYS_SERVICE_GROUP_MANIPULATION | join(" ") }}" {{ PATH_DOCKER_COMPOSE_INSTANCES }}'
system_service_force_linear_sync: true
- include_tasks: utils/run_once.yml - include_tasks: utils/run_once.yml

View File

@@ -1,19 +1,19 @@
- name: "Enable systemctl service" - name: "Enable systemctl service"
systemd: systemd:
name: "{{ system_service_id | get_service_name(SOFTWARE_NAME) }}" name: "{{ system_service_name }}"
enabled: yes enabled: yes
daemon_reload: true daemon_reload: true
become: true become: true
async: "{{ ASYNC_TIME if ASYNC_ENABLED | bool else omit }}" async: "{{ system_service_async }}"
poll: "{{ ASYNC_POLL if ASYNC_ENABLED | bool else omit }}" poll: "{{ system_service_poll }}"
listen: refresh systemctl service listen: refresh systemctl service
- name: "Set systemctl service state" - name: "Set systemctl service state"
systemd: systemd:
name: "{{ system_service_id | get_service_name(SOFTWARE_NAME) }}" name: "{{ system_service_name }}"
state: "{{ system_service_state }}" state: "{{ system_service_state }}"
become: true become: true
async: "{{ ASYNC_TIME if ASYNC_ENABLED | bool else omit }}" async: "{{ system_service_async }}"
poll: "{{ ASYNC_POLL if ASYNC_ENABLED | bool else omit }}" poll: "{{ system_service_poll }}"
when: not (system_service_suppress_flush | bool) when: not (system_service_suppress_flush | bool)
listen: refresh systemctl service listen: refresh systemctl service

View File

@@ -31,7 +31,7 @@
- name: "setup systemctl '{{ system_service_id }}'" - name: "setup systemctl '{{ system_service_id }}'"
template: template:
src: "{{ system_service_template_src }}" src: "{{ system_service_template_src }}"
dest: "{{ [ PATH_SYSTEM_SERVICE_DIR, system_service_id | get_service_name(SOFTWARE_NAME) ] | path_join }}" dest: "{{ [ PATH_SYSTEM_SERVICE_DIR, system_service_name ] | path_join }}"
owner: root owner: root
group: root group: root
mode: '0644' mode: '0644'
@@ -46,5 +46,5 @@
command: /bin/true command: /bin/true
notify: refresh systemctl service notify: refresh systemctl service
when: not system_service_uses_at when: not system_service_uses_at
when: system_force_flush | bool when: system_service_force_flush | bool

View File

@@ -1,22 +1,28 @@
UNIT_SUFFIX_REMOVER_PACKAGE: "unsure" UNIT_SUFFIX_REMOVER_PACKAGE: "unsure"
system_service_name: "{{ system_service_id | get_service_name(SOFTWARE_NAME) }}"
## Paths ## Paths
system_service_role_name: "{{ system_service_id | regex_replace('@','') }}" system_service_role_name: "{{ system_service_id | regex_replace('@','') }}"
system_service_role_dir: "{{ [ playbook_dir, 'roles', system_service_role_name ] | path_join }}" system_service_role_dir: "{{ [ playbook_dir, 'roles', system_service_role_name ] | path_join }}"
system_service_script_dir: "{{ [ PATH_SYSTEMCTL_SCRIPTS, system_service_id ] | path_join }}" system_service_script_dir: "{{ [ PATH_SYSTEMCTL_SCRIPTS, system_service_id ] | path_join }}"
## Settings ## Settings
system_force_flush: "{{ SYS_SERVICE_ALL_ENABLED | bool }}" # When set to true it activates the flushing of services. defaults to SYS_SERVICE_ALL_ENABLED system_service_force_linear_sync: "{{ system_service_name in SYS_SERVICE_GROUP_MANIPULATION }}" # Disables automatic async
system_service_suppress_flush: "{{ (system_service_id in SYS_SERVICE_SUPPRESS_FLUSH) | bool }}" # When set to true it suppresses the flushing of services system_service_force_flush: "{{ SYS_SERVICE_ALL_ENABLED | bool }}" # When set to true it activates the flushing of services. defaults to SYS_SERVICE_ALL_ENABLED
system_service_copy_files: true # When set to false file copying will be skipped system_service_suppress_flush: "{{ (system_service_id in SYS_SERVICE_SUPPRESS_FLUSH) | bool }}" # When set to true it suppresses the flushing of services
system_service_timer_enabled: false # When set to true timer will be loaded system_service_copy_files: true # When set to false file copying will be skipped
system_service_state: "{{ SYS_SERVICE_DEFAULT_STATE }}" system_service_timer_enabled: false # When set to true timer will be loaded
system_service_state: "{{ SYS_SERVICE_DEFAULT_STATE }}"
## ASYNC Settings
system_service_async: "{{ omit if (system_service_force_linear_sync | bool or not ASYNC_ENABLED | bool) else ASYNC_TIME }}"
system_service_poll: "{{ omit if (system_service_force_linear_sync | bool or not ASYNC_ENABLED | bool) else ASYNC_POLL }}"
# Dynamic Loaded ( Just available when dependencies are loaded ) # Dynamic Loaded ( Just available when dependencies are loaded )
system_service_script_base: "{{ system_service_script_src | basename | regex_replace('\\.j2$', '') }}" system_service_script_base: "{{ system_service_script_src | basename | regex_replace('\\.j2$', '') }}"
system_service_script_type: "{{ system_service_script_base | filetype }}" system_service_script_type: "{{ system_service_script_base | filetype }}"
system_service_script_inter: "/bin/{{ 'bash' if system_service_script_type == 'sh' else 'python3'}}" system_service_script_inter: "/bin/{{ 'bash' if system_service_script_type == 'sh' else 'python3'}}"
system_service_script_exec: "{{ system_service_script_inter }} {{ system_service_id | get_service_script_path( system_service_script_type ) }}" system_service_script_exec: "{{ system_service_script_inter }} {{ system_service_id | get_service_script_path( system_service_script_type ) }}"
# Service template # Service template
system_service_tpl_on_failure: "{{ SYS_SERVICE_ON_FAILURE_COMPOSE }}" system_service_tpl_on_failure: "{{ SYS_SERVICE_ON_FAILURE_COMPOSE }}"

View File

@@ -3,7 +3,7 @@
include_role: include_role:
name: sys-ctl-cln-anon-volumes name: sys-ctl-cln-anon-volumes
vars: vars:
system_force_flush: true system_service_force_flush: true
- include_tasks: utils/run_once.yml - include_tasks: utils/run_once.yml
when: run_once_sys_ctl_cln_anon_volumes is not defined when: run_once_sys_ctl_cln_anon_volumes is not defined