From 54e1e88a4e0c06aeaf358b1006e2fe4ce204332f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 3 Sep 2026 22:43:54 +0000 Subject: [PATCH 1/6] Add Aegis TPM-backed btrfs storage Co-authored-by: fscotto <17803710+fscotto@users.noreply.github.com> --- README.md | 7 +++- ansible/bootstrap/aegis.bu | 75 +++++++++++++++++++++++++++++++++++++- 2 files changed, 80 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e4b8e6a..c942289 100644 --- a/README.md +++ b/README.md @@ -117,12 +117,17 @@ ansible-playbook ansible/site.yml --limit prometheus \ ## Aegis `aegis` is a Raspberry Pi 4 running Fedora CoreOS. Provision it once with -`ansible/bootstrap/aegis.bu`, after replacing the SSH public-key placeholder: +`ansible/bootstrap/aegis.bu`, after replacing the SSH public-key placeholders: ```bash butane --strict --pretty --output aegis.ign ansible/bootstrap/aegis.bu ``` +The bootstrap reserves partition 5 on `/dev/mmcblk0` for `/var/lib`. On the first boot it +generates a random LUKS2 key, enrolls it in the attached TPM2 device, and formats the unlocked +volume as btrfs. This is destructive for that partition and requires a TPM2 module/device; a +Raspberry Pi 4 has no TPM onboard. The `core` and `pi` users both receive the configured SSH key. + The controller then manages it remotely as `core@aegis`; unlike local desktop profiles, Aegis is intentionally an SSH inventory target. `profile_aegis` manages rootful Podman Quadlets for AdGuard Home and iCloudPD, persistent data under `/var/lib`, the Podman auto-update timer, and diff --git a/ansible/bootstrap/aegis.bu b/ansible/bootstrap/aegis.bu index c283a11..ee052c3 100644 --- a/ansible/bootstrap/aegis.bu +++ b/ansible/bootstrap/aegis.bu @@ -1,5 +1,5 @@ # Bootstrap monouso per Fedora CoreOS su Aegis. -# Sostituire la chiave SSH prima di generare Ignition con butane --strict. +# Sostituire le chiavi SSH prima di generare Ignition con butane --strict. variant: fcos version: 1.6.0 passwd: @@ -7,10 +7,83 @@ passwd: - name: core ssh_authorized_keys: - "ssh-ed25519 CHANGEME_AEGIS_SSH_PUBLIC_KEY" + - name: pi + ssh_authorized_keys: + - "ssh-ed25519 CHANGEME_AEGIS_SSH_PUBLIC_KEY" storage: + disks: + - device: /dev/mmcblk0 + wipe_table: false + partitions: + - label: aegis-data + number: 5 + size_mib: 0 files: - path: /etc/hostname mode: 0644 contents: inline: | aegis + - path: /etc/crypttab + mode: 0644 + contents: + inline: | + aegis-data /dev/disk/by-partlabel/aegis-data - tpm2-device=auto + - path: /etc/fstab + mode: 0644 + contents: + inline: | + /dev/mapper/aegis-data /var/lib btrfs defaults,compress=zstd 0 0 + - path: /usr/local/sbin/aegis-storage-init + mode: 0750 + user: + name: root + group: + name: root + contents: + inline: | + #!/bin/bash + set -euo pipefail + + device=/dev/disk/by-partlabel/aegis-data + mapper=aegis-data + key_file=/run/aegis-storage/key + marker=/etc/aegis-storage.initialized + + if [[ -e "$marker" ]]; then + exit 0 + fi + + trap 'rm -f "$key_file"' EXIT + install -d -m 0700 /run/aegis-storage + dd if=/dev/urandom of="$key_file" bs=64 count=1 status=none + chmod 0600 "$key_file" + + cryptsetup luksFormat --batch-mode --type luks2 --key-file="$key_file" "$device" + systemd-cryptenroll --tpm2-device=auto --unlock-key-file="$key_file" "$device" + cryptsetup open --key-file="$key_file" "$device" "$mapper" + mkfs.btrfs -L aegis-data "/dev/mapper/$mapper" + mount "/dev/mapper/$mapper" /var/lib + touch "$marker" + + - path: /etc/systemd/system/aegis-storage-init.service + mode: 0644 + contents: + inline: | + [Unit] + Description=Initialize the TPM-backed Aegis data volume + Wants=systemd-udev-settle.service + After=systemd-udev-settle.service + Before=local-fs.target + ConditionPathExists=!/etc/aegis-storage.initialized + + [Service] + Type=oneshot + ExecStart=/usr/local/sbin/aegis-storage-init + + [Install] + WantedBy=local-fs-pre.target + systemd: + units: + - name: aegis-storage-init.service + enabled: true From 2004b48cf3fedaf65385c25cdae37b38e347a75f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 3 Sep 2026 22:44:21 +0000 Subject: [PATCH 2/6] Preserve existing Aegis filesystem tables Co-authored-by: fscotto <17803710+fscotto@users.noreply.github.com> --- ansible/bootstrap/aegis.bu | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/ansible/bootstrap/aegis.bu b/ansible/bootstrap/aegis.bu index ee052c3..2fbc9ce 100644 --- a/ansible/bootstrap/aegis.bu +++ b/ansible/bootstrap/aegis.bu @@ -27,13 +27,15 @@ storage: - path: /etc/crypttab mode: 0644 contents: - inline: | - aegis-data /dev/disk/by-partlabel/aegis-data - tpm2-device=auto + append: + - inline: | + aegis-data /dev/disk/by-partlabel/aegis-data - tpm2-device=auto - path: /etc/fstab mode: 0644 contents: - inline: | - /dev/mapper/aegis-data /var/lib btrfs defaults,compress=zstd 0 0 + append: + - inline: | + /dev/mapper/aegis-data /var/lib btrfs defaults,compress=zstd 0 0 - path: /usr/local/sbin/aegis-storage-init mode: 0750 user: From bc9b381525263eccfa41b66de8cc371feef3a078 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 3 Sep 2026 22:48:04 +0000 Subject: [PATCH 3/6] Remove unsupported Aegis TPM storage Co-authored-by: fscotto <17803710+fscotto@users.noreply.github.com> --- README.md | 7 ++-- ansible/bootstrap/aegis.bu | 72 -------------------------------------- 2 files changed, 2 insertions(+), 77 deletions(-) diff --git a/README.md b/README.md index c942289..2f66061 100644 --- a/README.md +++ b/README.md @@ -117,16 +117,13 @@ ansible-playbook ansible/site.yml --limit prometheus \ ## Aegis `aegis` is a Raspberry Pi 4 running Fedora CoreOS. Provision it once with -`ansible/bootstrap/aegis.bu`, after replacing the SSH public-key placeholders: +`ansible/bootstrap/aegis.bu`, after replacing the SSH public-key placeholder: ```bash butane --strict --pretty --output aegis.ign ansible/bootstrap/aegis.bu ``` -The bootstrap reserves partition 5 on `/dev/mmcblk0` for `/var/lib`. On the first boot it -generates a random LUKS2 key, enrolls it in the attached TPM2 device, and formats the unlocked -volume as btrfs. This is destructive for that partition and requires a TPM2 module/device; a -Raspberry Pi 4 has no TPM onboard. The `core` and `pi` users both receive the configured SSH key. +The `core` and `pi` users both receive the configured SSH key. The controller then manages it remotely as `core@aegis`; unlike local desktop profiles, Aegis is intentionally an SSH inventory target. `profile_aegis` manages rootful Podman Quadlets for AdGuard diff --git a/ansible/bootstrap/aegis.bu b/ansible/bootstrap/aegis.bu index 2fbc9ce..e3a7da3 100644 --- a/ansible/bootstrap/aegis.bu +++ b/ansible/bootstrap/aegis.bu @@ -11,81 +11,9 @@ passwd: ssh_authorized_keys: - "ssh-ed25519 CHANGEME_AEGIS_SSH_PUBLIC_KEY" storage: - disks: - - device: /dev/mmcblk0 - wipe_table: false - partitions: - - label: aegis-data - number: 5 - size_mib: 0 files: - path: /etc/hostname mode: 0644 contents: inline: | aegis - - path: /etc/crypttab - mode: 0644 - contents: - append: - - inline: | - aegis-data /dev/disk/by-partlabel/aegis-data - tpm2-device=auto - - path: /etc/fstab - mode: 0644 - contents: - append: - - inline: | - /dev/mapper/aegis-data /var/lib btrfs defaults,compress=zstd 0 0 - - path: /usr/local/sbin/aegis-storage-init - mode: 0750 - user: - name: root - group: - name: root - contents: - inline: | - #!/bin/bash - set -euo pipefail - - device=/dev/disk/by-partlabel/aegis-data - mapper=aegis-data - key_file=/run/aegis-storage/key - marker=/etc/aegis-storage.initialized - - if [[ -e "$marker" ]]; then - exit 0 - fi - - trap 'rm -f "$key_file"' EXIT - install -d -m 0700 /run/aegis-storage - dd if=/dev/urandom of="$key_file" bs=64 count=1 status=none - chmod 0600 "$key_file" - - cryptsetup luksFormat --batch-mode --type luks2 --key-file="$key_file" "$device" - systemd-cryptenroll --tpm2-device=auto --unlock-key-file="$key_file" "$device" - cryptsetup open --key-file="$key_file" "$device" "$mapper" - mkfs.btrfs -L aegis-data "/dev/mapper/$mapper" - mount "/dev/mapper/$mapper" /var/lib - touch "$marker" - - - path: /etc/systemd/system/aegis-storage-init.service - mode: 0644 - contents: - inline: | - [Unit] - Description=Initialize the TPM-backed Aegis data volume - Wants=systemd-udev-settle.service - After=systemd-udev-settle.service - Before=local-fs.target - ConditionPathExists=!/etc/aegis-storage.initialized - - [Service] - Type=oneshot - ExecStart=/usr/local/sbin/aegis-storage-init - - [Install] - WantedBy=local-fs-pre.target - systemd: - units: - - name: aegis-storage-init.service - enabled: true From 8d3f67885c2cffa42a31f14e4aff2db5d37cf171 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 3 Sep 2026 22:51:57 +0000 Subject: [PATCH 4/6] Configure Aegis pi Btrfs storage Co-authored-by: fscotto <17803710+fscotto@users.noreply.github.com> --- README.md | 5 +++-- ansible/bootstrap/aegis.bu | 19 ++++++++++++++++--- ansible/inventory/host_vars/aegis.yml | 2 +- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 2f66061..7e99dab 100644 --- a/README.md +++ b/README.md @@ -123,9 +123,10 @@ ansible-playbook ansible/site.yml --limit prometheus \ butane --strict --pretty --output aegis.ign ansible/bootstrap/aegis.bu ``` -The `core` and `pi` users both receive the configured SSH key. +The `pi` user receives the configured SSH key, and partition 5 on `/dev/mmcblk0` is formatted as +Btrfs and mounted at `/var/lib` on first boot. Formatting is destructive for that partition. -The controller then manages it remotely as `core@aegis`; unlike local desktop profiles, Aegis is +The controller then manages it remotely as `pi@aegis`; unlike local desktop profiles, Aegis is intentionally an SSH inventory target. `profile_aegis` manages rootful Podman Quadlets for AdGuard Home and iCloudPD, persistent data under `/var/lib`, the Podman auto-update timer, and `wake-ikaros`. Define `vault_aegis_icloudpd_apple_id` in Vault before applying it. iCloudPD still diff --git a/ansible/bootstrap/aegis.bu b/ansible/bootstrap/aegis.bu index e3a7da3..b26653e 100644 --- a/ansible/bootstrap/aegis.bu +++ b/ansible/bootstrap/aegis.bu @@ -4,13 +4,26 @@ variant: fcos version: 1.6.0 passwd: users: - - name: core - ssh_authorized_keys: - - "ssh-ed25519 CHANGEME_AEGIS_SSH_PUBLIC_KEY" - name: pi ssh_authorized_keys: - "ssh-ed25519 CHANGEME_AEGIS_SSH_PUBLIC_KEY" storage: + disks: + - device: /dev/mmcblk0 + wipe_table: false + partitions: + - label: aegis-data + number: 5 + size_mib: 0 + filesystems: + - device: /dev/disk/by-partlabel/aegis-data + format: btrfs + label: aegis-data + wipe_filesystem: false + mount: + path: /var/lib + options: + - compress=zstd files: - path: /etc/hostname mode: 0644 diff --git a/ansible/inventory/host_vars/aegis.yml b/ansible/inventory/host_vars/aegis.yml index d1e4a95..2232f68 100644 --- a/ansible/inventory/host_vars/aegis.yml +++ b/ansible/inventory/host_vars/aegis.yml @@ -1,7 +1,7 @@ --- ansible_host: aegis ansible_connection: ssh -ansible_user: core +ansible_user: pi ansible_become: true ansible_python_interpreter: /usr/bin/python3 From e92ff1c72921eb71a3f883e9edcf8fccb901aa14 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 3 Sep 2026 23:02:42 +0000 Subject: [PATCH 5/6] Mount Aegis Btrfs as root Co-authored-by: fscotto <17803710+fscotto@users.noreply.github.com> --- README.md | 3 ++- ansible/bootstrap/aegis.bu | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7e99dab..745bcb6 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,8 @@ butane --strict --pretty --output aegis.ign ansible/bootstrap/aegis.bu ``` The `pi` user receives the configured SSH key, and partition 5 on `/dev/mmcblk0` is formatted as -Btrfs and mounted at `/var/lib` on first boot. Formatting is destructive for that partition. +Btrfs and mounted as the root filesystem (`/`) on first boot. Formatting is destructive for that +partition. The controller then manages it remotely as `pi@aegis`; unlike local desktop profiles, Aegis is intentionally an SSH inventory target. `profile_aegis` manages rootful Podman Quadlets for AdGuard diff --git a/ansible/bootstrap/aegis.bu b/ansible/bootstrap/aegis.bu index b26653e..8b154b8 100644 --- a/ansible/bootstrap/aegis.bu +++ b/ansible/bootstrap/aegis.bu @@ -21,7 +21,7 @@ storage: label: aegis-data wipe_filesystem: false mount: - path: /var/lib + path: / options: - compress=zstd files: From 295f1a62ade544e74d3cbcf472a5be070df77a81 Mon Sep 17 00:00:00 2001 From: Fabio Scotto di Santolo Date: Fri, 4 Sep 2026 09:35:41 +0200 Subject: [PATCH 6/6] Handle Maven on Mise --- .../group_vars/workstation_dev_wsl.yml | 5 +++-- .../tasks/main.yml | 19 ++++++++++++++++--- .../.config/mise/config.toml | 1 + 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/ansible/inventory/group_vars/workstation_dev_wsl.yml b/ansible/inventory/group_vars/workstation_dev_wsl.yml index 3cc5843..d8dbbcd 100644 --- a/ansible/inventory/group_vars/workstation_dev_wsl.yml +++ b/ansible/inventory/group_vars/workstation_dev_wsl.yml @@ -8,9 +8,10 @@ workstation_dev_wsl_packages: - python3-pip - tmux -# Java 11 is no longer supplied by the Fedora repositories used by this WSL -# profile. Keep the JDK patch pinned; update this value deliberately. +# Java 11 and Maven are managed by Mise on this Fedora WSL profile. Keep their +# versions pinned; update them deliberately. workstation_mise_java_version: temurin-11.0.31+11 +workstation_mise_maven_version: 3.9.16 workstation_is_wsl: true workstation_wsl_systemd_enabled: true diff --git a/ansible/roles/profile_workstation_dev_wsl/tasks/main.yml b/ansible/roles/profile_workstation_dev_wsl/tasks/main.yml index e08d324..b835425 100644 --- a/ansible/roles/profile_workstation_dev_wsl/tasks/main.yml +++ b/ansible/roles/profile_workstation_dev_wsl/tasks/main.yml @@ -66,14 +66,27 @@ changed_when: false failed_when: false -- name: Install the pinned Java version with Mise - tags: [packages, mise, java, wsl] +- name: Check whether the pinned Maven version is installed with Mise + tags: [packages, mise, maven, wsl] + ansible.builtin.command: + cmd: "mise where maven@{{ workstation_mise_maven_version }}" + become_user: "{{ username }}" + environment: + HOME: "{{ user_home }}" + register: workstation_mise_maven_where + changed_when: false + failed_when: false + +- name: Install the pinned Mise tools + tags: [packages, mise, java, maven, wsl] ansible.builtin.command: cmd: mise install become_user: "{{ username }}" environment: HOME: "{{ user_home }}" - when: workstation_mise_java_where.rc != 0 + when: >- + workstation_mise_java_where.rc != 0 or + workstation_mise_maven_where.rc != 0 - name: Ensure WSL boot configuration file exists tags: [packages, services] diff --git a/dotfiles/workstation_dev_wsl/.config/mise/config.toml b/dotfiles/workstation_dev_wsl/.config/mise/config.toml index e452a0f..93944df 100644 --- a/dotfiles/workstation_dev_wsl/.config/mise/config.toml +++ b/dotfiles/workstation_dev_wsl/.config/mise/config.toml @@ -1,2 +1,3 @@ [tools] java = "temurin-11.0.31+11" +maven = "3.9.16"