diff --git a/README.md b/README.md index cadcfb0..3ff361c 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ An atomic Linux host keeps its base system read-only and replaceable. You still ## What you get -- **Seven signed distros.** Debian 13, Ubuntu 26.04 LTS, Fedora 44, CentOS Stream 10, Arch, and openSUSE Tumbleweed and Leap 16.0, rebuilt weekly and verified against the Frostyard publishing workflow before use. [Machine images →](https://frostyard.github.io/nsl/reference/machine-images/) +- **Eight signed distros.** Debian 13, Ubuntu 26.04 LTS, Fedora 44, CentOS Stream 10, Arch, openSUSE Tumbleweed and Leap 16.0, and the Azure Linux 4.0 beta, rebuilt weekly and verified against the Frostyard publishing workflow before use. [Machine images →](https://frostyard.github.io/nsl/reference/machine-images/) - **Your files and your account.** Your home, removable media and `/mnt` appear at `/mnt/host`, and you have your own username, UID and GID with passwordless `sudo`. [Host files →](https://frostyard.github.io/nsl/guides/host-files/) - **Ports and windows on the host.** A server in a machine is reachable at the same port on host `127.0.0.1`, and Wayland applications open windows on your desktop. [Ports →](https://frostyard.github.io/nsl/guides/ports/) · [Desktop applications →](https://frostyard.github.io/nsl/guides/desktop/) - **Your editor.** `nsl ssh-config` gives VS Code or any SSH client a host alias for a machine. [Editors over SSH →](https://frostyard.github.io/nsl/guides/editors/) diff --git a/docs/README.md b/docs/README.md index 227740e..4deb152 100644 --- a/docs/README.md +++ b/docs/README.md @@ -56,6 +56,7 @@ The binary implements the whole CLI contract: machines in the shared VM or, isol - [Machines in a shared VM](plans/shared-vm-implementation.md) — implementation of ADR-0016 and ADR-0017; start here for new work. - [Ubuntu, CentOS Stream and openSUSE Leap machine images](plans/more-machine-images.md) — three more machine images, accepted and published. +- [Azure Linux 4.0 machine image](plans/azure-linux.md) — Microsoft's Fedora-based beta in the rpm family. - [Shared-VM experiment](plans/shared-vm-experiment.md) — machines as containers in one VM; evidence for ADR-0017. - [Optional cloud-init provisioning](plans/cloud-init-provisioning.md) — deferred until cloud-init is re-validated in machines. diff --git a/docs/adr/0009-distribution-neutral-guest-contract.md b/docs/adr/0009-distribution-neutral-guest-contract.md index 8e75772..5b49745 100644 --- a/docs/adr/0009-distribution-neutral-guest-contract.md +++ b/docs/adr/0009-distribution-neutral-guest-contract.md @@ -20,7 +20,7 @@ Keep the host CLI and the VM agent distribution-neutral. Define one [machine-ima Creation applies only per-machine data: account, hostname, time zone, `sudo` rule and nspawn settings. - Fail clearly when a required capability is missing. Do not infer support from a distro name, `ID_LIKE`, a successful boot or a package install. -- Support a distro release only after its image passes acceptance. Debian 13, Fedora 44, Arch and openSUSE Tumbleweed came first; Ubuntu 26.04 LTS, CentOS Stream 10 and openSUSE Leap 16.0 followed. Track SUSE Linux Enterprise separately, including access and redistribution terms. +- Support a distro release only after its image passes acceptance. Debian 13, Fedora 44, Arch and openSUSE Tumbleweed came first; Ubuntu 26.04 LTS, CentOS Stream 10 and openSUSE Leap 16.0 followed, then Azure Linux 4.0. A release its distro still calls beta may join on the same terms, and the user documentation marks it as a beta. Track SUSE Linux Enterprise separately, including access and redistribution terms. - Keep guest distro, host distro and CPU architecture independent. Start with x86-64. - Every published image pins its recipe and integration revisions and records package inputs, provenance and acceptance results. - Distro MAC policy does not apply inside machines. Document that plainly; do not claim a distro's SELinux or AppArmor behavior. diff --git a/docs/design/image-publication.md b/docs/design/image-publication.md index b5ef23d..99e442d 100644 --- a/docs/design/image-publication.md +++ b/docs/design/image-publication.md @@ -12,7 +12,7 @@ A self-hosted runner labeled `nsl-image-builder` supplies the host prerequisites `scripts/publish-images.py build`: -1. runs `make ci`, then builds the VM image and the seven machine images from pinned recipes; +1. runs `make ci`, then builds the VM image and every machine image from pinned recipes; 2. runs `probe-vm.py` on the VM image; 3. runs `probe-machines.py` with every machine image, an isolated machine and `--gui`, so every declared capability is accepted: `gui` by the GUI check and `nesting` by the Podman check; 4. runs `measure-machines.py` with the Debian, Fedora, Arch and Tumbleweed images, the four that set the budget: four idle machines at or below 1,200 MiB without desktop sessions, as the experiment measured, and an additional machine at p95 ≤ 2 s. The budget comes from the publication runner's measurements ([ADR-0019](../adr/0019-persistent-publication-runner.md)). The acceptance report also records what four desktop sessions add, ungated; diff --git a/docs/plans/azure-linux.md b/docs/plans/azure-linux.md new file mode 100644 index 0000000..c55bcbf --- /dev/null +++ b/docs/plans/azure-linux.md @@ -0,0 +1,44 @@ +# Plan: Azure Linux 4.0 machine image + +**Status: Phase 1 complete, 2026-10-08. Phase 2 waits for a publication run.** + +Add Azure Linux 4.0, Microsoft's Fedora-based cloud distribution, as a machine image in the `rpm` family. It joins the catalogue only after it passes the [machine-image acceptance](../specs/machine-images.md#acceptance), under [ADR-0009](../adr/0009-distribution-neutral-guest-contract.md). + +Azure Linux 4.0 is a beta. Microsoft publishes it only under `packages.microsoft.com/azurelinux/4.0/beta/`, with `base`, `microsoft`, `nvidia` and `sdk` repositories; the image's own repository files enable `base` and `microsoft`. Packages and repository metadata are signed with the Mariner release key (`0CD9FED33135CE90`), the key mkosi already trusts for Azure Linux 3.0 through `distribution-gpg-keys`. + +## Phase 1 — Profile and acceptance + +- **Profile.** `image/machines/profiles/azurelinux/`, distribution `azure` (mkosi's name) and release `4.0`, in the `rpm` family with the Fedora 44 tools tree. Every rpm-family adapter package is in the beta `base` repository. + - mkosi v27's Azure Linux support builds `4.0/prod/REPO/ARCH` URLs, which do not exist for 4.0. `LocalMirror=` reads `4.0/beta/base/x86_64/` for the build and leaves the image's repository files to the distro. + - The pinned recipes (`68263d0`) have no Azure Linux recipe, so the profile names what Fedora's recipe adds that 4.0 packages: `dnf5`, `dbus-broker`, `glibc-langpack-en`, `iproute`, `iputils`, `pam`, `util-linux` and `vim-minimal`. A post-install script links `/etc/resolv.conf` to `/run/systemd/resolve/stub-resolv.conf`, as every recipe does. + - `azurelinux-release-common` requires `azurelinux-repos(4.0)`, which both `azurelinux-repos` and `azurelinux-repos-dev` provide. The dev package points dnf at an internal development feed with `gpgcheck=0`, so the profile names `azurelinux-repos`. +- **Probe.** Azure Linux 4.0 packages no `wayland-utils`, and its enabled repositories have none of galculator, zenity or foot. On Azure Linux, `probe-machines.py` lists the compositor's globals with a Python client of the Wayland protocol, and opens `gtk-lshw` from `lshw-gui`, a GTK 3 window that waits for an answer when run without `pkexec`. +- **Done when:** the image builds, and every check of `probe-machines.py --gui` passes on it beside a Debian peer with VM image r10. + +**Result, 2026-10-08: complete.** + +| Image | systemd | Size (zstd) | Entry latency, median | +| --- | --- | --- | --- | +| `nsl-machine-azure-4.0-x86-64-r1` | 258.4 | 71 MB | 62 ms | + +- **Build.** The image built on the first attempt in a fresh builder, from `azurelinux-release` 4.0-26 and 138 packages, with the signed `azurelinux-repos` and the basic release identity. Its os-release reads `Azure Linux 4.0 (Four Beta)`. It is the smallest image in the catalogue. +- **Acceptance** (`azure-probe-1.json`, VM image r10 `511a0431…` built from this branch, `--gui`): an Azure Linux machine and the published Debian r5 image ran 24 checks, and all passed. On Azure Linux, systemd reached `running` with no failed units, every tally check passed, and the packages check installed Python, jq, Podman 5.8 and `lshw-gui` from the beta repository in 44 s. The Python client found 33 globals, including `wl_compositor` and `xdg_wm_base`, and `gtk-lshw` held a window open until the timeout. Creation took 12 s and the first start 1.4 s. + +## Phase 2 — Publication + +- Add the selectors `azurelinux:4.0` and `azure-linux:4.0` to the publisher, and list the image as a beta in the user documentation. +- **Done when:** a signed catalogue lists the image, and `nsl create` works from `azurelinux:4.0` on a host with an empty cache. + +## Later / ideas + +- Move to Microsoft's production repositories when Azure Linux 4.0 leaves beta. The image's `azurelinux-repos` follows the distro; the profile's `LocalMirror=` changes with it, or goes once mkosi builds the right URLs for 4.0. +- An Azure Linux recipe upstream in `nspawn/mkosi-definitions` would replace the profile's package list and post-install script. + +## Open questions + +- Should the probe list Wayland globals with its Python client for every image, and drop `wayland-utils` from the workload? It stays limited to Azure Linux until another distro lacks `wayland-info`. + +## References + +- Implements: [machine images](../specs/machine-images.md), [image publication](../design/image-publication.md), [ADR-0009](../adr/0009-distribution-neutral-guest-contract.md). +- Follows: [Ubuntu, CentOS Stream and openSUSE Leap machine images](more-machine-images.md). diff --git a/docs/plans/more-machine-images.md b/docs/plans/more-machine-images.md index 44928ba..40e7728 100644 --- a/docs/plans/more-machine-images.md +++ b/docs/plans/more-machine-images.md @@ -46,6 +46,7 @@ Add the three machine images that [ADR-0009](../adr/0009-distribution-neutral-gu - Further releases of the same families, such as Debian 12, Ubuntu 24.04 LTS, Fedora 43 or CentOS Stream 9, each as a profile that passes acceptance. - AlmaLinux and Rocky Linux, which the recipes also carry, in the `rpm` family. +- Azure Linux 4.0, which the recipes do not carry: [its own plan](azure-linux.md). - Track SUSE Linux Enterprise separately, including access and redistribution terms ([ADR-0009](../adr/0009-distribution-neutral-guest-contract.md)). ## Open questions diff --git a/docs/specs/machine-images.md b/docs/specs/machine-images.md index 66183dc..a45b1b2 100644 --- a/docs/specs/machine-images.md +++ b/docs/specs/machine-images.md @@ -21,10 +21,11 @@ A machine image is one root filesystem tree, packaged as `rootfs.tar.zst` in a s | `arch:rolling`, `arch:btw` | `arch` | No `/etc/pacman.d/gnupg` in the image: the recipe's keyring, with its master private key, is deleted after the recipe's own scripts run. `nsl-pacman-keyring.service` runs `pacman-key --init` and `--populate` on first boot. Fedora 44 tools tree. | | `opensuse:tumbleweed`, `opensuse-tumbleweed:rolling` | `suse` | `shadow`, `timezone`, and `glibc-locale-base` for `C.UTF-8`; openSUSE Tumbleweed tools tree. | | `opensuse:16.0`, `opensuse-leap:16.0` | `suse` | The suse family's packages; openSUSE Tumbleweed tools tree. | +| `azurelinux:4.0`, `azure-linux:4.0` | `rpm` | A beta: Microsoft publishes Azure Linux 4.0 only under `packages.microsoft.com/azurelinux/4.0/beta`, which the build reads directly, since mkosi expects `prod`. The recipes have no Azure Linux recipe, so the profile adds what Fedora's adds: `dnf5`, `dbus-broker`, `glibc-langpack-en` and base tools, and links `/etc/resolv.conf` to the VM's resolver. It names `azurelinux-repos`: `azurelinux-repos-dev` also satisfies the release package and points dnf at an unsigned development feed. Fedora 44 tools tree. | Each adapter also names its family's `sudo`, CA certificates, OpenSSH server, DejaVu font, Adwaita cursors and Wayland client libraries. -Other distros and releases join after they pass acceptance ([plan](../plans/more-machine-images.md)). +Other distros and releases join after they pass acceptance ([plan](../plans/more-machine-images.md), [Azure Linux](../plans/azure-linux.md)). ### Machine layer @@ -108,6 +109,8 @@ Workload checks: | Translation | The working directory maps by device and inode, including a bind-mount alias; `/usr/share` is refused. | | Persistence | Packages, home, an enabled system service and a Podman image survive a VM restart. | +Azure Linux 4.0 packages no `wayland-info`. On it, the probe lists the compositor's globals with a Python client of the Wayland protocol instead. + Checks that an image does not repeat the [hub image tally](../plans/shared-vm-experiment.md#image-source-tally-hubnspawnorg-or-our-own): | Check | Expected | diff --git a/image/README.md b/image/README.md index eb5fe1e..35dfe05 100644 --- a/image/README.md +++ b/image/README.md @@ -3,7 +3,7 @@ nsl builds its images from pinned [nspawn/mkosi-definitions](https://github.com/nspawn/mkosi-definitions) recipes with mkosi v27, inside a disposable Lima builder. There are two kinds ([ADR-0017](../docs/adr/0017-shared-vm-and-machine-images.md)): - **The nsl VM image** (`vm/`): the Debian trixie disk that every nsl VM boots. It hosts machines as systemd-nspawn containers and runs the nsl agent. Contract: [VM image](../docs/specs/vm-image.md). -- **Machine images** (`machines/`): distro root filesystems that run as machines: Debian 13, Ubuntu 26.04 LTS, Fedora 44, CentOS Stream 10, Arch, openSUSE Tumbleweed and openSUSE Leap 16.0. Contract: [machine images](../docs/specs/machine-images.md). +- **Machine images** (`machines/`): distro root filesystems that run as machines: Debian 13, Ubuntu 26.04 LTS, Fedora 44, CentOS Stream 10, Arch, openSUSE Tumbleweed, openSUSE Leap 16.0 and Azure Linux 4.0, a beta. Contract: [machine images](../docs/specs/machine-images.md). ## Build the VM image @@ -43,20 +43,20 @@ The composer copies the agent to `/usr/lib/nsl/nsl-agent` and writes `/usr/lib/n ## Build machine images ```sh -scripts/build-image.sh --role machine --distribution debian # also ubuntu, fedora, centos, arch, opensuse +scripts/build-image.sh --role machine --distribution debian # also ubuntu, fedora, centos, arch, opensuse, azure scripts/build-image.sh --role machine --distribution opensuse --release 16.0 # Leap; opensuse alone is Tumbleweed python3 scripts/probe-machines.py --nsl build/nsl --vm-image build/image/share/nsl-vm-trixie-x86-64-r9.raw \ --machine-image build/image/share/nsl-machine-debian-trixie-x86-64-r4.tar.zst \ --evidence build/image/evidence/machines-probe.json [--gui] ``` -A machine build uses the recipe's container output without the disk profile, as a zstd tar: `nsl-machine-DISTRIBUTION-RELEASE-x86-64-rN.tar.zst`, with its manifest and the descriptor as built. Debian builds with the builder's own tools. Ubuntu, Fedora, CentOS Stream and Arch use a Fedora 44 tools tree, and Tumbleweed and Leap an openSUSE Tumbleweed one; the builder keeps mkosi's cache in `/var/cache/nsl-mkosi` between builds. Bump the profile's revision in `machines/profiles/NAME/profile.json` when inputs change. +A machine build uses the recipe's container output without the disk profile, as a zstd tar: `nsl-machine-DISTRIBUTION-RELEASE-x86-64-rN.tar.zst`, with its manifest and the descriptor as built. Debian builds with the builder's own tools. Ubuntu, Fedora, CentOS Stream, Arch and Azure Linux use a Fedora 44 tools tree, and Tumbleweed and Leap an openSUSE Tumbleweed one; the builder keeps mkosi's cache in `/var/cache/nsl-mkosi` between builds. Bump the profile's revision in `machines/profiles/NAME/profile.json` when inputs change. `machines/` composes three layers: 1. `common/`: the machine layer. It holds the `nsl` PAM service, the nesting mount and its preset, the Podman drop-in, `nsl-path`, and `nsl-osc7.sh`, which reports the working directory to VTE terminals. Its finalize script, which runs after the recipes' own scripts, masks every networkd and resolved unit and disables SSH services. It also removes SSH host keys and the random seed, sets the machine ID to `uninitialized`, and fills in the descriptor. -2. `families/FAMILY/`: packages, the tools tree and family fixes, such as Arch's keyring deletion and first-boot `nsl-pacman-keyring.service`. Families are `debian` (Debian and Ubuntu), `rpm` (Fedora and CentOS Stream), `arch` and `suse` (Tumbleweed and Leap). -3. `profiles/NAME/`: the distribution, release and revision, and settings for that distribution alone, such as Ubuntu's tools tree. +2. `families/FAMILY/`: packages, the tools tree and family fixes, such as Arch's keyring deletion and first-boot `nsl-pacman-keyring.service`. Families are `debian` (Debian and Ubuntu), `rpm` (Fedora, CentOS Stream and Azure Linux), `arch` and `suse` (Tumbleweed and Leap). +3. `profiles/NAME/`: the distribution, release and revision, and settings for that distribution alone, such as Ubuntu's tools tree. The recipes have no Azure Linux recipe, so its profile names the packages and the `resolv.conf` link that a recipe would add, and reads Microsoft's beta repository. Create a machine from a local build with `nsl create NAME --image FILE --digest sha256:HEX`. `probe-machines.py` runs the agent's entry matrix, the hub-image tally checks and the workload checks through the CLI. diff --git a/image/machines/profiles/azurelinux/mkosi.conf b/image/machines/profiles/azurelinux/mkosi.conf new file mode 100644 index 0000000..73bad4b --- /dev/null +++ b/image/machines/profiles/azurelinux/mkosi.conf @@ -0,0 +1,20 @@ +[Distribution] +# Azure Linux 4.0 publishes only a beta channel, under beta/ rather than the prod/ +# that mkosi's repositories assume. The build reads the base repository directly; +# the image's own repository files come from azurelinux-repos. +LocalMirror=https://packages.microsoft.com/azurelinux/4.0/beta/base/x86_64/ + +[Content] +# The recipes carry no Azure Linux recipe, so the profile names what Fedora's adds. +# azurelinux-repos-dev also provides azurelinux-repos(4.0) and points dnf at an +# unsigned development feed; naming azurelinux-repos keeps the signed one. +Packages=azurelinux-repos + dbus-broker + dnf5 + glibc-langpack-en + iproute + iputils + pam + util-linux + vim-minimal +PostInstallationScripts=nsl-azure-postinst.chroot diff --git a/image/machines/profiles/azurelinux/nsl-azure-postinst.chroot b/image/machines/profiles/azurelinux/nsl-azure-postinst.chroot new file mode 100755 index 0000000..027b281 --- /dev/null +++ b/image/machines/profiles/azurelinux/nsl-azure-postinst.chroot @@ -0,0 +1,5 @@ +#!/bin/sh +# What the recipes do for every other distribution: machines bind the VM's +# resolver at /run/systemd/resolve. +set -eu +ln -sf ../run/systemd/resolve/stub-resolv.conf /etc/resolv.conf diff --git a/image/machines/profiles/azurelinux/profile.json b/image/machines/profiles/azurelinux/profile.json new file mode 100644 index 0000000..c028613 --- /dev/null +++ b/image/machines/profiles/azurelinux/profile.json @@ -0,0 +1,7 @@ +{ + "distribution": "azure", + "release": "4.0", + "architecture": "x86-64", + "family": "rpm", + "revision": 1 +} diff --git a/scripts/build-image.sh b/scripts/build-image.sh index 5d79ef5..32fe960 100755 --- a/scripts/build-image.sh +++ b/scripts/build-image.sh @@ -18,7 +18,7 @@ while (($#)); do (($# >= 2)) || { echo "Missing value for $1" >&2; exit 2; } selection+=("$1" "$2"); shift 2 ;; --help|-h) - echo 'Usage: scripts/build-image.sh --role vm | --role machine --distribution debian|ubuntu|fedora|centos|arch|opensuse [--release RELEASE]' + echo 'Usage: scripts/build-image.sh --role vm | --role machine --distribution debian|ubuntu|fedora|centos|arch|opensuse|azure [--release RELEASE]' exit 0 ;; *) echo "Unknown option: $1" >&2; exit 2 ;; esac diff --git a/scripts/compose-image.py b/scripts/compose-image.py index d3f6c33..1a8519a 100644 --- a/scripts/compose-image.py +++ b/scripts/compose-image.py @@ -21,6 +21,7 @@ ('ubuntu', 'resolute'): 'ubuntu', ('centos', '10'): 'centos', ('opensuse', '16.0'): 'opensuse-leap', + ('azure', '4.0'): 'azurelinux', } diff --git a/scripts/probe-machines.py b/scripts/probe-machines.py index 933a70f..591c56b 100755 --- a/scripts/probe-machines.py +++ b/scripts/probe-machines.py @@ -40,7 +40,7 @@ import urllib.request import uuid -WORKLOAD = ['python3', 'jq', 'podman', 'wayland-utils'] +WORKLOAD = ['python3', 'jq', 'podman'] # Package commands by the descriptor's family. INSTALL = { 'debian': lambda pkgs: ['env', 'DEBIAN_FRONTEND=noninteractive', 'apt-get', 'install', '-y', '-qq', *pkgs], @@ -65,10 +65,43 @@ # Podman 5 defaults to pasta networking; Arch packages it separately. EXTRA = {'arch': ['passt']} # A Wayland application's package and command, by distribution. galculator is not -# packaged for openSUSE or CentOS Stream 10: foot is a Wayland-native terminal and -# zenity a GTK 4 dialog. -GUI_APP = {'opensuse': ('foot', ['foot']), 'centos': ('zenity', ['zenity', '--info', '--text=nsl'])} +# packaged for openSUSE, CentOS Stream 10 or Azure Linux 4.0: foot is a Wayland-native +# terminal, zenity a GTK 4 dialog, and gtk-lshw, run without lshw-gui's pkexec, a +# GTK 3 window that waits for an answer. +GUI_APP = {'opensuse': ('foot', ['foot']), 'centos': ('zenity', ['zenity', '--info', '--text=nsl']), + 'azure': ('lshw-gui', ['gtk-lshw'])} DEFAULT_GUI_APP = ('galculator', ['galculator']) +# The compositor's globals as wayland-info prints them: wl_display.get_registry and +# a sync, then each wl_registry.global until the callback is done. +WAYLAND_GLOBALS = r''' +import os, socket, struct, sys +display = os.environ['WAYLAND_DISPLAY'] +s = socket.socket(socket.AF_UNIX) +s.connect(os.path.join(os.environ.get('XDG_RUNTIME_DIR', '/'), display)) +s.sendall(struct.pack('/dev/null && echo $c; done').text.split() + present = p.m(name, 'sh', '-c', f'for c in python3 jq podman {info[0]} {command[0]}; do command -v $c >/dev/null && echo $c; done').text.split() removed = p.m(name, 'sudo', '-n', *REMOVE[family], timeout=600) gone = p.m(name, 'sh', '-c', 'command -v jq').returncode != 0 sudo = p.m(name, 'sudo', '-n', 'id', '-u') - return {'pass': r.returncode == 0 and set(present) >= {'python3', 'jq', 'podman', 'wayland-info'} and removed.returncode == 0 and gone and sudo.text == '0', + return {'pass': r.returncode == 0 and set(present) >= {'python3', 'jq', 'podman', info[0]} and removed.returncode == 0 and gone and sudo.text == '0', 'install_seconds': install, 'present': present, 'install_error': tail(r.err) if r.returncode else '', 'sudo': sudo.text} @@ -508,7 +543,7 @@ def desktop_env(p, name, variable): def check_gui(p, name, machine): """A window through the machine's persistent desktop session.""" display = desktop_env(p, name, 'WAYLAND_DISPLAY') - info = p.m(name, 'wayland-info', timeout=60) + info = p.m(name, *WAYLAND_INFO.get(machine['distribution'], DEFAULT_WAYLAND_INFO)[1], timeout=60) interfaces = sorted({line.split("'")[1] for line in info.text.splitlines() if "interface: '" in line}) # Chromium, Electron and Qt pick Wayland by the session type; logind keeps the background class. session = p.m(name, 'sh', '-c', 'printf "%s/%s " "$XDG_SESSION_TYPE" "$XDG_SESSION_CLASS"; ' diff --git a/scripts/publish-images.py b/scripts/publish-images.py index 0665c50..277953e 100644 --- a/scripts/publish-images.py +++ b/scripts/publish-images.py @@ -35,7 +35,8 @@ ('opensuse', 'tumbleweed'): ['opensuse:tumbleweed', 'opensuse-tumbleweed:rolling'], ('ubuntu', 'resolute'): ['ubuntu:resolute', 'ubuntu:26.04'], ('centos', '10'): ['centos:10', 'centos-stream:10'], - ('opensuse', '16.0'): ['opensuse:16.0', 'opensuse-leap:16.0']} + ('opensuse', '16.0'): ['opensuse:16.0', 'opensuse-leap:16.0'], + ('azure', '4.0'): ['azurelinux:4.0', 'azure-linux:4.0']} # The memory budget was set with these four idle machines; measure the same four. MEASURED = [('debian', 'trixie'), ('fedora', '44'), ('arch', 'rolling'), ('opensuse', 'tumbleweed')] # Payload files and the client's bounds (docs/specs/image-delivery.md#bounds). diff --git a/scripts/test_image_profiles.py b/scripts/test_image_profiles.py index 91232a3..304d7ef 100644 --- a/scripts/test_image_profiles.py +++ b/scripts/test_image_profiles.py @@ -101,7 +101,7 @@ def test_machine_images_compose_each_family(self): with tempfile.TemporaryDirectory() as tmp: for distribution, release, family in [('debian', 'trixie', 'debian'), ('ubuntu', 'resolute', 'debian'), ('fedora', '44', 'rpm'), ('centos', '10', 'rpm'), ('arch', 'rolling', 'arch'), ('opensuse', 'tumbleweed', 'suse'), - ('opensuse', '16.0', 'suse')]: + ('opensuse', '16.0', 'suse'), ('azure', '4.0', 'rpm')]: destination = Path(tmp)/f'{distribution}-{release}' profile = compose.select(ROOT, 'machine', distribution, release) name = compose.compose(ROOT, destination, profile, 'recipes-pin', 'mkosi-pin') @@ -123,6 +123,11 @@ def test_machine_images_compose_each_family(self): self.assertEqual((destination/'mkosi.tools.conf').is_file(), distribution != 'debian') self.assertEqual(config.rsplit('ToolsTree=', 1)[1].split()[0], 'no' if distribution == 'debian' else 'default') self.assertIn('nsl-arch-finalize.chroot', (Path(tmp)/'arch-rolling/mkosi.local.conf').read_text()) + # Azure Linux 4.0 builds from its beta repository and keeps the signed repository package, not the dev feed. + azure = (Path(tmp)/'azure-4.0/mkosi.local.conf').read_text() + self.assertIn('LocalMirror=https://packages.microsoft.com/azurelinux/4.0/beta/base/x86_64/', azure) + self.assertIn('Packages=azurelinux-repos\n', azure) + self.assertEqual((Path(tmp)/'azure-4.0/nsl-azure-postinst.chroot').stat().st_mode & 0o777, 0o755) def test_osc7_reports_the_directory_in_vte_terminals(self): script = str(ROOT/'image/machines/common/overlay/etc/profile.d/nsl-osc7.sh') diff --git a/site/content/contributing/build.md b/site/content/contributing/build.md index 8e3e934..27d862b 100644 --- a/site/content/contributing/build.md +++ b/site/content/contributing/build.md @@ -63,7 +63,7 @@ build/nsl create debian --image "$machine" --digest "sha256:$(sha256sum "$machin Each build prints a `Built PATH` line. Use that path for `image` or `machine` if the profile revision differs from these examples. -`--distribution` also takes `ubuntu`, `fedora`, `centos`, `arch` and `opensuse`; `--distribution opensuse --release 16.0` builds Leap. The [image build notes ↗](https://github.com/frostyard/nsl/blob/main/image/README.md) describe the layers and the builder. +`--distribution` also takes `ubuntu`, `fedora`, `centos`, `arch`, `opensuse` and `azure`; `--distribution opensuse --release 16.0` builds Leap. The [image build notes ↗](https://github.com/frostyard/nsl/blob/main/image/README.md) describe the layers and the builder. ## Accept images in disposable VMs diff --git a/site/content/index.md b/site/content/index.md index f767014..c12b611 100644 --- a/site/content/index.md +++ b/site/content/index.md @@ -45,11 +45,11 @@ hide: Run a development server in the machine and reach its forwarded port on host `127.0.0.1`. Wayland applications can open windows on your desktop through Waypipe. -- **Seven signed distros** +- **Eight signed distros** --- - Choose Debian, Ubuntu, Fedora, CentOS Stream, Arch, openSUSE Tumbleweed or Leap. The images are rebuilt weekly. nsl verifies that they came from the signed Frostyard publishing workflow before using them. + Choose Debian, Ubuntu, Fedora, CentOS Stream, Arch, openSUSE Tumbleweed or Leap, or try the Azure Linux 4.0 beta. The images are rebuilt weekly. nsl verifies that they came from the signed Frostyard publishing workflow before using them. - **Isolation when you need it** diff --git a/site/content/reference/machine-images.md b/site/content/reference/machine-images.md index 996b032..fb1a1e9 100644 --- a/site/content/reference/machine-images.md +++ b/site/content/reference/machine-images.md @@ -15,6 +15,7 @@ Choose from the machine images below, rebuilt by Frostyard at least weekly. Run | Arch Linux | `arch:rolling`, `arch:btw` | arch | | openSUSE Tumbleweed | `opensuse:tumbleweed`, `opensuse-tumbleweed:rolling` | suse | | openSUSE Leap 16.0 | `opensuse:16.0`, `opensuse-leap:16.0` | suse | +| Azure Linux 4.0 (beta) | `azurelinux:4.0`, `azure-linux:4.0` | rpm | All images are x86-64. A new distro or release has to pass the same acceptance tests before it's added. @@ -36,5 +37,6 @@ All images are x86-64. A new distro or release has to pass the same acceptance t - **CentOS Stream 10** enables EPEL, and adds GLES libraries so GTK 4 applications render. - **Arch Linux** initializes and populates its pacman keyring on the machine's first boot. - **openSUSE** images add `glibc-locale-base` for `C.UTF-8`. +- **Azure Linux 4.0** is a beta, and its machines install packages from Microsoft's beta repositories. Those repositories offer few desktop applications; GTK 3 applications such as `gtk-lshw` open windows. The full [machine-image contract ↗](https://github.com/frostyard/nsl/blob/main/docs/specs/machine-images.md) is in the repository.