May 23, 2025·6 min read·engineeringnixnixosdeployment

NixOS 25.05 introduces a new rebuild implementation for testing

Warbler includes an opt-in Python rebuild implementation, configuration-driven image building, and initial COSMIC support. The release separates stable distribution delivery from the readiness of individual integrations.

The program applying a declarative operating-system configuration is part of that system's operational interface. NixOS 25.05 introduces a full Python rewrite of nixos-rebuild for testing, while leaving adoption explicit. That gives the project a way to replace an important implementation without making every user switch to it on release day.

The Warbler release notes date NixOS 25.05 to May 23. Alongside the rebuild rewrite, they introduce configuration-driven image building and initial COSMIC desktop support. The notes in the release source identify which capabilities remain experimental or opt-in.

NixOS interests me because the machine's desired state can live in a repository and be rebuilt from declared inputs. The command applying that state deserves an equally clear contract. An alternative implementation is useful when the project makes its selection visible and lets users compare behavior against their existing workflow.

The rewrite can replace the command or sit beside it

The release offers two adoption paths for nixos-rebuild-ng. Setting system.rebuild.enableNg replaces the old nixos-rebuild command with the new implementation. Adding the package to the system instead provides it under its separate name, alongside the existing command.

The side-by-side form makes the distinction concrete in configuration. The package remains available under the separate name documented in the release notes, making the invocation distinguishable from the existing command.

{ pkgs, ... }:
{
  environment.systemPackages = [ pkgs.nixos-rebuild-ng ];
}

This declaration makes the new tool available without selecting it as the implementation behind the familiar command name. That is useful for investigating a tool whose job includes applying system changes. The identity of the implementation remains visible in the command being invoked.

The replacement form expresses a different decision. It selects the new implementation for the usual rebuild command, so the setting records a workflow change as part of the system configuration.

{
  system.rebuild.enableNg = true;
}

The release describes the rewrite as available for testing. It also states an expectation that the next major NixOS release will enable it by default. That expectation is a plan as of today, rather than evidence that the default has already changed in Warbler.

These two configuration forms avoid an ambiguous middle state in documentation. Installing a package and changing which implementation a standard command invokes are different actions. Someone reading a system configuration can tell whether the machine is making the experimental command available or adopting it as the normal rebuild tool.

A different implementation still has to preserve the workflow

The release calls this a full rewrite in Python. That describes an implementation change, not a new requirement that users describe their machines in Python. NixOS configuration remains the input to the rebuild process. The tool interpreting the deployment workflow has changed languages.

This matters because an operating-system deployment command connects several operations that users experience as one workflow. Building a system and applying it have different effects. An implementation can use the same configuration input while differing in argument handling or how it invokes other operations. Availability for testing creates a period in which those practical interactions can receive attention.

The release notes do not provide a claim that every existing wrapper is already compatible. They give an adoption mechanism and identify the testing status. That is enough to describe the change accurately without inventing a new performance result or a complete compatibility guarantee for the rewrite.

I prefer the explicit opt-in for this kind of tool. A declarative system makes experiments easier to describe, but the program applying a generation is still an operational dependency. Keeping both implementations available under distinct names supports a concrete comparison when someone needs to understand a changed behavior.

Image creation becomes another configuration output

Warbler adds a nixos-rebuild build-image subcommand for platform-specific disk images. The notes say it works similarly to the nixos-generators project and is available in both rebuild implementations. That is a separate capability from the implementation rewrite, so it does not require adopting the new command merely to obtain image-building support.

The distinction between an image and an applied system is useful here. A machine configuration can describe the desired system, while the deployment environment determines how that system needs to be packaged. Producing a disk image is another way to consume the configuration, with platform-specific requirements around the resulting artifact.

Adding the operation to the rebuild tool gives users a documented entry point within the system's own tooling. The release notes describe what the subcommand is for without implying that all possible target platforms have identical image layouts. The configuration and selected image platform still determine the artifact being built.

This fits the declarative model that makes NixOS useful to me. The system description can support a directly applied generation or an image produced for another deployment path. Those are different deliverables, but neither needs to become an unrelated manual account of which packages belong on the machine.

Option inspection follows a smaller implementation

The release also rewrites nixos-option as a Nix expression invoked by a simple Bash script. Its stated goals include lowering the maintenance threshold and reducing the verbosity of evaluation errors. It gains support for flake-based configurations and for descending into attrsOf and listOf submodule options.

That change addresses inspection rather than deployment. A declarative configuration is only useful to operators when they can determine what its options evaluate to. Support for nested submodule collections matters because a configuration can contain multiple similarly structured entries, each with its own option values.

The new --show-trace support also makes diagnostic detail an explicit request. The release notes connect this with less verbose ordinary errors, giving inspection a way to present a shorter default while still making an evaluation trace available. These are interface choices around understanding a configuration, rather than changes to the desired service state itself.

Taken together with the rebuild rewrite, this shows work on the tools surrounding the module system. The configuration language can remain the same while the programs used to inspect and apply it become easier for maintainers to evolve. That maintenance work matters to the long-term usability of declarative state.

COSMIC support has a narrower readiness claim

The release introduces initial integration for COSMIC, System76's Rust-based desktop environment, at Alpha 7. The notes provide separate options for the COSMIC greeter and the desktop environment. Selecting a login manager and selecting the desktop session remain distinct configuration decisions.

The NixOS integration is described as stable while still carrying an experimental designation because it is new. That wording distinguishes distribution integration from the upstream desktop's own development stage. A stable NixOS release can ship an explicitly experimental integration without claiming that its upstream desktop is a finished production release.

The maintainers ask users to report integration issues to the Nixpkgs COSMIC tracker rather than directly upstream. That gives the initial integration a defined place to collect reports. A problem in how the distribution assembles a session may need different investigation from a defect in a desktop component itself.

The release also updates GNOME to version 48, with changes to default applications and fonts. This is a reminder that a distribution release coordinates multiple desktop choices. The COSMIC addition creates another option, while existing integrations continue to change independently of whether a user enables it.

Channel archives gain a flake input path

The release notes also announce Lockable HTTP Tarball Protocol support on channels.nixos.org. Their example uses the channel's nixexprs.tar.xz URL as a flake input. This connects an existing channel publication artifact to a flake declaration without requiring the input URL to name a Git hosting service.

The distinction is the transport and publication interface used to obtain Nixpkgs. A channel archive and a Git repository reference are different ways to identify source material. Providing a lockable archive endpoint gives a flake another explicit source option. The published example identifies the 25.05 channel, while the lock records the resolved input used by the configuration.

A stable release can carry explicit experiments

Warbler's status does not erase the individual status of every facility it includes. The rebuild rewrite is opt-in for testing, COSMIC integration is new and marked experimental, and image building is available through both rebuild implementations. Those distinctions determine what a user is actually choosing.

For my use of NixOS, the useful property is that these choices can appear in declared configuration. The release does not require a hidden replacement of the rebuild command to try the new implementation. It supplies a side-by-side package path and a separate option for adopting the rewrite as the standard command.