<feed xmlns='http://www.w3.org/2005/Atom'>
<title>archangel, branch main</title>
<subtitle>Arch Linux installer ISO — ZFS-on-root or BTRFS, doubles as rescue disk
</subtitle>
<id>https://git.cjennings.net/archangel/atom?h=main</id>
<link rel='self' href='https://git.cjennings.net/archangel/atom?h=main'/>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archangel/'/>
<updated>2026-06-28T02:08:28+00:00</updated>
<entry>
<title>fix(installer): scope AUR list to filesystem, keep pacman.conf 0644</title>
<updated>2026-06-28T02:08:28+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-28T02:08:28+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archangel/commit/?id=2ead67458add6accda226cca3e21592162d05bfd'/>
<id>urn:sha1:2ead67458add6accda226cca3e21592162d05bfd</id>
<content type='text'>
The baked AUR set installed unconditionally, so zfs-auto-snapshot reached every target. On a btrfs install there's no zfs to satisfy its dependency, and pacstrap aborted the whole transaction. The ISO still bakes the full set. install_base now filters the manifest names through filter_aur_for_fs, dropping zfs-only tooling (zfs-auto-snapshot, zrepl) on a non-zfs target.

strip_repo_stanza mv'd a 0600 mktemp file onto the target, so a clean install shipped /etc/pacman.conf root-only and every user-level makepkg/yay failed to read it. It now truncate-writes through the existing file, preserving the pristine 0644.

Tested in test_common.bats.
</content>
</entry>
<entry>
<title>fix(installer): refresh package databases before pacstrap</title>
<updated>2026-06-25T17:05:56+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-25T17:05:56+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archangel/commit/?id=89691a0dc9eb7dcbf8583797d7cdc34aecec0d56'/>
<id>urn:sha1:89691a0dc9eb7dcbf8583797d7cdc34aecec0d56</id>
<content type='text'>
A ZFS-root install from an aged ISO died in install_base: dkms couldn't build zfs/2.3.3 against a current linux-lts. The ISO bakes the archzfs sync db at build time, so as the ISO ages that db keeps pinning an older zfs-dkms while linux-lts is pulled current from the live mirror. The DKMS module then fails to compile against the newer kernel.

Run pacman -Syy after the archzfs and baked-AUR repos are added to the live pacman.conf and before pacstrap -K, so pacstrap resolves the current zfs-dkms instead of the stale baked one. A plain -y can be skipped by pacman's freshness check against the GitHub-served archzfs db (no reliable timestamps), so -yy forces the refresh.
</content>
</entry>
<entry>
<title>refactor(installer): extract parse_btrfs_subvol_opts helper</title>
<updated>2026-06-24T01:05:17+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-24T01:05:17+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archangel/commit/?id=73e66b703258270a3d688a51dd90ed2f24401568'/>
<id>urn:sha1:73e66b703258270a3d688a51dd90ed2f24401568</id>
<content type='text'>
mount_btrfs_subvolumes and generate_btrfs_fstab each carried an identical block that composed a subvolume's mount options from BTRFS_OPTS plus the per-subvol extra flags. The two could drift out of sync. Extracted the logic into parse_btrfs_subvol_opts (pure string transform), preserving the exact behavior, and called it from both. Added bats cases covering the default, compress=no, nodatacow, nosuid, and combined paths.
</content>
</entry>
<entry>
<title>fix(installer): RAID validation, set -e fix, drop dead shadow branch</title>
<updated>2026-06-24T00:55:07+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-24T00:55:07+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archangel/commit/?id=edb5016809f3bc657283d8c2402970dbbab3c5cf'/>
<id>urn:sha1:edb5016809f3bc657283d8c2402970dbbab3c5cf</id>
<content type='text'>
Two installer cleanups from the todo backlog.

validate_config now rejects a RAID_LEVEL the selected disk count can't support, guarding the unattended path (the interactive path already constrains the choice). While adding it I found a latent bug: the error loop's ((errors++)) returned 0 on the first error and tripped set -e in the monolith's `[[ UNATTENDED == true ]] &amp;&amp; validate_config` call, aborting after one warning instead of listing every problem. Switched to pre-increment so the count accumulates as designed. Added four bats cases, including one that runs validate_config under set -e outside bats' run shield.

build.sh dropped the dead shadow-file rebuild else-branch. The profile is always copied fresh from releng (which ships /etc/shadow), so the branch never ran, and its hardcoded account list had drifted from what releng provides. Replaced with an assertion that fails the build loudly if the file is ever missing.
</content>
</entry>
<entry>
<title>chore: ignore elisp and python build artifacts</title>
<updated>2026-06-24T00:11:13+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-24T00:11:13+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archangel/commit/?id=f0f56e1fe2e2bbb3a57bb61235e67c0bdc8402ae'/>
<id>urn:sha1:f0f56e1fe2e2bbb3a57bb61235e67c0bdc8402ae</id>
<content type='text'>
</content>
</entry>
<entry>
<title>fix(build): drop sanoid from the baked AUR set</title>
<updated>2026-06-17T05:13:15+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-17T05:13:15+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archangel/commit/?id=448a40651e71f8be4dd6a7b3b03bb233e6894eec'/>
<id>urn:sha1:448a40651e71f8be4dd6a7b3b03bb233e6894eec</id>
<content type='text'>
sanoid depends on perl-config-inifiles, which is AUR-only. makepkg -s can't resolve it from the official repos, so the build aborts before it produces an ISO. The 2026-06-09 dependency gate checked AUR-RPC existence rather than the official sync dbs, so it wrongly classified perl-config-inifiles as official. A full build caught it.

sanoid joins paru and mkinitcpio-firmware as AUR-of-AUR packages deferred to the vNext dependency-resolution work. The v1 baked set is now eight packages. Updated the tests and README to match.
</content>
</entry>
<entry>
<title>chore: gitignore .claude/ and AGENTS.md</title>
<updated>2026-06-17T03:57:41+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-17T03:57:41+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archangel/commit/?id=4985fa8fa92784b5e63455df43bf59cf3387b7fe'/>
<id>urn:sha1:4985fa8fa92784b5e63455df43bf59cf3387b7fe</id>
<content type='text'>
</content>
</entry>
<entry>
<title>chore: gitignore the personal project-level CLAUDE.md</title>
<updated>2026-06-10T05:11:12+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-10T05:11:12+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archangel/commit/?id=5ca601c5b5bdb64ce764c723a590c191e67308e9'/>
<id>urn:sha1:5ca601c5b5bdb64ce764c723a590c191e67308e9</id>
<content type='text'>
</content>
</entry>
<entry>
<title>docs: document baked AUR packages in the README</title>
<updated>2026-06-10T04:48:21+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-10T04:48:21+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archangel/commit/?id=492f704ec11487c8a802b50d3c86ba1137b66253'/>
<id>urn:sha1:492f704ec11487c8a802b50d3c86ba1137b66253</id>
<content type='text'>
Add a Build Host Requirements subsection covering the baked AUR repo: the v1 package set and audit date, the base-devel/git/sudo build-host needs, the makepkg -s host build-dep mutation, the manifest, and the installed-system disposition (packages installed, repo not retained). Document the --skip-aur toggle and add the AUR build to the build-steps list.
</content>
</entry>
<entry>
<title>feat(install): install baked AUR packages and clean the target config</title>
<updated>2026-06-10T04:45:00+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-10T04:45:00+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archangel/commit/?id=4e6f4cc66206f02e92d4a2ca2f414fad5a3439a1'/>
<id>urn:sha1:4e6f4cc66206f02e92d4a2ca2f414fad5a3439a1</id>
<content type='text'>
Wire the baked AUR repo into the installer. Before pacstrap, install_base checks whether the ISO shipped the repo and, if so, exposes [aur] in the live /etc/pacman.conf and reads the package names from the manifest, adding them to the pacstrap set so they install into the target offline. This mirrors the existing [archzfs] handling. pacstrap resolves repos from the live system, not $MNTPOINT.

The live config already carries [aur] from the shipped ISO config, so the append is idempotent by design. A --skip-aur ISO ships no repo, and aur_repo_available gates the whole path, so the installer still works there.

configure_system strips any [aur] stanza from the target /etc/pacman.conf. pacstrap installs a stock target config with no [aur], so this is defensive, but it guarantees the installed system never references /usr/share/aur-packages, which exists only on the live ISO.

Four new common.sh helpers carry the logic: aur_repo_available, append_aur_repo (idempotent), aur_manifest_names (the manifest is the source of what to install, so the list never drifts), and strip_repo_stanza. All four covered across Normal, Boundary, and Error.
</content>
</entry>
</feed>
