s3fs: allow turning the mounts off, off on asxpio-ops

On the 38 GB ops disk the s3fs cache reserve (ensure_diskfree) never
fit, so all three mounts failed at every boot since 2026-09-22. Backups
now go to Hetzner S3 with rclone instead.

Add s3fs_enabled (default true); when false the role unmounts the
buckets and drops their fstab entries, keeping the credentials file
that the rclone wrapper reads.

Assisted-by: Claude:opus-5
This commit is contained in:
Sergei Poljanski 2026-10-12 05:03:11 +04:00
commit 66ab6d8db3
3 changed files with 83 additions and 52 deletions

View file

@ -6,4 +6,7 @@
ssh_allow_public_git: true ssh_allow_public_git: true
ssh_git_user: git ssh_git_user: git
# Off: the cache reserve never fit the 38 GB disk, so the mounts failed at
# every boot. Backups go to Hetzner S3 with rclone instead.
s3fs_enabled: false
s3fs_ensure_diskfree: 20000 # Total:40GB Keep:20GB free = ~15GB for Cache s3fs_ensure_diskfree: 20000 # Total:40GB Keep:20GB free = ~15GB for Cache

View file

@ -9,6 +9,10 @@ s3_region: "hel1"
s3_access_key: "" s3_access_key: ""
s3_secret_key: "" s3_secret_key: ""
# false: no mounts. Unmounts and drops the fstab entries; the credentials
# file stays (backups use it with rclone, /root/backups/rclone-hetzner.sh).
s3fs_enabled: true
# S3 Buckets to mount (non-replication buckets only) # S3 Buckets to mount (non-replication buckets only)
s3_buckets: s3_buckets:
- name: asxpio-terraform-main - name: asxpio-terraform-main

View file

@ -32,65 +32,89 @@
owner: root owner: root
group: root group: root
- name: Create mount points for S3 buckets - name: Mount S3 buckets
ansible.builtin.file: when: s3fs_enabled | bool
path: "{{ item.mount_point }}" block:
state: directory - name: Create mount points for S3 buckets
mode: "{{ item.mode }}" ansible.builtin.file:
owner: "{{ item.owner }}" path: "{{ item.mount_point }}"
group: "{{ item.group }}" state: directory
mode: "{{ item.mode }}"
owner: "{{ item.owner }}"
group: "{{ item.group }}"
loop: "{{ s3_buckets }}"
loop_control:
label: "{{ item.name }} -> {{ item.mount_point }}"
- name: Add S3 buckets to /etc/fstab
ansible.builtin.lineinfile:
path: /etc/fstab
line: "{{ item.name }} {{ item.mount_point }} fuse.s3fs _netdev,{{ s3fs_options | join(',') }} 0 0"
regexp: "^{{ item.name }}\\s+{{ item.mount_point }}"
state: present
loop: "{{ s3_buckets }}"
loop_control:
label: "{{ item.name }} -> {{ item.mount_point }}"
- name: Mount all S3 buckets
ansible.builtin.command:
cmd: "mount {{ item.mount_point }}"
loop: "{{ s3_buckets }}"
loop_control:
label: "{{ item.name }} -> {{ item.mount_point }}"
register: mount_result
changed_when: mount_result.rc == 0
failed_when: false
- name: Verify S3 buckets are mounted
ansible.builtin.command:
cmd: "mountpoint -q {{ item.mount_point }}"
loop: "{{ s3_buckets }}"
loop_control:
label: "{{ item.name }} -> {{ item.mount_point }}"
register: verify_mount
changed_when: false
failed_when: verify_mount.rc != 0
- name: Display mounted S3 buckets
ansible.builtin.debug:
msg: |
✅ S3 Buckets mounted successfully:
{% for bucket in s3_buckets %}
- {{ bucket.name }} -> {{ bucket.mount_point }}
{% endfor %}
- name: Test write access to Immich bucket
ansible.builtin.copy:
content: "S3FS test file created on {{ ansible_date_time.iso8601 }}"
dest: "{{ s3_buckets | selectattr('name', 'equalto', 'asxpio-immich-main') | map(attribute='mount_point') | first }}/.s3fs-test"
mode: '0644'
when: "'asxpio-immich-main' in s3_buckets | map(attribute='name')"
register: write_test
- name: Remove test file
ansible.builtin.file:
path: "{{ s3_buckets | selectattr('name', 'equalto', 'asxpio-immich-main') | map(attribute='mount_point') | first }}/.s3fs-test"
state: absent
when: write_test is changed
- name: Unmount S3 buckets
ansible.builtin.command:
cmd: "umount {{ item.mount_point }}"
loop: "{{ s3_buckets }}" loop: "{{ s3_buckets }}"
loop_control: loop_control:
label: "{{ item.name }} -> {{ item.mount_point }}" label: "{{ item.mount_point }}"
register: umount_result
changed_when: umount_result.rc == 0
failed_when: false
when: not (s3fs_enabled | bool)
- name: Add S3 buckets to /etc/fstab - name: Remove S3 buckets from /etc/fstab
ansible.builtin.lineinfile: ansible.builtin.lineinfile:
path: /etc/fstab path: /etc/fstab
line: "{{ item.name }} {{ item.mount_point }} fuse.s3fs _netdev,{{ s3fs_options | join(',') }} 0 0" regexp: "^{{ item.name }}\\s+{{ item.mount_point }}\\s"
regexp: "^{{ item.name }}\\s+{{ item.mount_point }}"
state: present
loop: "{{ s3_buckets }}"
loop_control:
label: "{{ item.name }} -> {{ item.mount_point }}"
- name: Mount all S3 buckets
ansible.builtin.command:
cmd: "mount {{ item.mount_point }}"
loop: "{{ s3_buckets }}"
loop_control:
label: "{{ item.name }} -> {{ item.mount_point }}"
register: mount_result
changed_when: mount_result.rc == 0
failed_when: false
- name: Verify S3 buckets are mounted
ansible.builtin.command:
cmd: "mountpoint -q {{ item.mount_point }}"
loop: "{{ s3_buckets }}"
loop_control:
label: "{{ item.name }} -> {{ item.mount_point }}"
register: verify_mount
changed_when: false
failed_when: verify_mount.rc != 0
- name: Display mounted S3 buckets
ansible.builtin.debug:
msg: |
✅ S3 Buckets mounted successfully:
{% for bucket in s3_buckets %}
- {{ bucket.name }} -> {{ bucket.mount_point }}
{% endfor %}
- name: Test write access to Immich bucket
ansible.builtin.copy:
content: "S3FS test file created on {{ ansible_date_time.iso8601 }}"
dest: "{{ s3_buckets | selectattr('name', 'equalto', 'asxpio-immich-main') | map(attribute='mount_point') | first }}/.s3fs-test"
mode: '0644'
when: "'asxpio-immich-main' in s3_buckets | map(attribute='name')"
register: write_test
- name: Remove test file
ansible.builtin.file:
path: "{{ s3_buckets | selectattr('name', 'equalto', 'asxpio-immich-main') | map(attribute='mount_point') | first }}/.s3fs-test"
state: absent state: absent
when: write_test is changed loop: "{{ s3_buckets }}"
loop_control:
label: "{{ item.name }} -> {{ item.mount_point }}"
when: not (s3fs_enabled | bool)