Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
21 changes: 11 additions & 10 deletions doc/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
2 changes: 1 addition & 1 deletion doc/design/goals.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
124 changes: 124 additions & 0 deletions doc/guests/azurelinux-guest.md
Original file line number Diff line number Diff line change
@@ -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.
Loading