From 0d29a9ae6218f656ebe21589b4a9da7de9664b82 Mon Sep 17 00:00:00 2001 From: Stefan Strobl Date: Wed, 24 Dec 2025 09:51:25 +0100 Subject: [PATCH] feat(disk): add phase 1 narrative for disk preparation modules Add literate programming phase 1 documentation for: - partitioning.sh: UEFI layout with ESP and encrypted root - encryption.sh: LUKS encryption strategy and key handling - filesystems.sh: filesystem choices and swap configuration - mounts.sh: mount tree preparation for installer handoff Decision: Swap file instead of swap partition for automatic encryption and flexibility. Swap partition would require either a second LUKS container (two passphrases at boot), unencrypted swap (security risk), or LVM (out of scope). Decision: /boot inside encrypted root for simplicity. GRUB unlocks LUKS once, kernel and initramfs are protected. ESP remains unencrypted per UEFI requirements. Decision: Default to btrfs with explicit ext4 opt-in. Btrfs provides snapshots and flexibility. Swap file on btrfs requires No-COW subvolume to avoid corruption. Trade-off: LUKS2 vs LUKS1. LUKS2 provides better security features and tooling, but GRUB <2.06 may have incomplete support. Users informed of potential boot issues with clear recovery path rather than silent downgrade. --- src/encryption.sh | 30 ++++++++++++++++++++++++++++++ src/filesystems.sh | 35 +++++++++++++++++++++++++++++++++++ src/mounts.sh | 24 ++++++++++++++++++++++++ src/partitioning.sh | 28 ++++++++++++++++++++++++++++ 4 files changed, 117 insertions(+) create mode 100644 src/encryption.sh create mode 100644 src/filesystems.sh create mode 100644 src/mounts.sh create mode 100644 src/partitioning.sh diff --git a/src/encryption.sh b/src/encryption.sh new file mode 100644 index 0000000..789ee6e --- /dev/null +++ b/src/encryption.sh @@ -0,0 +1,30 @@ +# === Motivation === +# Protect user data with full-disk encryption while keeping boot reliable. +# === Problem Statement === +# The wrapper must create and open an encrypted container for the root filesystem. +# === Scope === +# In scope: encryption mode selection, key handling policy, and naming conventions. +# Out of scope: specific encryption tool commands. +# === Concepts === +# LUKS version: compatibility trade-off between bootloader support and features. +# Mapping name: the identifier exposed for the opened container. +# === Decisions === +# Default to LUKS2 to benefit from improved security features and tooling. +# Never store passphrases in the script or config files. +# Support passphrase-only unlocks to keep the flow simple and auditable. +# Use default LUKS2 settings (PBKDF2 or Argon2i) for key derivation. +# If GRUB fails to unlock LUKS2 after installation, provide clear guidance to recreate with LUKS1. +# Do not auto-downgrade to LUKS1 silently; make the user aware of the compatibility issue. +# === Alternatives Considered === +# Unencrypted root rejected because it defeats the goal. +# Defaulting to LUKS1 rejected because LUKS2 improves maintainability and security tooling. +# Auto-detecting GRUB LUKS2 support rejected due to complexity and version fragmentation. +# === Constraints === +# Bootloader support limits available encryption features when /boot is inside encrypted root. +# GRUB versions before 2.06 may have incomplete LUKS2 support depending on distribution patches. +# === Open Questions === +# Should we allow users to customize LUKS2 PBKDF parameters (iterations, memory), or use defaults? +# How do we handle GRUB boot failures with LUKS2 - provide recovery instructions or force LUKS1? +# Should the wrapper test GRUB's ability to unlock LUKS2 before completing installation? +# === Success Criteria === +# The encrypted container opens reliably and is ready for filesystem creation. diff --git a/src/filesystems.sh b/src/filesystems.sh new file mode 100644 index 0000000..8315525 --- /dev/null +++ b/src/filesystems.sh @@ -0,0 +1,35 @@ +# === Motivation === +# Provide a stable filesystem base aligned with user intent. +# === Problem Statement === +# The wrapper must format the root and boot partitions using the selected filesystem. +# === Scope === +# In scope: filesystem options, defaults, and naming. +# Out of scope: exact formatting command flags. +# === Concepts === +# Root filesystem: primary data store inside the encrypted container. +# Boot filesystem: unencrypted partition for firmware and bootloader data. +# === Decisions === +# Default to btrfs with opt-in alternatives for users who want ext4. +# Ensure filesystem choices are explicit and confirmed before formatting. +# Use swap file instead of swap partition to keep layout simple and flexible. +# Swap file lives inside encrypted root for automatic encryption protection. +# Swap file size is chosen interactively based on system needs. +# For btrfs, swap file must reside on a No-COW subvolume to avoid corruption. +# === Alternatives Considered === +# Automatic detection of best filesystem rejected to keep behavior predictable. +# Swap partition rejected because it requires either: +# - Separate LUKS container (second passphrase at boot) +# - Unencrypted swap (security risk: sensitive data in swap) +# - LVM setup (out of scope for this wrapper) +# Swap partition also has fixed size, while swap file can be resized post-install. +# === Constraints === +# Filesystem choice must be compatible with the initramfs and bootloader. +# Hibernation with swap file requires kernel >= 5.0 and resume_offset parameter. +# For btrfs swap files, COW must be disabled on the swap subvolume. +# === Open Questions === +# Should btrfs subvolumes be created for root, home, and swap, or keep it flat? +# How should we handle swap file creation - in this phase or defer to post-install? +# Should we support configurable filesystem options (compression, mount flags)? +# === Success Criteria === +# Filesystems are prepared in the right places and match the chosen layout. +# Swap file is ready for activation and resides within encrypted root. diff --git a/src/mounts.sh b/src/mounts.sh new file mode 100644 index 0000000..11b0b89 --- /dev/null +++ b/src/mounts.sh @@ -0,0 +1,24 @@ +# === Motivation === +# Present a clean mount tree to the installer. +# === Problem Statement === +# The installer expects mounts to exist and should not reformat them. +# === Scope === +# In scope: mount points, ordering, and verification. +# Out of scope: mount command details. +# === Concepts === +# Mount tree: the hierarchy rooted at the target installation path. +# === Decisions === +# Mount root first, then boot-related partitions. +# Verify mounts before handing control to the installer. +# Default to mounting the ESP at /boot/efi for UEFI-first layouts. +# Keep /boot inside the encrypted root (no separate /boot mount by default). +# === Alternatives Considered === +# Letting the installer mount everything rejected because encryption requires pre-mount. +# === Constraints === +# Mount paths must align with the installer's expectations. +# === Open Questions === +# Should we verify mount points are writable before handing off to installer? +# How do we handle mount failures - retry, abort, or offer manual intervention? +# Should we mount with specific options (noatime, relatime) or use defaults? +# === Success Criteria === +# The installer sees a ready mount tree and skips formatting. diff --git a/src/partitioning.sh b/src/partitioning.sh new file mode 100644 index 0000000..e4e88b1 --- /dev/null +++ b/src/partitioning.sh @@ -0,0 +1,28 @@ +# === Motivation === +# Establish a predictable disk layout that supports encrypted root. +# === Problem Statement === +# We need a partition scheme that works for UEFI and leaves encryption boundaries clear. +# === Scope === +# In scope: layout choices, partition roles, and size policy. +# Out of scope: exact partitioning commands and tooling. +# === Concepts === +# EFI System Partition (ESP): unencrypted boot partition for UEFI. +# Root partition: the encrypted container for the main system. +# Separate boot partition: unencrypted /boot used only in alternative layouts. +# === Decisions === +# Keep ESP unencrypted to meet firmware requirements. +# Make root the only encrypted container by default to keep the flow simple. +# Use a UEFI-first layout with an ESP as the standard path. +# BIOS support is out of scope for this wrapper. +# Do not create a separate unencrypted /boot; /boot lives inside encrypted root. +# Default ESP size is 1G; root size is chosen interactively. +# === Alternatives Considered === +# Separate encrypted /home rejected for phase 1 due to complexity. +# === Constraints === +# Layout must remain compatible with the chosen bootloader. +# === Open Questions === +# Should we support GPT labels for partitions, or use default numeric identifiers? +# What partition alignment should we use for optimal SSD performance? +# Should ESP size be configurable, or keep the 1G default fixed? +# === Success Criteria === +# The layout supports boot and allows the installer to mount targets cleanly.