diff options
| -rw-r--r-- | Makefile | 8 | ||||
| -rw-r--r-- | README.org | 590 | ||||
| -rw-r--r-- | SESSION-CONTEXT.md | 168 | ||||
| -rwxr-xr-x | build.sh | 21 | ||||
| -rwxr-xr-x | custom/archsetup-zfs | 8 | ||||
| -rw-r--r-- | docs/NOTES.org | 26 | ||||
| -rwxr-xr-x | download-archzfs-iso.sh | 145 | ||||
| -rwxr-xr-x | scripts/boot-vm.sh | 2 | ||||
| -rwxr-xr-x | scripts/build-release | 207 | ||||
| -rwxr-xr-x | scripts/full-test.sh | 20 | ||||
| -rwxr-xr-x | scripts/sanity-test.sh | 69 | ||||
| -rwxr-xr-x | scripts/test-install.sh | 8 | ||||
| -rwxr-xr-x | scripts/test-vm.sh | 10 |
13 files changed, 217 insertions, 1065 deletions
@@ -40,11 +40,11 @@ release: test test-install @echo "==> Deploying ISO..." @# Move old ISOs to archive @mkdir -p archive - @mv -f archzfs-*.iso archive/ 2>/dev/null || true + @mv -f archangel-*.iso archive/ 2>/dev/null || true @# Copy new ISO to project root - @cp out/archzfs-*.iso . + @cp out/archangel-*.iso . @echo "==> Release complete:" - @ls -lh archzfs-*.iso + @ls -lh archangel-*.iso # Clean build artifacts clean: @@ -56,4 +56,4 @@ clean: # Clean everything including releases distclean: clean rm -rf archive - rm -f archzfs-*.iso + rm -f archangel-*.iso @@ -1,31 +1,40 @@ -#+TITLE: archzfs - Arch Linux ZFS Root Installation ISO +#+TITLE: archangel - Arch Linux ZFS/Btrfs Installation ISO #+AUTHOR: #+OPTIONS: toc:3 * Overview -archzfs is a custom Arch Linux ISO build system that creates a live environment -optimized for installing Arch Linux on ZFS root filesystems. It provides an -interactive installer with support for encrypted ZFS, multi-disk RAID +archangel is a custom Arch Linux ISO build system that creates a live environment +optimized for installing Arch Linux on ZFS or Btrfs root filesystems. It provides an +interactive installer with support for encrypted filesystems, multi-disk RAID configurations, and automatic snapshot management. -The ISO includes all necessary ZFS tools pre-loaded, eliminating the need for +The ISO includes all necessary tools pre-loaded, eliminating the need for manual module loading or package installation during the install process. * Features -- *ZFS Root Filesystem* - Full ZFS installation with native encryption -- *Multi-Disk RAID* - Support for mirror, stripe, raidz1/2/3 configurations -- *EFI Boot Redundancy* - GRUB installed on all disks for boot resilience +- *Dual Filesystem Support* - Choose ZFS or Btrfs during installation +- *Native Encryption* - ZFS encryption or LUKS2 for Btrfs +- *Multi-Disk RAID* - Mirror, stripe, raidz1/2/3 (ZFS) or RAID0/1/10 (Btrfs) +- *EFI Boot Redundancy* - Bootloader installed on all disks for resilience - *fzf-Based Interface* - Fuzzy search for timezone, locale, keymap, disk, RAID, and WiFi selection - *Genesis Snapshot* - Automatic pristine-state snapshot after installation -- *Rollback Script* - One-command factory reset via ~/root/rollback-to-genesis~ -- *Pre-Pacman Snapshots* - Automatic snapshots before package operations -- *Snapshot Retention* - Automatic pruning keeps disk usage bounded -- *GRUB Snapshot Boot* - Boot into any ZFS snapshot directly from GRUB menu +- *Snapshot Boot* - ZFSBootMenu (ZFS) or grub-btrfs (Btrfs) for booting snapshots - *NetworkManager* - WiFi configuration copied to installed system - *SSH Ready* - Optional SSH with root login for headless servers -- *LTS Kernel* - Uses linux-lts for stability with ZFS +- *LTS Kernel* - Uses linux-lts for stability + +** Filesystem Comparison + +| Feature | ZFS | Btrfs | +|---------+-----+-------| +| Bootloader | ZFSBootMenu | GRUB + grub-btrfs | +| Encryption | Native ZFS encryption | LUKS2 | +| Snapshots | zfs snapshot | snapper | +| Snapshot boot | Built into ZFSBootMenu | grub-btrfs menu | +| RAID support | mirror, raidz1/2/3, stripe | RAID0, RAID1, RAID10 | +| EFI size | 512MB | 1GB | * Quick Start @@ -40,7 +49,7 @@ sudo ./build.sh ./scripts/test-vm.sh --multi-disk #+END_SRC -Boot the ISO and run ~install-archzfs~ to start the installation. +Boot the ISO and run ~archangel~ to start the installation. * Prerequisites @@ -52,7 +61,7 @@ Boot the ISO and run ~install-archzfs~ to start the installation. ** Runtime Dependencies (included in ISO) - ZFS kernel modules (via zfs-dkms) -- GRUB with ZFS support +- Btrfs tools - NetworkManager - fzf for interactive selection @@ -67,17 +76,16 @@ sudo ./build.sh The build script will: 1. Copy the base Arch releng profile 2. Switch to linux-lts kernel -3. Add the archzfs repository -4. Add custom packages (ZFS, NetworkManager, fzf, etc.) -5. Copy the install-archzfs script +3. Add the archzfs repository (for ZFS packages) +4. Add custom packages (ZFS, Btrfs, NetworkManager, fzf, etc.) +5. Copy the archangel installer script 6. Build the ISO using mkarchiso ** Build Output -- ISO location: ~out/archzfs-vmlinuz-{version}-lts-YYYY-MM-DD-x86_64.iso~ -- Example: ~archzfs-vmlinuz-6.12.65-lts-2026-01-18-x86_64.iso~ +- ISO location: ~out/archangel-vmlinuz-{version}-lts-YYYY-MM-DD-x86_64.iso~ +- Example: ~archangel-vmlinuz-6.12.65-lts-2026-01-18-x86_64.iso~ - Build logs: visible in terminal output -- Build time: typically 5-15 minutes depending on cache ** Clean Rebuild @@ -89,25 +97,27 @@ sudo ./build.sh * Project Structure #+BEGIN_EXAMPLE -archzfs/ +archangel/ ├── build.sh # Main ISO build script ├── custom/ -│ ├── install-archzfs # Interactive installation script -│ ├── install-archzfs.conf.example # Example config for unattended install -│ ├── grub-zfs-snap # ZFS snapshot GRUB menu generator -│ ├── zfs-snap-prune # Snapshot retention/pruning script -│ ├── 40_zfs_snapshots # GRUB generator script (for /etc/grub.d/) -│ └── zz-grub-zfs-snap.hook # Pacman hook for auto-regeneration +│ ├── archangel # Interactive installation script +│ ├── archangel.conf.example # Example config for unattended install +│ ├── lib/ # Modular installer components +│ │ ├── common.sh # Shared utilities +│ │ ├── config.sh # Configuration handling +│ │ ├── disk.sh # Disk partitioning +│ │ ├── zfs.sh # ZFS-specific functions +│ │ └── btrfs.sh # Btrfs-specific functions +│ ├── zfssnapshot # ZFS snapshot utility +│ └── zfsrollback # ZFS rollback utility ├── scripts/ -│ └── test-vm.sh # QEMU test VM launcher -├── profile/ # archiso profile (generated during build) -│ ├── airootfs/ # Files copied to live ISO -│ │ └── usr/local/bin/ # Contains install-archzfs -│ ├── packages.x86_64 # Package list for ISO -│ └── pacman.conf # Pacman config with archzfs repo +│ ├── test-vm.sh # QEMU test VM launcher +│ ├── test-install.sh # Automated install tests +│ ├── sanity-test.sh # Quick ISO verification +│ └── build-release # Build and distribute ISO ├── vm/ # VM disk images (created by test-vm.sh) -├── work/ # Build working directory (created by build.sh) -├── out/ # Built ISO output (created by build.sh) +├── work/ # Build working directory +├── out/ # Built ISO output └── docs/ # Documentation #+END_EXAMPLE @@ -115,8 +125,8 @@ archzfs/ | Script | Description | |--------+-------------| -| ~build.sh~ | Builds the ISO. Copies releng profile, adds ZFS packages, configures kernel, runs mkarchiso | -| ~custom/install-archzfs~ | Interactive installer run on the live ISO. Handles disk partitioning, ZFS pool creation, base system install, bootloader setup | +| ~build.sh~ | Builds the ISO. Copies releng profile, adds packages, configures kernel, runs mkarchiso | +| ~custom/archangel~ | Interactive installer. Handles disk partitioning, filesystem creation, base system install, bootloader setup | | ~scripts/test-vm.sh~ | Launches QEMU VM for testing. Supports single and multi-disk configurations | * Testing with VMs @@ -132,7 +142,7 @@ This creates a 50GB virtual disk and boots the ISO. ** Multi-Disk RAID Test #+BEGIN_SRC bash -# Two 50GB disks (for mirror or stripe) +# Two 50GB disks (for mirror) ./scripts/test-vm.sh --multi-disk # Three 50GB disks (for raidz1) @@ -142,11 +152,11 @@ This creates a 50GB virtual disk and boots the ISO. ** SSH Access to VM #+BEGIN_SRC bash -# Password: archzfs +# Password: archangel ssh -p 2222 root@localhost # Or with sshpass -sshpass -p archzfs ssh -p 2222 root@localhost +sshpass -p archangel ssh -p 2222 root@localhost #+END_SRC ** Clean VM State @@ -161,99 +171,48 @@ sshpass -p archzfs ssh -p 2222 root@localhost ./scripts/test-vm.sh --boot-disk #+END_SRC -* Development Workflow - -** Iterative Testing with Genesis Rollback - -After completing an installation in the VM, you can rollback to the genesis -snapshot and re-test without reinstalling. This is useful for testing archsetup -or other post-install scripts. - -*** In the VM (after installation and reboot): - -#+BEGIN_SRC bash -# Rollback to pristine post-install state -/root/rollback-to-genesis - -# Reboot to apply -reboot -#+END_SRC - -*** From the host: - -#+BEGIN_SRC bash -# The VM disk retains the ZFS pool -# Just boot from disk again -./scripts/test-vm.sh --boot-disk -#+END_SRC - -** Updating the Install Script - -#+BEGIN_SRC bash -# Edit the script -vim custom/install-archzfs - -# Copy to a running VM for immediate testing -sshpass -p archzfs scp -P 2222 custom/install-archzfs root@localhost:/usr/local/bin/ - -# Or rebuild the ISO for fresh testing -sudo ./build.sh -#+END_SRC - * Installation Walkthrough -The ~install-archzfs~ script provides a guided installation with fzf-based +The ~archangel~ script provides a guided installation with fzf-based selection interfaces. ** Phase 1: Configuration Gathering -1. *Hostname* - System hostname -2. *Timezone* - Fuzzy search through all timezones (preview shows current time) -3. *Locale* - All locales available (preview shows format examples) -4. *Keymap* - Console keyboard layout -5. *Disk Selection* - Multi-select with TAB (preview shows disk details) -6. *RAID Level* - For multi-disk: mirror, stripe, raidz1/2/3 (preview shows capacity calculations) -7. *WiFi* - Scan and select network (preview shows signal/security) -8. *ZFS Passphrase* - Encryption passphrase (required at every boot) +1. *Filesystem* - Choose ZFS or Btrfs +2. *Hostname* - System hostname +3. *Timezone* - Fuzzy search through all timezones +4. *Locale* - All locales available +5. *Keymap* - Console keyboard layout +6. *Disk Selection* - Multi-select with TAB (preview shows disk details) +7. *RAID Level* - For multi-disk: mirror, stripe, raidz1/2/3 (ZFS) or RAID0/1/10 (Btrfs) +8. *Encryption* - Encryption passphrase (ZFS native or LUKS2) 9. *Root Password* - System root password 10. *SSH* - Enable SSH with root login (default: yes) ** Phase 2: Unattended Installation After configuration, the installation runs without intervention: -- Disk partitioning (EFI + ZFS on each disk) -- ZFS pool creation with encryption -- Dataset creation (ROOT, home, var, etc.) +- Disk partitioning (EFI + root on each disk) +- Filesystem creation with encryption +- Dataset/subvolume creation - Base system installation via pacstrap - System configuration (locale, timezone, hostname) -- Bootloader installation (GRUB on all EFI partitions) +- Bootloader installation (ZFSBootMenu or GRUB) - Genesis snapshot creation -** RAID Level Options - -| Disks | Available Options | -|-------+-------------------| -| 1 | Single (no RAID) | -| 2 | Mirror, Stripe | -| 3+ | Mirror, Stripe, RAIDZ1 | -| 4+ | Mirror, Stripe, RAIDZ1, RAIDZ2 | -| 5+ | Mirror, Stripe, RAIDZ1, RAIDZ2, RAIDZ3 | - * Unattended Installation -For automated or headless installations, use a config file to provide all -configuration values upfront. The installer will run without any user -interaction. +For automated or headless installations, use a config file. ** Using a Config File #+BEGIN_SRC bash # Copy and edit the example config -cp /root/install-archzfs.conf.example /root/my-install.conf +cp /root/archangel.conf.example /root/my-install.conf vim /root/my-install.conf # Run with config file -install-archzfs --config-file /root/my-install.conf +archangel --config-file /root/my-install.conf #+END_SRC *Important*: The config file is ONLY used when explicitly specified with @@ -262,118 +221,19 @@ to prevent accidental disk destruction. ** Config File Reference -Example config file (~install-archzfs.conf.example~ is included on the ISO): - -#+BEGIN_SRC bash -############################# -# System Configuration -############################# - -# Hostname for the installed system (required) -HOSTNAME=archzfs - -# Timezone (required) - Use format: Region/City -# Examples: America/Los_Angeles, Europe/London, Asia/Tokyo -TIMEZONE=America/Los_Angeles - -# Locale (optional, default: en_US.UTF-8) -LOCALE=en_US.UTF-8 - -# Console keymap (optional, default: us) -KEYMAP=us - -############################# -# Disk Configuration -############################# - -# Disks to use for installation (required) -# Single disk: DISKS=/dev/vda -# Multiple disks: DISKS=/dev/vda,/dev/vdb,/dev/vdc -DISKS=/dev/vda - -# RAID level for multi-disk setups (optional) -# Options: mirror, stripe, raidz1, raidz2, raidz3 -# Default: mirror (when multiple disks specified) -# Leave empty for single disk -RAID_LEVEL= - -############################# -# Security -############################# - -# ZFS encryption passphrase (required) -# This will be required at every boot to unlock the pool -ZFS_PASSPHRASE=changeme - -# Root password (required) -ROOT_PASSWORD=changeme - -############################# -# Network Configuration -############################# - -# Enable SSH with root login (optional, default: yes) -# Set to "no" to disable SSH -ENABLE_SSH=yes - -# WiFi configuration (optional) -# Leave empty for ethernet-only or to skip WiFi setup -WIFI_SSID= -WIFI_PASSWORD= -#+END_SRC - -** Required vs Optional Fields - | Field | Required | Default | Description | |-------+----------+---------+-------------| +| ~FILESYSTEM~ | No | zfs | Filesystem type (zfs or btrfs) | | ~HOSTNAME~ | Yes | - | System hostname | | ~TIMEZONE~ | Yes | - | Timezone (Region/City format) | | ~DISKS~ | Yes | - | Comma-separated disk paths | -| ~ZFS_PASSPHRASE~ | Yes | - | ZFS encryption passphrase | +| ~ZFS_PASSPHRASE~ | Yes* | - | Encryption passphrase (*if not NO_ENCRYPT) | | ~ROOT_PASSWORD~ | Yes | - | Root user password | | ~LOCALE~ | No | en_US.UTF-8 | System locale | | ~KEYMAP~ | No | us | Console keyboard layout | | ~RAID_LEVEL~ | No | mirror | RAID type for multi-disk | | ~ENABLE_SSH~ | No | yes | Enable SSH server | -| ~WIFI_SSID~ | No | - | WiFi network name | -| ~WIFI_PASSWORD~ | No | - | WiFi password | - -** Example Configurations - -*** Single Disk Server - -#+BEGIN_SRC bash -HOSTNAME=webserver -TIMEZONE=UTC -DISKS=/dev/sda -ZFS_PASSPHRASE=MySecurePass123 -ROOT_PASSWORD=RootPass456 -ENABLE_SSH=yes -#+END_SRC - -*** Two-Disk Mirror (Recommended for Servers) - -#+BEGIN_SRC bash -HOSTNAME=fileserver -TIMEZONE=America/New_York -DISKS=/dev/sda,/dev/sdb -RAID_LEVEL=mirror -ZFS_PASSPHRASE=MySecurePass123 -ROOT_PASSWORD=RootPass456 -ENABLE_SSH=yes -#+END_SRC - -*** Three-Disk RAIDZ1 - -#+BEGIN_SRC bash -HOSTNAME=storage -TIMEZONE=Europe/London -DISKS=/dev/sda,/dev/sdb,/dev/sdc -RAID_LEVEL=raidz1 -ZFS_PASSPHRASE=MySecurePass123 -ROOT_PASSWORD=RootPass456 -ENABLE_SSH=yes -#+END_SRC +| ~NO_ENCRYPT~ | No | no | Skip encryption (testing only) | * Bare Metal Installation @@ -381,290 +241,66 @@ ENABLE_SSH=yes #+BEGIN_SRC bash # Write ISO to USB drive (replace /dev/sdX) -sudo dd if=out/archzfs-vmlinuz-*.iso of=/dev/sdX bs=4M status=progress oflag=sync +sudo dd if=out/archangel-vmlinuz-*.iso of=/dev/sdX bs=4M status=progress oflag=sync #+END_SRC ** Booting 1. Boot from USB (may need to disable Secure Boot) 2. Wait for live environment to load -3. Run ~install-archzfs~ - -** WiFi Setup - -The installer will scan for WiFi networks and present them in fzf. -Select your network and enter the password. The connection is tested -before proceeding and will be copied to the installed system. +3. Run ~archangel~ -** SSH Access After Reboot +** Post-Reboot -If you enabled SSH during installation: -1. The system will have NetworkManager enabled -2. WiFi credentials are copied from the live environment -3. SSH is enabled with root password login -4. Connect via: ~ssh root@<ip-address>~ +*** ZFS Systems +1. Enter ZFS encryption passphrase at ZFSBootMenu prompt +2. Select boot environment (or wait for default) +3. Log in as root -*Important*: Harden SSH after first login (disable password auth, use keys). - -** Post-Reboot Steps - -1. Enter ZFS encryption passphrase at boot -2. Log in as root -3. Run ~archsetup~ for further configuration +*** Btrfs Systems +1. GRUB menu appears +2. Enter LUKS passphrase when prompted +3. Log in as root * Post-Installation -** ZFS Snapshot Boot Entries (grub-zfs-snap) - -The installer configures GRUB to display bootable ZFS snapshots in the boot menu. -This allows you to boot directly into a previous system state without manually -rolling back. - -*** How It Works - -- A GRUB submenu "ZFS Snapshots" appears in the boot menu -- Shows up to 10 most recent snapshots of the root dataset -- Selecting a snapshot boots the system in read-only mode from that snapshot -- The running system sees the snapshot's files, but changes go to a temporary overlay - -*** When Snapshots Appear in GRUB - -The GRUB menu is automatically updated: -- After kernel updates (~linux-lts~) -- After ZFS package updates (~zfs-dkms~, ~zfs-utils~) -- After GRUB updates -- After any kernel module installation - -*** Manual Snapshot Management +** ZFS Snapshot Management #+BEGIN_SRC bash -# Create a snapshot before making changes -zfs snapshot zroot/ROOT/default@before-experiment +# Create a snapshot +zfssnapshot "before-experiment" -# Regenerate GRUB menu to include new snapshot -grub-zfs-snap +# Interactive rollback with fzf +zfsrollback -# List snapshots that will appear in GRUB -grub-zfs-snap --list +# List snapshots +zfs list -t snapshot #+END_SRC -*** Customization - -Environment variables control behavior: +** Btrfs Snapshot Management #+BEGIN_SRC bash -# Change pool name (default: zroot) -POOL_NAME=mypool grub-zfs-snap +# Create a snapshot (via snapper) +snapper -c root create -d "before-experiment" -# Change root dataset (default: ROOT/default) -ROOT_DATASET=ROOT/arch grub-zfs-snap +# List snapshots +snapper -c root list -# Show more snapshots in menu (default: 10) -MAX_SNAPSHOTS=20 grub-zfs-snap +# Rollback (requires reboot) +snapper -c root rollback <number> #+END_SRC -*** Booting from a Snapshot - -1. Reboot and select "ZFS Snapshots" from GRUB menu -2. Choose the desired snapshot by date/name -3. System boots with that snapshot's root filesystem -4. Files are read-only - to make permanent, rollback from normal boot - ** Genesis Snapshot -The installer creates a recursive snapshot of the entire pool named ~genesis~. -This represents the pristine post-install state. +Both filesystems create a "genesis" snapshot after installation, representing +the pristine post-install state. #+BEGIN_SRC bash -# View genesis snapshots +# ZFS: View genesis snapshot zfs list -t snapshot | grep genesis -#+END_SRC -** Rollback to Factory State - -#+BEGIN_SRC bash -# Interactive rollback with confirmation -/root/rollback-to-genesis - -# Reboot to apply -reboot -#+END_SRC - -*Warning*: This destroys all changes since installation! - -** Useful ZFS Commands - -#+BEGIN_SRC bash -# List all snapshots -zfs list -t snapshot - -# Create manual snapshot -zfs snapshot zroot/home@my-backup - -# Rollback to snapshot -zfs rollback zroot/home@my-backup - -# Pool status -zpool status - -# Pool usage -zpool list -#+END_SRC - -** Snapshot Retention Policy - -The system automatically prunes old snapshots to prevent unbounded disk usage. - -*** Retention Rules - -| Rule | Description | -|------+-------------| -| Keep 20 most recent | Always preserved regardless of age | -| Delete if >180 days | Snapshots beyond position 20, older than 6 months | -| Genesis protected | Never deleted, regardless of position or age | - -*** How It Works - -Pruning runs automatically: -- *After every pacman operation* - Pre-pacman hook triggers prune after creating new snapshot -- *Daily via systemd timer* - Catches any missed pruning, syncs GRUB menu - -*** Manual Pruning - -#+BEGIN_SRC bash -# Preview what would be deleted -zfs-snap-prune --dry-run - -# Run with verbose output -zfs-snap-prune --verbose - -# Check current snapshots -zfs-snap-prune --help -#+END_SRC - -*** Customizing Retention - -Set environment variables before running: - -#+BEGIN_SRC bash -# Keep more snapshots (default: 20) -KEEP_COUNT=50 zfs-snap-prune - -# Shorter retention period (default: 180 days) -MAX_AGE_DAYS=90 zfs-snap-prune - -# Different pool/dataset -POOL_NAME=tank ROOT_DATASET=ROOT/arch zfs-snap-prune -#+END_SRC - -To change defaults permanently, edit ~/usr/local/bin/zfs-snap-prune~. - -*** Example: One Year of Use - -With weekly pacman updates (~52/year) plus genesis: -- Total snapshots created: ~53 -- Snapshots kept: ~27 (20 recent + ~6 within 180 days + genesis) -- Snapshots pruned: ~26 (older than 180 days, beyond position 20) - -* Keeping Up-to-Date - -** Kernel Updates on Installed Systems - -The installed system uses *zfs-dkms* which builds ZFS modules from source. This -means kernel updates work automatically: - -1. *Pacman installs new kernel* - ~linux-lts~ update via pacman/topgrade -2. *DKMS hook triggers* - Automatically compiles ZFS for the new kernel -3. *mkinitcpio hook triggers* - Regenerates initramfs with new ZFS modules -4. *Reboot* - System boots with new kernel and matching ZFS modules - -*** Why DKMS? - -| Approach | Pros | Cons | -|----------+------+------| -| ~zfs-dkms~ (what we use) | Always compatible, builds for any kernel | Slower updates (compile time) | -| ~zfs-linux-lts~ (prebuilt) | Fast updates | Must wait for archzfs to release matching version | - -We use DKMS because it guarantees compatibility - you're never stuck waiting -for the archzfs maintainers to release a new package. - -*** Verify After Kernel Update - -#+BEGIN_SRC bash -# Check ZFS module matches running kernel -uname -r # Current kernel version -modinfo zfs | grep vermagic # ZFS module version - -# These should show the same kernel version -#+END_SRC - -*** If Something Goes Wrong - -If a kernel update breaks ZFS (rare with LTS kernel): - -#+BEGIN_SRC bash -# Boot from archzfs ISO -# Import the pool -zpool import -f zroot - -# Enter passphrase when prompted, then mount -zfs mount -a -mount /dev/vda1 /mnt/boot # EFI partition - -# Chroot and fix -arch-chroot /mnt - -# Option 1: Rebuild DKMS modules -dkms autoinstall -mkinitcpio -P - -# Option 2: Rollback to previous snapshot -# (exit chroot first) -/mnt/root/rollback-to-genesis -#+END_SRC - -*** Pre-Pacman Snapshots - -The installer configures automatic snapshots before every pacman operation. -If a kernel update causes issues, you can rollback: - -#+BEGIN_SRC bash -# List recent snapshots -zfs list -t snapshot -o name,creation | grep ROOT - -# Rollback to pre-update snapshot -zfs rollback zroot/ROOT/default@autosnap_YYYY-MM-DD_HH:MM:SS -reboot -#+END_SRC - -** Rebuilding the ISO - -Rebuild the ISO when: -- New Linux LTS kernel is released (for new installations) -- New ZFS version is released -- You've made changes to install-archzfs -- archzfs repository packages are updated - -*** Rebuild Process - -#+BEGIN_SRC bash -# Clean and rebuild -sudo rm -rf work out -sudo ./build.sh -#+END_SRC - -The build automatically pulls the latest packages from: -- Official Arch repositories -- archzfs repository (https://archzfs.com) - -*** Checking for Updates - -#+BEGIN_SRC bash -# Check current linux-lts version in repos -pacman -Si linux-lts | grep Version - -# Check archzfs package versions -curl -s https://archzfs.com/archzfs/x86_64/ | grep -o 'zfs-linux-lts-[^"]*' +# Btrfs: View genesis snapshot +snapper -c root list | grep genesis #+END_SRC * Troubleshooting @@ -682,7 +318,6 @@ sudo ./build.sh The ISO includes DKMS-built ZFS modules. If modules fail to load: - Check ~dmesg | grep -i zfs~ for errors - Ensure you're using the LTS kernel -- The archzfs repo may be out of sync with kernel updates (wait for update) ** Disk Not Showing in Selection @@ -690,31 +325,24 @@ The ISO includes DKMS-built ZFS modules. If modules fail to load: - Check ~lsblk~ to verify disk visibility - USB drives may need a moment to be detected -** WiFi Networks Not Found - -- Verify WiFi hardware is present: ~ip link~ -- In VMs, there is no WiFi adapter (expected) -- Try rescanning: ~nmcli device wifi rescan~ - ** Boot Fails After Installation +*** ZFS +- Check ZFSBootMenu appears (if not, check EFI boot order with ~efibootmgr~) +- Verify pool can import: boot ISO, ~zpool import -f zroot~ + +*** Btrfs - Verify EFI boot entries: ~efibootmgr -v~ - Check GRUB config: ~/boot/grub/grub.cfg~ -- Ensure ZFS modules in initramfs: ~lsinitcpio /boot/initramfs-linux-lts.img | grep zfs~ - -** Encryption Passphrase Not Accepted - -- Keyboard layout at boot is US by default -- Passphrase is case-sensitive -- Check for num-lock state * Links - [[https://archzfs.com][archzfs Repository]] - ZFS packages for Arch Linux - [[https://openzfs.github.io/openzfs-docs/][OpenZFS Documentation]] - Official ZFS documentation -- [[https://wiki.archlinux.org/title/ZFS][Arch Wiki - ZFS]] - Arch-specific ZFS information -- [[https://wiki.archlinux.org/title/Archiso][Arch Wiki - Archiso]] - Building custom Arch ISOs -- [[https://github.com/openzfs/zfs][OpenZFS on GitHub]] - ZFS source code +- [[https://get.zfsbootmenu.org][ZFSBootMenu]] - ZFS boot manager +- [[https://wiki.archlinux.org/title/Btrfs][Arch Wiki - Btrfs]] - Btrfs information +- [[https://wiki.archlinux.org/title/Snapper][Arch Wiki - Snapper]] - Btrfs snapshot management +- [[https://github.com/Antynea/grub-btrfs][grub-btrfs]] - Boot Btrfs snapshots from GRUB * License diff --git a/SESSION-CONTEXT.md b/SESSION-CONTEXT.md deleted file mode 100644 index cb1bbb7..0000000 --- a/SESSION-CONTEXT.md +++ /dev/null @@ -1,168 +0,0 @@ -# Session Context - 2026-01-19 - -## Summary -Major session: Added ZFS snapshot scripts, fixed grub-zfs-snap, created fully automated build-release workflow with sanity testing. - -## Key Accomplishments - -### 1. ZFS Snapshot Management Scripts -- Copied `zfssnapshot` and `zfsrollback` from archsetup to archzfs ISO -- Scripts now installed to `/usr/local/bin/` on live ISO and target systems -- Added `fzf` to `install-archzfs` pacstrap (required by zfsrollback) -- Fixed zfsrollback fzf height (40% → 70%) -- Fixed zfsrollback to sort datasets by depth (children before parents) for proper rollback order -- Created task in archsetup inbox to remove duplicate scripts - -### 2. Fixed grub-zfs-snap Syntax Error -- **Bug:** `\$(grub-probe ...)` wrote literal string to grub.cfg -- **Fix:** Removed backslash so command executes at config generation time -- **File:** `custom/grub-zfs-snap` line 106 -- GRUB doesn't support bash-style `$()` command substitution - -### 3. Automated Sanity Test (`scripts/sanity-test.sh`) -- Boots ISO in headless QEMU (no display) -- Waits for SSH availability (port 2223, timeout 180s) -- Runs 13 automated tests via SSH: - - ZFS module loaded - - ZFS/zpool commands work - - Custom scripts present (zfsrollback, zfssnapshot, grub-zfs-snap, etc.) - - fzf installed - - LTS kernel running - - archsetup directory present -- Reports pass/fail summary -- Fully automated - no human input required - -### 4. Build-Release Workflow (`scripts/build-release`) -Complete automated workflow for ISO build and distribution: - -**Usage:** -```bash -sudo ./scripts/build-release # Full: build, test, distribute -sudo ./scripts/build-release --yes # Full with auto-confirm dd -sudo ./scripts/build-release --skip-build --skip-test --yes # Just distribute -``` - -**Options:** -- `--skip-build` - Skip ISO build, use existing -- `--skip-test` - Skip sanity test -- `--yes, -y` - Auto-confirm dd to ARCHZFS drive - -**Distribution Targets:** -1. `~/Downloads/isos/` (always) -2. `truenas.local:/mnt/vault/isos/` (via cjennings@, checks reachable) -3. ARCHZFS labeled drive (detected via `blkid -L ARCHZFS`, writes via dd) -4. Ventoy drive (detected by label "Ventoy" or ventoy/ directory) - -**Key Fixes:** -- Uses `SUDO_USER` to get real user's home (not /root) -- SSH/SCP runs as real user to use their SSH keys -- Uses `cjennings@truenas.local` (not root) -- No removable check for ARCHZFS (Framework expansion cards show as internal) -- Graceful handling of failures (warns and continues) - -### 5. Added eBPF Tracing Tools -- Added to ISO: `bpftrace`, `bcc-tools`, `perf`, `w3m` -- Updated RESCUE-GUIDE.txt with sections 9 (System Tracing) and 10 (Terminal Web Browsing) - -## Technical Notes - -### os-prober Warning -``` -Warning: os-prober will not be executed to detect other bootable partitions. -``` -- Disabled by default since GRUB 2.06 for security -- Not needed for single-OS ZFS systems -- To enable: Add `GRUB_DISABLE_OS_PROBER=false` to `/etc/default/grub` - -### Genesis Snapshot Best Practice -Scripts must be part of genesis snapshot to survive rollback: -1. `install-archzfs` installs zfssnapshot, zfsrollback, fzf -2. These exist before genesis snapshot is taken -3. Future rollbacks preserve the tools - -### Framework Laptop Note -Expansion card drives show as internal (RM=0) but are hot-swappable. -Don't check for removable flag when detecting ARCHZFS drives. - -### Ratio Machine -- Host: ratio (192.168.86.48) -- Login: root / welcome -- Scripts deployed: zfssnapshot, zfsrollback, grub-zfs-snap, fzf - -### Cogito Machine (Build Host) -- Framework Desktop ML with AMD Ryzen AI MAX+ 395 -- Specs in `assets/cogito-hardware-specs.txt` - -## Files Modified/Created This Session - -**New Files:** -- `scripts/sanity-test.sh` - Automated ISO testing -- `scripts/build-release` - Build and distribution workflow -- `custom/zfssnapshot` - ZFS snapshot creation -- `custom/zfsrollback` - Interactive ZFS rollback -- `assets/cogito-hardware-specs.txt` - Build machine specs -- `/home/cjennings/code/archsetup/inbox/remove-zfs-scripts.md` - Task for archsetup - -**Modified Files:** -- `custom/grub-zfs-snap` - Fixed syntax error -- `custom/install-archzfs` - Added fzf to pacstrap -- `custom/RESCUE-GUIDE.txt` - Added tracing/browser sections -- `build.sh` - Added bpftrace, bcc-tools, perf, w3m, zfs script copies -- `TODO.org` - Updated tasks - -## Commits This Session -``` -d0e76f0 Add --yes flag for fully automated distribution -2c261bc Update build-release for TrueNAS and Framework drives -c68e550 Fix build-release for running with sudo -d3eaaff Add automated sanity test for ISO verification -5eba633 Fix zfsrollback to process children before parents -4e7e3fe Fix grub-zfs-snap command substitution syntax error -ee668df Increase fzf height in zfsrollback to 70% -7c0d655 Add fzf to target system packages -156dde5 Add zfssnapshot and zfsrollback scripts to ISO -e924c53 Add TODO for zfsrollback and zfssnapshot scripts -d2c2cca Add eBPF tracing tools and w3m terminal browser -66c92a2 Add session context for 2026-01-19 -c719d45 Add build-release script for ISO build and distribution -``` - -## Final Distribution (This Session) -``` -ISO: archzfs-vmlinuz-6.12.66-lts-2026-01-19-x86_64.iso (5.2GB) - -Distributed to: - ✓ /home/cjennings/Downloads/isos/ - ✓ truenas.local:/mnt/vault/isos/ - ✓ /dev/sda (ARCHZFS boot drive) - ✓ /dev/sdb1 (Ventoy) -``` - -## Pending/Future Work -- User should run archsetup on ratio after genesis rollback -- archsetup inbox task: remove duplicate zfssnapshot/zfsrollback scripts - -## Session 2026-01-19 (continued) - -### Added --full-test to build-release - -Created comprehensive installation test framework: - -**New File: `scripts/full-test.sh`** -- Automated installation testing for all disk configurations -- Tests: single-disk, mirror (2 disks), raidz1 (3 disks) -- Each test: boots ISO, runs unattended install, reboots, verifies ZFS health -- Options: `--quick` (single-disk only), `--verbose` -- Runs sanity-test.sh first, then install tests - -**Modified: `scripts/build-release`** -- Added `--full-test` option -- When specified, runs full-test.sh instead of sanity-test.sh -- Usage: `sudo ./scripts/build-release --full-test` - -**Usage:** -```bash -sudo ./scripts/build-release # Sanity test only (fast) -sudo ./scripts/build-release --full-test # All install tests (~30-45 min) -sudo ./scripts/build-release --skip-test # No testing -``` @@ -14,7 +14,7 @@ OUT_DIR="$SCRIPT_DIR/out" CUSTOM_DIR="$SCRIPT_DIR/custom" # Live ISO root password (for SSH access during testing/emergencies) -LIVE_ROOT_PASSWORD="archzfs" +LIVE_ROOT_PASSWORD="archangel" # Colors for output RED='\033[0;31m' @@ -161,7 +161,7 @@ linux-lts-headers wget networkmanager -# mDNS for network discovery (ssh root@archzfs.local) +# mDNS for network discovery (ssh root@archangel.local) avahi nss-mdns @@ -222,6 +222,7 @@ fsarchiver partimage xfsprogs btrfs-progs +snapper f2fs-tools exfatprogs ncdu @@ -267,12 +268,12 @@ info "LTS Kernel version: $KERNEL_VER" # Update profiledef.sh with our ISO name info "Updating ISO metadata..." -# Format: archzfs-vmlinuz-6.12.65-lts-2026-01-18-x86_64.iso +# Format: archangel-vmlinuz-6.12.65-lts-2026-01-18-x86_64.iso ISO_DATE=$(date +%Y-%m-%d) -sed -i "s/^iso_name=.*/iso_name=\"archzfs-vmlinuz-${KERNEL_VER}-lts\"/" "$PROFILE_DIR/profiledef.sh" +sed -i "s/^iso_name=.*/iso_name=\"archangel-vmlinuz-${KERNEL_VER}-lts\"/" "$PROFILE_DIR/profiledef.sh" sed -i "s/^iso_version=.*/iso_version=\"${ISO_DATE}\"/" "$PROFILE_DIR/profiledef.sh" # Fixed label for stable GRUB boot entry (default is date-based ARCH_YYYYMM) -sed -i "s/^iso_label=.*/iso_label=\"ARCHZFS\"/" "$PROFILE_DIR/profiledef.sh" +sed -i "s/^iso_label=.*/iso_label=\"ARCHANGEL\"/" "$PROFILE_DIR/profiledef.sh" # Create airootfs directories mkdir -p "$PROFILE_DIR/airootfs/usr/local/bin" @@ -284,20 +285,20 @@ info "Enabling SSH on live ISO..." ln -sf /usr/lib/systemd/system/sshd.service \ "$PROFILE_DIR/airootfs/etc/systemd/system/multi-user.target.wants/sshd.service" -# Enable Avahi mDNS for network discovery (ssh root@archzfs.local) +# Enable Avahi mDNS for network discovery (ssh root@archangel.local) info "Enabling Avahi mDNS..." ln -sf /usr/lib/systemd/system/avahi-daemon.service \ "$PROFILE_DIR/airootfs/etc/systemd/system/multi-user.target.wants/avahi-daemon.service" -# Set hostname to "archzfs" for mDNS discovery -info "Setting hostname to archzfs..." -echo "archzfs" > "$PROFILE_DIR/airootfs/etc/hostname" +# Set hostname to "archangel" for mDNS discovery +info "Setting hostname to archangel..." +echo "archangel" > "$PROFILE_DIR/airootfs/etc/hostname" # Create /etc/hosts with proper hostname entries cat > "$PROFILE_DIR/airootfs/etc/hosts" << 'EOF' 127.0.0.1 localhost ::1 localhost -127.0.1.1 archzfs.localdomain archzfs +127.0.1.1 archangel.localdomain archangel EOF # Configure nsswitch.conf for mDNS resolution diff --git a/custom/archsetup-zfs b/custom/archsetup-zfs index 89aeb08..df8f835 100755 --- a/custom/archsetup-zfs +++ b/custom/archsetup-zfs @@ -6,7 +6,7 @@ # This is a ZFS-specific variant of archsetup. # It replaces btrfs snapshot tooling with ZFS equivalents. # -# Run this after install-archzfs completes and you've rebooted. +# Run this after archangel completes and you've rebooted. # Commentary # @@ -15,7 +15,7 @@ # - Adds: sanoid/syncoid configuration verification # - Keeps: All other package installations and configurations # -# The ZFS snapshot infrastructure is already configured by install-archzfs: +# The ZFS snapshot infrastructure is already configured by archangel: # - sanoid.timer for automatic snapshots # - pacman hook for pre-upgrade snapshots # - syncoid script for TrueNAS replication @@ -340,7 +340,7 @@ essential_services() { pacman_install pacman-contrib systemctl enable --now paccache.timer >> "$logfile" 2>&1 - # ZFS snapshot services (already configured by install-archzfs) + # ZFS snapshot services (already configured by archangel) display "subtitle" "ZFS Snapshot Services" action="verifying sanoid timer" && display "task" "$action" systemctl enable --now sanoid.timer >> "$logfile" 2>&1 || \ @@ -416,7 +416,7 @@ main() { echo " ~/code/archsetup/archsetup" echo "" echo "The ZFS-specific services (sanoid, pacman hooks," - echo "syncoid) were already configured by install-archzfs." + echo "syncoid) were already configured by archangel." echo "" # When fully implemented, this will call: diff --git a/docs/NOTES.org b/docs/NOTES.org index 92e4f34..51a31f3 100644 --- a/docs/NOTES.org +++ b/docs/NOTES.org @@ -1,4 +1,4 @@ -#+TITLE: Claude Code Notes - archzfs +#+TITLE: Claude Code Notes - archangel #+AUTHOR: Craig Jennings & Claude #+DATE: 2026-01-17 @@ -28,21 +28,21 @@ Build system for creating a custom Arch Linux installation ISO with ZFS support. ** Repository -- Remote: =cjennings@cjennings.net:git/archzfs.git= +- Remote: =cjennings@cjennings.net:git/archangel.git= - Branch: =main= - docs/ is committed (not private) ** Key Components - =build.sh= - Main build script (runs as root) - - Downloads ZFS packages from archzfs GitHub releases + - Downloads ZFS packages from archzfs.com repository - Creates custom archiso profile based on releng - Adds custom packages (nodejs, npm, jq, zsh, htop, ripgrep, etc.) - Copies custom installer scripts into ISO - Builds ISO with mkarchiso - =custom/= - Custom scripts included in ISO - - =install-archzfs= - Main installer script + - =archangel= - Main installer script - =install-claude= - Claude Code installer - =archsetup-zfs= - ZFS-specific Arch setup - =zfs-setup= - Installs ZFS packages and loads module (generated by build.sh) @@ -51,14 +51,12 @@ Build system for creating a custom Arch Linux installation ISO with ZFS support. ** Current State -TESTING: install-archzfs script almost complete. +TESTING: archangel installer supports both ZFS and Btrfs. -- ISO builds successfully (4.8G) with linux-lts + zfs-dkms -- ZFS module loads correctly in live environment -- install-archzfs runs through partitioning, pool creation, base install, system config -- Last fix: added freetype2 for grub-mkfont (needs rebuild to test) - -Next: Rebuild ISO, complete install test, boot installed system. +- ISO builds successfully with linux-lts + zfs-dkms +- ZFS installations use ZFSBootMenu +- Btrfs installations use GRUB + grub-btrfs for snapshot boot +- Both filesystems support multi-disk RAID configurations ** Goals @@ -440,7 +438,7 @@ Each entry should use this format: *Files Modified:* - [[file:../build.sh][build.sh]] - Removed grub-zfs-snap copying -- [[file:../custom/install-archzfs][custom/install-archzfs]] - Major ZFSBootMenu rewrite +- [[file:../custom/archangel][custom/install-archzfs]] - Major ZFSBootMenu rewrite - [[file:../custom/zfssnapshot][custom/zfssnapshot]] - Removed grub-zfs-snap call - [[file:../custom/zfsrollback][custom/zfsrollback]] - Removed grub-zfs-snap call @@ -515,7 +513,7 @@ Each entry should use this format: - Behavioral lessons go in PRINCIPLES.org, technical facts in session docs *Files Modified:* -- [[file:../custom/install-archzfs][custom/install-archzfs]] - Fixed mkinitcpio configuration +- [[file:../custom/archangel][custom/install-archzfs]] - Fixed mkinitcpio configuration - [[file:../todo.org][todo.org]] - Added ZFS rollback + /boot issue, ZFSBootMenu task - [[file:PRINCIPLES.org][docs/PRINCIPLES.org]] - New file with behavioral lessons - [[file:protocols.org][docs/protocols.org]] - Added PRINCIPLES.org to session startup @@ -599,7 +597,7 @@ Each entry should use this format: *Files Modified:* - [[file:../build.sh][build.sh]] - major updates for linux-lts, bootloader configs, mkinitcpio preset -- [[file:../custom/install-archzfs][custom/install-archzfs]] - multiple bug fixes, removed sanoid/syncoid +- [[file:../custom/archangel][custom/install-archzfs]] - multiple bug fixes, removed sanoid/syncoid - [[file:~/code/archsetup/inbox/zfs-sanoid-detection.txt][archsetup inbox]] - sanoid/syncoid config for archsetup to implement *Current State:* diff --git a/download-archzfs-iso.sh b/download-archzfs-iso.sh deleted file mode 100755 index 65b5f3d..0000000 --- a/download-archzfs-iso.sh +++ /dev/null @@ -1,145 +0,0 @@ -#!/bin/bash -# download-archzfs-iso.sh - Download the official archzfs ISO and add our scripts -# -# The archzfs project maintains ISOs with matched kernel+ZFS versions. -# This script downloads their ISO and creates a script bundle to use with it. - -set -e - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -OUT_DIR="$SCRIPT_DIR/out" -CUSTOM_DIR="$SCRIPT_DIR/custom" - -# Colors -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -CYAN='\033[0;36m' -NC='\033[0m' - -info() { echo -e "${GREEN}[INFO]${NC} $1"; } -warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } - -mkdir -p "$OUT_DIR" - -echo "" -echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" -echo " ArchZFS ISO Setup" -echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" -echo "" - -# Check for existing archzfs ISO -EXISTING_ISO=$(ls "$OUT_DIR"/archlinux-*-zfs-*.iso 2>/dev/null | head -1) - -if [[ -n "$EXISTING_ISO" ]]; then - info "Found existing archzfs ISO: $(basename "$EXISTING_ISO")" - read -p "Use this ISO? [Y/n]: " use_existing - if [[ "$use_existing" != "n" && "$use_existing" != "N" ]]; then - ISO_FILE="$EXISTING_ISO" - fi -fi - -if [[ -z "$ISO_FILE" ]]; then - info "Fetching latest archzfs ISO URL..." - - # Get the latest ISO from archzfs releases - RELEASE_URL="https://github.com/archzfs/archzfs/releases" - - echo "" - echo "Please download the latest archzfs ISO from:" - echo -e " ${CYAN}$RELEASE_URL${NC}" - echo "" - echo "Look for: archlinux-YYYY.MM.DD-zfs-linux-lts-x86_64.iso" - echo "Save it to: $OUT_DIR/" - echo "" - read -p "Press Enter once downloaded, or Ctrl+C to abort..." - - ISO_FILE=$(ls "$OUT_DIR"/archlinux-*-zfs-*.iso 2>/dev/null | head -1) - - if [[ -z "$ISO_FILE" ]]; then - echo "No archzfs ISO found in $OUT_DIR/" - exit 1 - fi -fi - -info "Using ISO: $ISO_FILE" - -# Create a tarball of our custom scripts -info "Creating script bundle..." - -BUNDLE_DIR=$(mktemp -d) -mkdir -p "$BUNDLE_DIR/archzfs-scripts" - -# Copy our scripts -cp "$CUSTOM_DIR/install-archzfs" "$BUNDLE_DIR/archzfs-scripts/" -cp "$CUSTOM_DIR/install-claude" "$BUNDLE_DIR/archzfs-scripts/" -cp "$CUSTOM_DIR/archsetup-zfs" "$BUNDLE_DIR/archzfs-scripts/" - -# Copy archsetup if available -if [[ -d /home/cjennings/code/archsetup ]]; then - info "Including archsetup..." - cp -r /home/cjennings/code/archsetup "$BUNDLE_DIR/archzfs-scripts/" - rm -rf "$BUNDLE_DIR/archzfs-scripts/archsetup/.git" - rm -rf "$BUNDLE_DIR/archzfs-scripts/archsetup/.claude" -fi - -# Create setup script -cat > "$BUNDLE_DIR/archzfs-scripts/setup.sh" << 'SETUP' -#!/bin/bash -# Run this after booting the archzfs ISO -# It copies the installation scripts to the right places - -set -e - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -echo "Setting up archzfs installation scripts..." - -# Copy scripts to /usr/local/bin -cp "$SCRIPT_DIR/install-archzfs" /usr/local/bin/ -cp "$SCRIPT_DIR/install-claude" /usr/local/bin/ -cp "$SCRIPT_DIR/archsetup-zfs" /usr/local/bin/ -chmod +x /usr/local/bin/install-archzfs -chmod +x /usr/local/bin/install-claude -chmod +x /usr/local/bin/archsetup-zfs - -# Copy archsetup to /code -if [[ -d "$SCRIPT_DIR/archsetup" ]]; then - mkdir -p /code - cp -r "$SCRIPT_DIR/archsetup" /code/ - echo "archsetup copied to /code/archsetup" -fi - -echo "" -echo "Setup complete! You can now run:" -echo " install-archzfs" -echo "" -SETUP -chmod +x "$BUNDLE_DIR/archzfs-scripts/setup.sh" - -# Create the tarball -BUNDLE_FILE="$OUT_DIR/archzfs-scripts.tar.gz" -tar -czf "$BUNDLE_FILE" -C "$BUNDLE_DIR" archzfs-scripts -rm -rf "$BUNDLE_DIR" - -info "Script bundle created: $BUNDLE_FILE" - -echo "" -echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" -echo -e "${GREEN}Setup Complete!${NC}" -echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" -echo "" -echo "To install Arch on ZFS:" -echo "" -echo "1. Boot from the archzfs ISO:" -echo " $(basename "$ISO_FILE")" -echo "" -echo "2. Connect to network, then download and extract scripts:" -echo " # If you have a web server or USB drive with the bundle:" -echo " tar -xzf archzfs-scripts.tar.gz" -echo " cd archzfs-scripts && ./setup.sh" -echo "" -echo "3. Run the installer:" -echo " install-archzfs" -echo "" -echo "Alternative: Copy scripts via SSH from another machine" -echo "" diff --git a/scripts/boot-vm.sh b/scripts/boot-vm.sh index 82922db..6eb8eea 100755 --- a/scripts/boot-vm.sh +++ b/scripts/boot-vm.sh @@ -6,7 +6,7 @@ # - Otherwise, boot from ISO SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -VM_DISK="$SCRIPT_DIR/../vm/archzfs-test.qcow2" +VM_DISK="$SCRIPT_DIR/../vm/archangel-test.qcow2" if [[ -f "$VM_DISK" ]] && [[ $(stat -c%s "$VM_DISK") -gt 200000 ]]; then # Disk exists and is larger than ~200KB (has been written to) diff --git a/scripts/build-release b/scripts/build-release index e02381a..ef0c96f 100755 --- a/scripts/build-release +++ b/scripts/build-release @@ -1,5 +1,5 @@ #!/bin/bash -# build-release - Build and distribute the archzfs ISO +# build-release - Build and distribute the archangel ISO # # Usage: # ./scripts/build-release # Full build, sanity test, and distribute @@ -8,10 +8,7 @@ # ./scripts/build-release --skip-test # Skip all testing # # Distribution targets: -# - ~/downloads/isos (always) # - truenas.local:/mnt/vault/isos (if reachable) -# - USB drive with ARCHZFS label (if present, writes via dd) -# - Ventoy USB drive (if detected, copies ISO file) set -e @@ -28,7 +25,6 @@ else fi # Distribution targets -LOCAL_ISO_DIR="$REAL_HOME/downloads/isos" TRUENAS_HOST="truenas.local" TRUENAS_PATH="/mnt/vault/isos" @@ -48,21 +44,18 @@ step() { echo -e "\n${CYAN}=== $1 ===${NC}\n"; } SKIP_BUILD=false SKIP_TEST=false FULL_TEST=false -AUTO_CONFIRM=false while [[ $# -gt 0 ]]; do case $1 in --skip-build) SKIP_BUILD=true; shift ;; --skip-test) SKIP_TEST=true; shift ;; --full-test) FULL_TEST=true; shift ;; - --yes|-y) AUTO_CONFIRM=true; shift ;; -h|--help) - echo "Usage: $0 [--skip-build] [--skip-test] [--full-test] [--yes]" + echo "Usage: $0 [--skip-build] [--skip-test] [--full-test]" echo "" echo "Options:" echo " --skip-build Skip ISO build, distribute existing ISO" echo " --skip-test Skip QEMU sanity test" echo " --full-test Run comprehensive install tests (single, mirror, raidz1)" - echo " --yes, -y Auto-confirm dd to ARCHZFS drive (no prompt)" exit 0 ;; *) error "Unknown option: $1" ;; @@ -75,7 +68,7 @@ TRUENAS_SUCCESS=false # Check root for build check_root() { if [[ $EUID -ne 0 ]]; then - error "This script must be run as root (for build and dd operations)" + error "This script must be run as root (for build operations)" fi } @@ -122,94 +115,6 @@ full_test() { info "All installation tests passed!" } -# Find ARCHZFS labeled USB drive -find_archzfs_drive() { - ARCHZFS_DEV=$(blkid -L ARCHZFS 2>/dev/null | head -1) - if [[ -n "$ARCHZFS_DEV" ]]; then - # Get the parent device (e.g., /dev/sda from /dev/sda1) - ARCHZFS_DISK=$(lsblk -no PKNAME "$ARCHZFS_DEV" 2>/dev/null | head -1) - if [[ -n "$ARCHZFS_DISK" ]]; then - ARCHZFS_DISK="/dev/$ARCHZFS_DISK" - # Note: Don't check for removable - Framework expansion cards - # show as internal drives but are actually hot-swappable - info "Found ARCHZFS drive: $ARCHZFS_DISK" - return 0 - fi - fi - ARCHZFS_DISK="" - return 1 -} - -# Find Ventoy USB drive -find_ventoy_drive() { - VENTOY_PART="" - VENTOY_MOUNT="" - - # Method 1: Look for partition labeled "Ventoy" - local ventoy_by_label=$(blkid -L Ventoy 2>/dev/null | head -1) - if [[ -n "$ventoy_by_label" ]]; then - VENTOY_PART="$ventoy_by_label" - info "Found Ventoy drive by label: $VENTOY_PART" - return 0 - fi - - # Method 2: Check mounted or mountable partitions for ventoy/ directory - # Look for removable drives with exfat/ntfs - while read -r dev fstype rm; do - [[ "$rm" != "1" ]] && continue # Skip non-removable - [[ ! "$fstype" =~ ^(exfat|ntfs|vfat)$ ]] && continue # Skip wrong fs types - - local mount_point=$(lsblk -no MOUNTPOINT "/dev/$dev" 2>/dev/null) - local needs_unmount=false - - if [[ -z "$mount_point" ]]; then - # Try mounting temporarily - mount_point=$(mktemp -d) - if mount -o ro "/dev/$dev" "$mount_point" 2>/dev/null; then - needs_unmount=true - else - rmdir "$mount_point" - continue - fi - fi - - # Check for ventoy directory - if [[ -d "$mount_point/ventoy" ]] || [[ -f "$mount_point/ventoy/ventoy.json" ]]; then - VENTOY_PART="/dev/$dev" - info "Found Ventoy drive by content: $VENTOY_PART" - if $needs_unmount; then - umount "$mount_point" - rmdir "$mount_point" - fi - return 0 - fi - - if $needs_unmount; then - umount "$mount_point" - rmdir "$mount_point" - fi - done < <(lsblk -rno NAME,FSTYPE,RM 2>/dev/null | grep -v "^loop") - - return 1 -} - -# Distribute to local directory -distribute_local() { - step "Distributing to Local Directory" - mkdir -p "$LOCAL_ISO_DIR" - - # Remove old archzfs ISOs - local old_isos=$(ls "$LOCAL_ISO_DIR"/archzfs-*.iso 2>/dev/null || true) - if [[ -n "$old_isos" ]]; then - info "Removing old ISOs..." - rm -f "$LOCAL_ISO_DIR"/archzfs-*.iso - fi - - info "Copying to $LOCAL_ISO_DIR/" - cp "$ISO_FILE" "$LOCAL_ISO_DIR/" - info "Done: $LOCAL_ISO_DIR/$ISO_NAME" -} - # Distribute to TrueNAS distribute_truenas() { step "Distributing to TrueNAS" @@ -222,18 +127,12 @@ distribute_truenas() { info "TrueNAS is reachable" - # Run SSH/SCP as the real user (not root) to use their SSH keys - local ssh_cmd="ssh" + # Run SCP as the real user (not root) to use their SSH keys local scp_cmd="scp" if [[ -n "$SUDO_USER" ]]; then - ssh_cmd="sudo -u $SUDO_USER ssh" scp_cmd="sudo -u $SUDO_USER scp" fi - # Remove old ISOs and copy new one - info "Removing old ISOs from TrueNAS..." - $ssh_cmd "cjennings@$TRUENAS_HOST" "rm -f $TRUENAS_PATH/archzfs-*.iso" 2>/dev/null || true - info "Copying to $TRUENAS_HOST:$TRUENAS_PATH/" if $scp_cmd "$ISO_FILE" "cjennings@$TRUENAS_HOST:$TRUENAS_PATH/"; then info "Done: $TRUENAS_HOST:$TRUENAS_PATH/$ISO_NAME" @@ -244,106 +143,15 @@ distribute_truenas() { fi } -# Write to ARCHZFS USB drive -distribute_archzfs_usb() { - step "Writing to ARCHZFS USB Drive" - - if ! find_archzfs_drive; then - warn "No ARCHZFS USB drive found, skipping" - return 0 - fi - - # Confirm before writing (unless --yes flag) - echo "" - warn "About to write ISO to $ARCHZFS_DISK" - lsblk "$ARCHZFS_DISK" - echo "" - - if ! $AUTO_CONFIRM; then - warn "This will ERASE ALL DATA on the drive!" - read -p "Type 'yes' to confirm: " confirm - if [[ "$confirm" != "yes" ]]; then - warn "Skipping USB write" - return 0 - fi - else - info "Auto-confirmed (--yes flag)" - fi - - # Unmount any mounted partitions - for part in $(lsblk -rno NAME "$ARCHZFS_DISK" | tail -n +2); do - umount "/dev/$part" 2>/dev/null || true - done - - info "Writing ISO to $ARCHZFS_DISK..." - dd if="$ISO_FILE" of="$ARCHZFS_DISK" bs=4M status=progress oflag=sync - sync - info "Done writing to $ARCHZFS_DISK" -} - -# Copy to Ventoy USB drive -distribute_ventoy() { - step "Copying to Ventoy USB Drive" - - if ! find_ventoy_drive; then - warn "No Ventoy USB drive found, skipping" - return 0 - fi - - # Mount if needed - local mount_point=$(lsblk -no MOUNTPOINT "$VENTOY_PART" 2>/dev/null) - local needs_unmount=false - - if [[ -z "$mount_point" ]]; then - mount_point=$(mktemp -d) - info "Mounting $VENTOY_PART to $mount_point" - mount "$VENTOY_PART" "$mount_point" - needs_unmount=true - fi - - # Remove old archzfs ISOs - local old_isos=$(ls "$mount_point"/archzfs-*.iso 2>/dev/null || true) - if [[ -n "$old_isos" ]]; then - info "Removing old ISOs from Ventoy..." - rm -f "$mount_point"/archzfs-*.iso - fi - - info "Copying ISO to Ventoy drive..." - cp "$ISO_FILE" "$mount_point/" - sync - info "Done: $mount_point/$ISO_NAME" - - if $needs_unmount; then - info "Unmounting Ventoy drive..." - umount "$mount_point" - rmdir "$mount_point" - fi -} - # Summary show_summary() { step "Distribution Complete" echo "ISO: $ISO_NAME" echo "" - echo "Distributed to:" - echo " ✓ $LOCAL_ISO_DIR/" - if $TRUENAS_SUCCESS; then - echo " ✓ $TRUENAS_HOST:$TRUENAS_PATH/" - else - echo " ✗ $TRUENAS_HOST (failed or skipped)" - fi - - if [[ -n "$ARCHZFS_DISK" ]]; then - echo " ✓ $ARCHZFS_DISK (USB boot drive)" - else - echo " - ARCHZFS USB drive (not found)" - fi - - if [[ -n "$VENTOY_PART" ]]; then - echo " ✓ $VENTOY_PART (Ventoy)" + echo "Distributed to: $TRUENAS_HOST:$TRUENAS_PATH/" else - echo " - Ventoy drive (not found)" + echo "TrueNAS not reachable - ISO only in out/" fi } @@ -366,10 +174,7 @@ main() { step "Skipping Tests" fi - distribute_local distribute_truenas - distribute_archzfs_usb - distribute_ventoy show_summary } diff --git a/scripts/full-test.sh b/scripts/full-test.sh index a1e1c3a..9276bab 100755 --- a/scripts/full-test.sh +++ b/scripts/full-test.sh @@ -1,5 +1,5 @@ #!/bin/bash -# full-test.sh - Comprehensive installation testing for archzfs ISO +# full-test.sh - Comprehensive installation testing for archangel ISO # # Runs automated installation tests for all disk configurations: # - Single disk @@ -8,7 +8,7 @@ # # Each test: # 1. Boots ISO in headless QEMU -# 2. Runs unattended install-archzfs +# 2. Runs unattended archangel # 3. Reboots into installed system # 4. Verifies ZFS pool is healthy # @@ -40,7 +40,7 @@ OVMF_VARS_ORIG="/usr/share/edk2/x64/OVMF_VARS.4m.fd" # SSH settings SSH_PORT=2224 # Different port to avoid conflicts SSH_USER="root" -SSH_PASS_LIVE="archzfs" # Live ISO password +SSH_PASS_LIVE="archangel" # Live ISO password SSH_PASS_INSTALLED="testroot123" # Installed system password (from config) SSH_PASS="$SSH_PASS_LIVE" # Current password (switches after install) SSH_OPTS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR -o ConnectTimeout=5" @@ -90,7 +90,7 @@ while [[ $# -gt 0 ]]; do -h|--help) echo "Usage: $0 [--quick] [--verbose]" echo "" - echo "Comprehensive installation testing for archzfs ISO." + echo "Comprehensive installation testing for archangel ISO." echo "" echo "Options:" echo " --quick, -q Run single-disk test only (faster)" @@ -167,7 +167,7 @@ start_vm_iso() { done qemu-system-x86_64 \ - -name "archzfs-fulltest" \ + -name "archangel-fulltest" \ -machine q35,accel=kvm \ -cpu host \ -smp "$VM_CPUS" \ @@ -207,7 +207,7 @@ start_vm_disk() { done qemu-system-x86_64 \ - -name "archzfs-fulltest" \ + -name "archangel-fulltest" \ -machine q35,accel=kvm \ -cpu host \ -smp "$VM_CPUS" \ @@ -340,11 +340,11 @@ $config CONF" # Run installation - info "Running install-archzfs (this takes several minutes)..." + info "Running archangel (this takes several minutes)..." local install_start=$(date +%s) # Run install in background and monitor - ssh_cmd "nohup install-archzfs --config-file /tmp/install.conf > /tmp/install.log 2>&1 &" + ssh_cmd "nohup archangel --config-file /tmp/install.conf > /tmp/install.log 2>&1 &" # Wait for installation to complete local elapsed=0 @@ -354,7 +354,7 @@ CONF" ((elapsed += check_interval)) # Check if install process is still running - if ! ssh_cmd "pgrep -f 'install-archzfs' > /dev/null" 2>/dev/null; then + if ! ssh_cmd "pgrep -f 'archangel' > /dev/null" 2>/dev/null; then # Process finished - check result by looking for success indicators local exit_check=$(ssh_cmd "tail -30 /tmp/install.log" 2>/dev/null) # Check for various success indicators @@ -541,7 +541,7 @@ print_summary() { # Main main() { - banner "ARCHZFS FULL INSTALLATION TEST" + banner "ARCHANGEL FULL INSTALLATION TEST" check_deps find_iso diff --git a/scripts/sanity-test.sh b/scripts/sanity-test.sh index eeb4d29..9248da1 100755 --- a/scripts/sanity-test.sh +++ b/scripts/sanity-test.sh @@ -1,5 +1,5 @@ #!/bin/bash -# sanity-test.sh - Automated sanity test for archzfs ISO +# sanity-test.sh - Automated sanity test for archangel ISO # # Boots the ISO in a headless QEMU VM, waits for SSH, runs verification # commands, and reports pass/fail. Fully automated - no human input required. @@ -22,7 +22,7 @@ VM_DISK="$VM_DIR/sanity-test.qcow2" VM_DISK_SIZE="10G" VM_RAM="2048" VM_CPUS="2" -VM_NAME="archzfs-sanity" +VM_NAME="archangel-sanity" # UEFI firmware OVMF_CODE="/usr/share/edk2/x64/OVMF_CODE.4m.fd" @@ -32,7 +32,7 @@ OVMF_VARS="$VM_DIR/sanity-test-OVMF_VARS.fd" # SSH settings SSH_PORT=2223 # Different port to avoid conflicts with test-vm.sh SSH_USER="root" -SSH_PASS="archzfs" +SSH_PASS="archangel" SSH_TIMEOUT=180 # Max seconds to wait for SSH SSH_OPTS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR -o ConnectTimeout=5" @@ -62,7 +62,7 @@ while [[ $# -gt 0 ]]; do -h|--help) echo "Usage: $0 [--verbose]" echo "" - echo "Automated sanity test for archzfs ISO." + echo "Automated sanity test for archangel ISO." echo "Boots ISO in headless QEMU, verifies via SSH, reports results." exit 0 ;; @@ -232,8 +232,8 @@ run_sanity_tests() { "zfs-" # Test 4: Custom scripts present - run_test "install-archzfs script present" \ - "test -x /usr/local/bin/install-archzfs && echo 'exists'" \ + run_test "archangel script present" \ + "test -x /usr/local/bin/archangel && echo 'exists'" \ "exists" run_test "zfsrollback script present" \ @@ -244,14 +244,6 @@ run_sanity_tests() { "test -x /usr/local/bin/zfssnapshot && echo 'exists'" \ "exists" - run_test "grub-zfs-snap script present" \ - "test -x /usr/local/bin/grub-zfs-snap && echo 'exists'" \ - "exists" - - run_test "zfs-snap-prune script present" \ - "test -x /usr/local/bin/zfs-snap-prune && echo 'exists'" \ - "exists" - # Test 5: fzf installed (required by zfsrollback) run_test "fzf installed" \ "command -v fzf && echo 'found'" \ @@ -287,10 +279,10 @@ run_sanity_tests() { "grep -q 'mdns' /etc/nsswitch.conf && echo 'configured'" \ "configured" - # Test 9: Hostname set to archzfs - run_test "Hostname is archzfs" \ + # Test 9: Hostname set to archangel + run_test "Hostname is archangel" \ "cat /etc/hostname" \ - "archzfs" + "archangel" # Test 10: Kernel version (LTS) run_test "Running LTS kernel" \ @@ -302,6 +294,47 @@ run_sanity_tests() { "test -d /code/archsetup && echo 'exists'" \ "exists" + # Test 11: Btrfs tools installed (dual filesystem support) + run_test "Btrfs tools installed" \ + "command -v btrfs && echo 'found'" \ + "found" + + run_test "mkfs.btrfs available" \ + "command -v mkfs.btrfs && echo 'found'" \ + "found" + + # Test 12: Snapper installed (Btrfs snapshot management) + run_test "Snapper installed" \ + "command -v snapper && echo 'found'" \ + "found" + + # Test 13: archangel installer components + run_test "archangel script executable" \ + "file /usr/local/bin/archangel | grep -q 'script' && echo 'executable'" \ + "executable" + + run_test "archangel lib directory present" \ + "test -d /usr/local/bin/lib && echo 'exists'" \ + "exists" + + run_test "archangel lib/common.sh present" \ + "test -f /usr/local/bin/lib/common.sh && echo 'exists'" \ + "exists" + + run_test "archangel config example present" \ + "test -f /root/archangel.conf.example && echo 'exists'" \ + "exists" + + # Test 14: GRUB installed (for Btrfs bootloader) + run_test "GRUB installed" \ + "command -v grub-install && echo 'found'" \ + "found" + + # Test 15: Cryptsetup for LUKS (Btrfs encryption) + run_test "Cryptsetup installed" \ + "command -v cryptsetup && echo 'found'" \ + "found" + echo "" } @@ -328,7 +361,7 @@ print_summary() { main() { echo "" echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" - echo -e "${CYAN} ARCHZFS ISO SANITY TEST${NC}" + echo -e "${CYAN} ARCHANGEL ISO SANITY TEST${NC}" echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" echo "" diff --git a/scripts/test-install.sh b/scripts/test-install.sh index c4f859f..f0046bb 100755 --- a/scripts/test-install.sh +++ b/scripts/test-install.sh @@ -1,5 +1,5 @@ #!/bin/bash -# test-install.sh - Automated installation testing for archzfs +# test-install.sh - Automated installation testing for archangel # # Runs unattended installs in VMs using test config files. # Verifies installation success via SSH (when enabled) or console. @@ -22,7 +22,7 @@ VM_RAM="4096" VM_CPUS="4" VM_DISK_SIZE="20G" export SSH_PORT="2222" -export SSH_PASSWORD="archzfs" +export SSH_PASSWORD="archangel" SERIAL_LOG="$LOG_DIR/serial.log" # Timeouts (seconds) @@ -149,7 +149,7 @@ start_vm() { # Start VM with serial console logging qemu-system-x86_64 \ - -name "archzfs-test-$test_name" \ + -name "archangel-test-$test_name" \ -machine type=q35,accel=kvm \ -cpu host \ -m "$VM_RAM" \ @@ -183,7 +183,7 @@ start_vm_from_disk() { # Start VM without ISO, boot from disk qemu-system-x86_64 \ - -name "archzfs-test-$test_name" \ + -name "archangel-test-$test_name" \ -machine type=q35,accel=kvm \ -cpu host \ -m "$VM_RAM" \ diff --git a/scripts/test-vm.sh b/scripts/test-vm.sh index 4c56570..f2a4a00 100755 --- a/scripts/test-vm.sh +++ b/scripts/test-vm.sh @@ -1,5 +1,5 @@ #!/bin/bash -# test-vm.sh - Test the archzfs ISO in a QEMU virtual machine +# test-vm.sh - Test the archangel ISO in a QEMU virtual machine # # Usage: # ./test-vm.sh # Create new VM and boot ISO (single disk) @@ -13,7 +13,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_DIR="$(dirname "$SCRIPT_DIR")" # VM Configuration -VM_NAME="archzfs-test" +VM_NAME="archangel-test" VM_DIR="$PROJECT_DIR/vm" VM_DISK="$VM_DIR/$VM_NAME.qcow2" VM_DISK2="$VM_DIR/$VM_NAME-disk2.qcow2" @@ -139,8 +139,8 @@ boot_iso() { echo " - Press Ctrl+Alt+G to release mouse grab" echo " - Press Ctrl+Alt+F to toggle fullscreen" echo " - Serial console output appears in this terminal" - echo " - SSH: ssh -p 2222 root@localhost (password: archzfs)" - echo " - Run 'install-archzfs' to start installation" + echo " - SSH: ssh -p 2222 root@localhost (password: archangel)" + echo " - Run 'archangel' to start installation" echo " - Monitor socket: $MONITOR_SOCKET" echo "" @@ -258,7 +258,7 @@ show_help() { echo " CPUs: $VM_CPUS" echo "" echo "SSH into running VM:" - echo " ssh -p 2222 root@localhost (password: archzfs)" + echo " ssh -p 2222 root@localhost (password: archangel)" } # Main |
