platform/platform-infra/ansible/roles/zfs/tasks/main.yml
Bart Van Geyt d715244b76 Phase 1: Ansible host baseline for Ubuntu VM
Idempotent host configuration targeting Ubuntu 24.04 with ZFS on a
dedicated second disk. Role-based platform-infra/ansible:

- base: apt packages, timezone, unattended security upgrades.
- zfs: install ZFS, create pool on a dedicated disk (guarded against
  wiping a non-empty disk), create platform datasets + customers parent
  per docs/03; docker dataset mounted at /var/lib/docker.
- docker: Docker Engine + Compose plugin, daemon.json written before first
  start so the native zfs storage driver initializes on the ZFS data-root;
  per-site network address pool preconfigured.
- firewall: nftables inbound default-deny in a dedicated table that never
  flushes Docker's rules; container outbound SMTP blocked via a DOCKER-USER
  jump applied by a systemd oneshot.
- ssh_hardening: key-first SSH with an anti-lockout assertion, config
  validation gate, and the sftponly group for Phase 4 SFTP accounts.

Includes ansible.cfg, requirements.yml, inventory example, group_vars with
safety notes, and a run guide. Real inventory (hosts.yml) is git-ignored.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 12:45:42 +02:00

64 lines
2.1 KiB
YAML

---
- name: Install ZFS userland + kernel module
ansible.builtin.apt:
name: zfsutils-linux
state: present
- name: Ensure the ZFS kernel module is loaded
community.general.modprobe:
name: zfs
state: present
# --- Pool creation (guarded & destructive) ----------------------------------
- name: Check whether the ZFS pool already exists
ansible.builtin.command: "zpool list -H -o name {{ zfs_pool_name }}"
register: zpool_check
changed_when: false
failed_when: false
- name: Record pool existence
ansible.builtin.set_fact:
zpool_exists: "{{ zpool_check.rc == 0 }}"
- name: Probe the target disk for existing data
ansible.builtin.command: "lsblk -nro FSTYPE,MOUNTPOINT,PARTTYPE {{ zfs_pool_disk }}"
register: disk_probe
changed_when: false
when: not zpool_exists
- name: Refuse to create a pool on a non-empty disk unless forced
ansible.builtin.assert:
that:
- (disk_probe.stdout | trim | length == 0) or zfs_pool_force
fail_msg: >-
{{ zfs_pool_disk }} appears to already contain data
({{ disk_probe.stdout | trim }}). Refusing to create the pool. Verify you
picked the right disk, then set zfs_pool_force=true to override.
when: not zpool_exists
- name: Create the ZFS pool on the dedicated disk
ansible.builtin.command: >-
zpool create {{ '-f ' if zfs_pool_force else '' }}-o ashift=12
-O compression={{ zfs_compression }}
-O atime=off
-O xattr=sa
-O acltype=posixacl
-O mountpoint=/{{ zfs_pool_name }}
{{ zfs_pool_name }} {{ zfs_pool_disk }}
when: not zpool_exists
# --- Datasets ---------------------------------------------------------------
- name: List existing datasets
ansible.builtin.command: "zfs list -H -o name"
register: zfs_existing
changed_when: false
- name: Create platform + customers datasets
ansible.builtin.command: >-
zfs create -p
{% if item.mountpoint is defined %}-o mountpoint={{ item.mountpoint }}{% endif %}
{{ zfs_pool_name }}/{{ item.path }}
loop: "{{ zfs_child_datasets }}"
loop_control:
label: "{{ zfs_pool_name }}/{{ item.path }}"
when: (zfs_pool_name ~ '/' ~ item.path) not in zfs_existing.stdout_lines