fix(tasks): remove the btrfs subvolume of a deleted unix user

Deleting a user whose home is a btrfs subvolume left that subvolume behind. The role passed remove=true to the user
module, but userdel removes a home directory with rmdir, which refuses to delete a subvolume that still holds nested
subvolumes or is otherwise not empty. The home therefore survived the removal and blocked a later recreation of the
same user, because btrfs_subvolume then found the path already occupied.

The subvolume is now deleted explicitly by the same module that created it, which keeps the creation and the removal
symmetric. Snapshots are stored outside the subvolume, so a btrbk based backup keeps the data available even though
the home itself is gone.

The removal is skipped when the home directory no longer exists, since findmnt fails on a missing path.

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
2026-09-09 21:39:42 +02:00
co-authored by Copilot
parent f222b1c615
commit 5f757914be
2 changed files with 36 additions and 2 deletions
+32 -2
View File
@@ -1,7 +1,37 @@
---
- name: Remove unix user {{ unix_user.key }}
- name: "Define home directory for unix user: {{ unix_user.key }}"
ansible.builtin.set_fact:
_unix_users_home: "{{ unix_user.value.home | default('/home/' + unix_user.key) }}"
# userdel cannot remove a btrfs subvolume. Such a home is deleted afterwards via the btrfs_subvolume module.
- name: "Remove unix user: {{ unix_user.key }}"
ansible.builtin.user:
name: "{{ unix_user.key }}"
state: absent
remove: true
remove: "{{ not (unix_user.value.btrfs | default(false)) }}"
- name: "Remove btrfs home of unix user: {{ unix_user.key }}"
when: unix_user.value.btrfs is defined and
unix_user.value.btrfs
block:
- name: "Stat home directory"
ansible.builtin.stat:
path: "{{ _unix_users_home }}"
register: _unix_users_home_stat
# findmnt fails on a missing path, so the device is only determined as long as the home directory exists.
- name: "Delete btrfs subvolume of an existing home directory"
when: _unix_users_home_stat.stat.exists
block:
- name: "Find btrfs device"
ansible.builtin.command:
cmd: /bin/bash -c "findmnt -no SOURCE -T {{ _unix_users_home }} | sed 's/\[.*\]//'"
register: _unix_users_btrfs_device
changed_when: false
- name: "Delete btrfs subvolume: {{ _unix_users_home }}"
community.general.btrfs_subvolume:
filesystem_device: "{{ _unix_users_btrfs_device.stdout }}"
name: "{{ _unix_users_home }}"
state: absent