backup-homarr: rootless rclone install + delete older R2 versions

This commit is contained in:
Samuel James 2026-08-29 11:34:54 +00:00
parent 734935708a
commit 6df0813628

View File

@ -137,18 +137,40 @@
group: "{{ deploy_user }}"
mode: "0750"
- name: Ensure rclone is installed (rootless via user bin if needed)
- name: Ensure rclone is installed (ROOTLESS — no sudo; installs to ~/.local/bin)
block:
- name: rclone present?
ansible.builtin.command: rclone version
- name: rclone present on PATH or in ~/.local/bin?
ansible.builtin.shell: 'command -v rclone || command -v "$HOME/.local/bin/rclone"'
register: rc_ver
changed_when: false
failed_when: false
- name: Install rclone via official script (needs sudo)
ansible.builtin.shell: curl -fsSL https://rclone.org/install.sh | sudo bash
- name: Install rclone rootless (download static binary to ~/.local/bin)
when: rc_ver.rc != 0
block:
- name: Ensure ~/.local/bin exists
ansible.builtin.file:
path: "/home/{{ deploy_user }}/.local/bin"
state: directory
mode: "0755"
- name: Download + unpack latest rclone linux-amd64 into ~/.local/bin (rootless, python unzip)
ansible.builtin.shell: |
set -e
D="$(mktemp -d)"; cd "$D"
curl -fsSL https://downloads.rclone.org/rclone-current-linux-amd64.zip -o rclone.zip
python3 -c "import zipfile,glob,shutil,os,stat; z=zipfile.ZipFile('rclone.zip'); z.extractall('.'); b=glob.glob('rclone-*-linux-amd64/rclone')[0]; dst=os.path.expanduser('~/.local/bin/rclone'); shutil.copy(b,dst); os.chmod(dst, 0o755)"
changed_when: true
- name: Resolve rclone binary path (PATH or ~/.local/bin)
ansible.builtin.shell: 'command -v rclone || echo "/home/{{ deploy_user }}/.local/bin/rclone"'
register: rclone_bin_res
changed_when: false
- name: Set rclone binary fact
ansible.builtin.set_fact:
rclone_bin: "{{ rclone_bin_res.stdout_lines[0] }}"
- name: "Stop Homarr (consistent sqlite snapshot)"
community.docker.docker_compose_v2:
project_src: "{{ homarr_dir }}"
@ -192,7 +214,7 @@
- name: Upload tar to R2 (r2:<bucket>/homarr/<file>)
ansible.builtin.command:
cmd: rclone copyto "{{ backup_dir }}/{{ backup_name }}" "r2:{{ r2_bucket }}/homarr/{{ backup_name }}" --s3-no-check-bucket
cmd: "{{ rclone_bin }} copyto \"{{ backup_dir }}/{{ backup_name }}\" \"r2:{{ r2_bucket }}/homarr/{{ backup_name }}\" --s3-no-check-bucket"
environment: "{{ rclone_env }}"
register: upload
changed_when: true
@ -200,12 +222,29 @@
- name: Verify object exists in R2
ansible.builtin.command:
cmd: rclone lsf "r2:{{ r2_bucket }}/homarr/{{ backup_name }}"
cmd: "{{ rclone_bin }} lsf \"r2:{{ r2_bucket }}/homarr/{{ backup_name }}\""
environment: "{{ rclone_env }}"
register: verify
changed_when: false
failed_when: backup_name not in verify.stdout
- name: List existing Homarr backups in R2 for this host
ansible.builtin.command:
cmd: "{{ rclone_bin }} lsf \"r2:{{ r2_bucket }}/homarr/\""
environment: "{{ rclone_env }}"
register: r2_listing
changed_when: false
- name: Delete OLDER R2 backups for this host (keep only the one just uploaded)
ansible.builtin.command:
cmd: "{{ rclone_bin }} deletefile \"r2:{{ r2_bucket }}/homarr/{{ item }}\""
environment: "{{ rclone_env }}"
loop: "{{ r2_listing.stdout_lines }}"
when:
- item is match('homarr-' ~ inventory_hostname ~ '-.*\.tar$')
- item != backup_name
changed_when: true
- name: Prune old LOCAL tars (keep {{ keep_local }} newest)
ansible.builtin.shell: >-
ls -1t "{{ backup_dir }}"/homarr-*.tar 2>/dev/null | tail -n +{{ keep_local + 1 }} | xargs -r rm -f
@ -216,7 +255,8 @@
ansible.builtin.debug:
msg: >-
Backed up {{ backup_name }} ({{ (bkstat.stat.size / 1048576) | round(1) }} MB)
-> r2:{{ r2_bucket }}/homarr/ ; Homarr healthy (HTTP {{ health.status }}).
-> r2:{{ r2_bucket }}/homarr/ (older versions for {{ inventory_hostname }} deleted) ;
Homarr healthy (HTTP {{ health.status }}).
- name: "Cleanup runner temp key"
hosts: localhost