From bbc4b46f3062fad87ae29b76b4a6503383e0d915 Mon Sep 17 00:00:00 2001 From: Pedro Henrique Penna Date: Fri, 9 Oct 2026 18:10:28 -0300 Subject: [PATCH] doc: describe the Azure Linux guest in the design The design goals named only Alpine and Ubuntu userland although Azure Linux 3.0 is an implemented guest that CI boots on every backend. Add a design chapter for it beside the Ubuntu chapter, index it, and name it in the goals and the README quick start. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- README.md | 4 +- doc/design.md | 21 +++--- doc/design/goals.md | 2 +- doc/guests/azurelinux-guest.md | 124 +++++++++++++++++++++++++++++++++ 4 files changed, 138 insertions(+), 13 deletions(-) create mode 100644 doc/guests/azurelinux-guest.md diff --git a/README.md b/README.md index d7300d4f5..bc59b6aee 100644 --- a/README.md +++ b/README.md @@ -18,8 +18,8 @@ files, build tools, and benchmarks needed to use NVX. Python 3.10 or newer is required. The commands below download the prebuilt NVX package for the selected platform from the cloned revision's release when available, or from its nearest released first-parent ancestor otherwise, so no local build is required. A successful boot prints -`NVX-GUEST-BOOT-OK: alpine` and opens a root shell. Select Ubuntu userland with the same NVX kernel -by passing `--guest ubuntu`. +`NVX-GUEST-BOOT-OK: alpine` and opens a root shell. Select Ubuntu or Azure Linux userland with the +same NVX kernel by passing `--guest ubuntu` or `--guest azurelinux`. Exit cleanly from the guest with `/sbin/nvx-exit 0`. See the [setup](doc/setup.md) and [run](doc/run.md) guides for detailed prerequisites and runtime options. diff --git a/doc/design.md b/doc/design.md index d59f8f1b6..ebe9fd2c7 100644 --- a/doc/design.md +++ b/doc/design.md @@ -13,13 +13,14 @@ yet implemented; they are not part of the current machine contract. 5. [Time ABI](design/time-abi.md) 6. [Sandbox filesystem and agent architecture](design/sandbox-filesystem-and-agent-architecture.md) 7. [Ubuntu guest support](guests/ubuntu-guest.md) -8. [Snapshot and restore](design/snapshot-and-restore.md) -9. [Snapshot sharing and host storage](design/snapshot-sharing-and-host-storage.md) -10. [Host attachment model](design/host-attachment-model.md) -11. [Concurrency and trust boundaries](design/concurrency-and-trust-boundaries.md) -12. [Validation](design/validation.md) -13. [Current limits](design/current-limits.md) -14. [Remaining production work](design/remaining-production-work.md) -15. [Integrated implementation status](design/integrated-implementation-status.md) -16. [Component responsibility map](design/code-ownership-map.md) -17. [Copilot-driven adversarial testing](design/copilot-adversarial-testing.md) +8. [Azure Linux guest support](guests/azurelinux-guest.md) +9. [Snapshot and restore](design/snapshot-and-restore.md) +10. [Snapshot sharing and host storage](design/snapshot-sharing-and-host-storage.md) +11. [Host attachment model](design/host-attachment-model.md) +12. [Concurrency and trust boundaries](design/concurrency-and-trust-boundaries.md) +13. [Validation](design/validation.md) +14. [Current limits](design/current-limits.md) +15. [Remaining production work](design/remaining-production-work.md) +16. [Integrated implementation status](design/integrated-implementation-status.md) +17. [Component responsibility map](design/code-ownership-map.md) +18. [Copilot-driven adversarial testing](design/copilot-adversarial-testing.md) diff --git a/doc/design/goals.md b/doc/design/goals.md index 53a5d4d11..1aa270f3f 100644 --- a/doc/design/goals.md +++ b/doc/design/goals.md @@ -6,7 +6,7 @@ NVX provides a small, versioned virtual machine for running an x86-64 Linux guest without firmware or a PC platform. Its design has four primary goals: - boot the same uncompressed Linux-direct kernel with explicitly selected - Alpine or Ubuntu userland on Linux and Windows; + Alpine, Ubuntu, or Azure Linux userland on Linux and Windows; - keep the guest-visible machine independent of the selected hypervisor; - expose only a fixed, allowlisted set of devices; and - capture a running VM into immutable artifacts that can be restored in a new diff --git a/doc/guests/azurelinux-guest.md b/doc/guests/azurelinux-guest.md new file mode 100644 index 000000000..d8a72d95f --- /dev/null +++ b/doc/guests/azurelinux-guest.md @@ -0,0 +1,124 @@ +# Azure Linux guest support + +[Design index](../design.md) + +NVX runs Azure Linux 3.0 userland on its own Linux kernel. It builds one +artifact, `initramfs-azurelinux.cpio.gz`, which `nvx.py run --guest azurelinux` +boots for an interactive shell or a workload. The artifact boots no Azure Linux +kernel, firmware, or systemd, and it does not change the +[machine and device ABI](../design/machine-and-device-abi.md). + +[Build](../build.md), [Run](../run.md), and the +[command-line reference](../usage.md) cover the commands. This chapter +describes how the pieces fit together and why. + +## Role + +The Azure Linux initramfs is a workload guest, not a sandbox control +environment. Alpine remains the default guest of `run` and the only control +environment of `sandbox`: + +- the initramfs omits the sandbox init agent, so the common `/init` refuses + sandbox mode; +- the microVM test harness rejects the sandbox-control scenarios for Azure + Linux; and +- `build-distro-layer` accepts only Ubuntu, so there is no Azure Linux + sandbox layer. + +A restore takes the guest from the captured RAM and machine contract, so `run` +rejects `--guest azurelinux` together with `--restore-snapshot`. + +## Kernel policy + +The initramfs boots the same `build/vmlinux` as Alpine and Ubuntu. The +[Ubuntu chapter](ubuntu-guest.md#kernel-policy) describes what that kernel +provides and omits. Azure Linux support therefore means Azure Linux userland +under the NVX kernel policy, not compatibility with every Azure Linux +workload. + +## Root filesystem builder + +The initramfs is built only with Docker: `build-initramfs --guest azurelinux` +and `build-guest` with Azure Linux selected use the Docker build, and +`build-guest --native` refuses Azure Linux. The +[Dockerfile](../../docker/Dockerfile) defines the build from pinned inputs: + +- **Base image**: the Azure Linux 3.0 `base/core` container image from MCR, + pinned by digest. `SOURCE-MANIFEST.json` repeats the release, image, and + package-lock digest, and `scripts/nvx.py verify` fails when they disagree + with the build constants. +- **Supplemental packages** from the lock in + [`azurelinux/packages.lock.json`](../../azurelinux/packages.lock.json), + which adds `busybox` and `util-linux`, the source of `setpriv`, with their + dependencies. Each entry records the RPM's name, version, release, + architecture, URL, and SHA-256. The lock must name the same release, + architecture, and base image as the build, and every URL must point into the + Azure Linux 3.0 base repository on `packages.microsoft.com`. + +The build then: + +1. downloads each locked RPM and verifies its SHA-256; +2. inside the pinned base image, imports the Microsoft RPM signing key, + checks every RPM signature, installs the RPMs, and requires `ldd`, + `setpriv`, and BusyBox to be present; +3. records the installed RPM inventory for the package manifest; +4. installs the common NVX `/init`, the guest scripts it needs, and + statically linked helpers built from `guest/common`, so the helpers do not + depend on Azure Linux libraries; +5. links the BusyBox applets that the shared guest scripts expect, including + `/bin/sh`; every other command resolves to the Azure Linux packages; +6. gives the `nobody` account, UID 65534, the empty home `/nonexistent` + instead of `/dev/null`, because workload identities need an existing home + directory; and +7. removes the RPM and package-manager databases and caches, which record + install-time state. + +The archive is packed with root ownership, timestamps set to the Unix epoch, a +sorted file order, and no compression timestamp, so a rebuild from the same +inputs is intended to be byte-identical. Unlike the Ubuntu artifacts, no +automated check compares two Azure Linux rebuilds. + +## Azure Linux initramfs + +The Azure Linux initramfs boots like the Alpine one at the machine level: +OpenVMM loads the kernel and initramfs through the +[Linux direct MP-table loader](../design/cold-boot.md#linux-direct-mp-table-loader), +and the common [`/init`](../../guest/common/init) runs as PID 1. It runs the +same boot steps as for the other guests, including the +[time ABI](../design/time-abi.md) boot step, and then runs an `nvx_exec` +workload, starts the managed agent, or opens a shell. The managed agent runs +the workload directly in the initramfs root, not in a separate layer. On the +shell path, `/init` reads the guest identity from `/etc/os-release`, stops on +an unknown one, prints `NVX-GUEST-BOOT-OK: azurelinux`, and starts the +BusyBox shell. + +The guest defaults to 512 MiB, like Ubuntu, because the kernel unpacks the +initramfs into a RAM filesystem capped at half of guest memory; see +[Run](../run.md). + +## Provenance and corresponding source + +The package manifest `initramfs-azurelinux.cpio.gz.packages.json` records the +release, architecture, base image, input digest, and artifact SHA-256. Each +package entry names the RPM's version, release, architecture, license, and +source RPM. The manifest also records the source and binary digests of the +freestanding device-I/O helper. The input digest is a domain-separated SHA-256 +over the release, architecture, base image, and the checkout files that define +the build: the Dockerfile, the package lock, the build modules that download +the RPMs and compute the digest, and `guest/common`. + +Release staging rejects a manifest that does not match the artifact, the base +image, or the current inputs. Only binary-only packages carry the two Azure +Linux files; the published platform releases are binary-only, and `download` +installs them. `collect-sources` does not collect Azure Linux corresponding +source, so `package --include-source` omits the guest; see +[Package and source delivery](../distribution.md) and the +[release layout](../build.md). + +## Validation + +CI rebuilds the initramfs in Docker when its inputs change. The +[microVM test workflow](../../.github/workflows/run-nvx-microvm-tests.yml) +runs Azure Linux boot, identity, console exit, network, network snapshot, +workload identity, and managed lifecycle scenarios with one processor on every +backend. Azure Linux is not part of the performance gates.