Skip to content

VM Image - #193

Merged
jonringer merged 19 commits into
masterfrom
jonringer/vm-image
Oct 8, 2026
Merged

jonringer merged 19 commits into
masterfrom
jonringer/vm-image

Conversation

@jonringer

Copy link
Copy Markdown
Collaborator

Get the diskImage build working, and have it be able to run using QEMU

…ules: init

Port disk image and ISO creation dependencies from nixpkgs, and add
aggregateModules for combining kernel module trees with depmod.
virtiofs requires KVM (vhost-user-fs-pci). Switch to 9p which works
with software-only QEMU emulation, enabling VM-based builds on any host.
- Disable structuredAttrs (script uses plain string variables)
- Guard firmware directory operations when firmware list is empty
- Always create insmod-list even when all modules are builtin
The builder script was missing entirely. Also disable structuredAttrs
since substituteAll relies on environment variables being exported as
plain strings.
Add makeInitrd and makeModulesClosure to kernel passthru so
linuxPackages.kernel.makeInitrd is available for initrd creation.

Mark IPV6_FOU_TUNNEL as optional module to fix config check when the
option is built-in.
Major overhaul of the initramfs builder:
- Use static busybox for all basic utilities (mount, modprobe, sh, etc.)
- Add blkid for UUID-based root device lookup without udev
- Use makeModulesClosure for minimal module set instead of aggregateModules
- Decompress .ko.xz modules for busybox modprobe compatibility
- Create combined /lib with shared libraries and kernel modules
- Set up /sbin/modprobe for kernel request_module() autoloading
- Parse root=UUID= from kernel cmdline, wait for device to appear
- Parse init= for correct switch_root target
- Redirect output to serial console for VM debugging
- Properly patchelf dynamic binaries after nuke-refs
Pass EKAOS_INSTALL_BOOTLOADER through nixos-enter so the bootloader
installer runs inside the chroot. Add dosfstools to binPath for ESP
formatting.
switch-to-configuration now respects EKAOS_INSTALL_BOOTLOADER (and
NIXOS_INSTALL_BOOTLOADER for compatibility). When set, it runs
install-bootloader and writes a fallback boot entry directly if no
generation entries exist. Fix bootspec (boot.json) generation for
structuredAttrs compatibility.
Set PATH in stage-2 init to include essential system utilities so
commands like mountpoint, mkdir, mount are found.

Fix SYSTEMD_UNIT_PATH to use trailing colon (append to defaults)
instead of replacing the entire search path.
The systemd package moves units from lib/ to example/ during build.
Fix all target symlinks to use the correct example/systemd/system/ path
and add the full set of targets needed for the boot chain.

Add SYSTEMD_UNIT_PATH entry so systemd discovers all packaged units
(services, sockets, etc.) at runtime.

Add 00-ekaos.preset to disable services that fail without extra
configuration (firstboot, resolved, timesyncd, networkd, homed, oomd,
pcrlock, sysext, etc.) preventing them from blocking the boot.
Fix references to systemd-vconsole-setup.service,
systemd-user-sessions.service, and systemd-networkd.service to use
example/systemd/system/ instead of lib/systemd/system/.

Remove /dev/null placeholder entries in multi-user.target.wants/ that
caused cp -rL failures during activation.
Use cp -rfL instead of cp -rL with || true so errors are visible and
existing files are overwritten.

Generate /etc/machine-id during activation to prevent systemd from
entering first-boot mode (which runs the interactive firstboot wizard).
Expose image build outputs at the top level when their respective
modules are enabled, so they can be built directly from the eval-config
entry point.
Example module that builds a bootable QEMU disk image with UEFI boot,
initrd with virtio modules, and serial console support.
Services with ConditionXxx= (pcrlock, tpm2, pstore, sysext, oomd,
boot-update, etc.) skip gracefully when their conditions aren't met —
no need to disable them in the preset.

Only disable services that run as dedicated system users (resolved,
networkd, timesyncd, oomd) which the corresponding ekaos modules
create when opted in, plus firstboot and homed.
Add boot-test.nix, a test runner that boots an ekaos system in QEMU
without building a disk image.  The nix store is shared via 9p with a
tmpfs overlay, and kernel modules (9p, overlay, virtio) are loaded from
a minimal decompressed initrd.  Serial output is checked for "Startup
finished" to confirm the default target was reached.

Add boot-to-multiuser test that validates the full boot chain:
  kernel → initrd → 9p+overlay mount → stage-2 → systemd → multi-user
The module was setting system.build.pinsFile without declaring it,
causing evaluation to fail with "option does not exist".
scripts/unit fails in the build sandbox.
Add an assertion that rejects __structuredAttrs = false. All derivation
attributes that need to be visible as environment variables should use
the `env` attrset instead.

Fix substituteAll to work under structuredAttrs by routing substitution
variables through `env`. Remove stale __structuredAttrs = false from
initrd-utils and boot-test-initrd runCommands.
@jonringer
jonringer marked this pull request as ready for review October 8, 2026 14:54
@jonringer
jonringer merged commit afa06c5 into master Oct 8, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant