# ECP-0087: LAN-Capable iPXE/QEMU VM Module

Status: Implemented

## Context

`every.channel` already has reusable runner and netboot modules, but hosts that want a continuously-running iPXE test VM still have to carry ad hoc QEMU glue. That makes boot-path verification and downstream reuse harder, and it prevents hosts from declaratively opting into a LAN-visible guest for tuner discovery.

## Decision

1. Add `nixosModules.ec-ipxe-qemu` at `nix/modules/ec-ipxe-qemu.nix`.
2. Add a dedicated publisher guest module/output pair:
   - `nixosModules.ec-publisher-guest`
   - `nixosConfigurations.ec-publisher-x86_64`
   - `nixosConfigurations.ec-publisher-x86_64-netboot`
   This keeps the VM path explicitly publisher-oriented while leaving host-specific tuner/broadcast choices to downstream configs.
3. Define `services.every-channel.ipxe-qemu.*` options for:
   - persistent qcow2/state directory handling,
   - user-mode iPXE boot networking that chains to a configurable internet boot URL,
   - optional second NIC via `macvtap` for non-disruptive LAN presence,
   - guest sizing and raw QEMU argument overrides.
4. Run the guest as a persistent systemd service (`every-channel-ipxe-qemu`) with restart-on-exit semantics so host restarts or config switches naturally refresh the in-memory booted VM.
5. Enable one conservative instance on `ecp-forge` using the user-mode boot path only, so the module is exercised in-repo without assuming a local tuner LAN on the forge host.

## Alternatives Considered

- Keep host-specific shell glue outside `every.channel`. Rejected because downstream hosts cannot reuse or review the boot path as a first-class module.
- Require a Linux bridge on the host for LAN access. Rejected for now because it is more disruptive than `macvtap` and unnecessary for an initial deployment.
- Boot only with QEMU user networking. Rejected because tuner discovery needs a real LAN attachment on some hosts.

## Rollout / Teardown

- Rollout:
  - import `nixosModules.ec-ipxe-qemu`,
  - enable `services.every-channel.ipxe-qemu`,
  - set `lan.enable = true` plus `lan.macvtap.interface` on hosts that need LAN discovery.
- Teardown:
  - disable `services.every-channel.ipxe-qemu.enable`,
  - remove host options,
  - fall back to ad hoc QEMU or direct host publishers if needed.
