Core NixOS utilities in safe, portable Rust for NixOS and friends
Rust
96
206 commits
updated Sep 19, 2026
nixos-core
nixos-core is a multi-call binary implementing core NixOS system utilities in
safe, portable Rust, replacing some of the Perl, Bash and Python scripts that
are generally load-bearing for safety and performance. While some of those
scripts _can_ be replaced through various means (such as the Perlless and
Bashless profiles in Nixpkgs) the available methods usually change how your
system behaves, and may yield general instability or even breakage as is the
case with the /etc overlay system.
This repository provides a multi-call 1 Rust binary that aims to replace some of the fragile and occasionally undesirable Bash, Perl and Python scripts as well as some utilities that were already written in Rust in a fast, portable and easy-to-audit codebase. See the motivation section for why we also try to replace Rust code with more Rust code, or why this repository exists in the first place.
The NixOS module and the nixos-core crate replaces legacy Bash and Perl
scripts that execute on every NixOS system during boot and activation. While the
amount of Bash and Perl has been steadily decreasing in Nixpkgs, non-Systemd
spins of NixOS don't always get the same luxury. Thus, nixos-core aims to be the
one-size-fits-all that you can use on both NixOS and spins of NixOS requiring a
solution to those common problems.
The multi-call design of nixos-core, like BusyBox, reduces binary size and
simplifies deployment so that it can fit on your NixOS or NixOS-like system. The
project is intentionally modular to fit the particular needs of any user through
the NixOS module and
feature flags.
The scope of this program is currently limited to what Nixpkgs permits in terms of replacing the legacy solutions cleanly through the module system. Here is a general overview of what can currently be replaced:
| Command | Original Component | Purpose | Status |
|---|---|---|---|
update-users-groups | update-users-groups.pl | Manage /etc/passwd, /etc/group, /etc/shadow | First-class |
setup-etc | setup-etc.pl | Atomically update /etc/static | First-class |
init-script-builder | init-script-builder.sh | Create generic /sbin/init | First-class |
stage-1-init | stage-1-init.sh | Initrd bootstrap | First-class |
stage-2-init | stage-2-init.sh | System activation | First-class |
persist | Impermanence | Project persistent paths into an ephemeral root | First-class |
While the project is rather new, base rewrites are complete and mostly verified
through VM tests and even in real systems. If you're interested in testing
nixos-core on your system, but are skeptical, you may be interested in
enabling it gradually through the NixOS module knobs and test each individual
component. As it stands, nixos-core does not change anything that can "brick"
your system, i.e., you can easily roll back a generation in case something goes
wrong.
The nixos-core crate provides a multi-call binary invocable either as a
symlink:
# Invoke the update-users-groups command
$ update-users-groups /nix/store/...-users-groups.json
Or explicitly as a subcommand:
# Subcommand of update-users-groups
$ nixos-core update-users-groups /nix/store/...-users-groups.json
This usage pattern, like the mono-repo design, is a deliberate choice that allows reusing code and shared patterns without the cognitive overhead of cross-referencing separate projects. It also lets us provide a relatively small binary that does everything.
All commands provided by the nixos-core binary are enabled by default, but
also feature-gated through Rust's feature flags. This design lets you disable
commands that you don't want or need at build time and choose which binaries
to install, and what components to replace. Feature flags work both with cargo
(--features) and as package arguments when building with Nix:
[(prev: final: {
nixos-core = prev.nixos-core.override {
withStage1 = false; # e.g., skip initrd bootstrap
}
})];
Additional feature flags, also exposed as overridable package attributes,
control the behavior of stage 2. These are bootspec,
systemd-integration, and full-nixos-init-compat, providing complete
compatibility with the pre-existing behavior of Nixpkgs' stage 2. If you are
developing a systemd-less NixOS variant but still want to manage stage 2, you
can disable systemd-integration while retaining bootspec support. Most of
these features are described in detail in the stage2 crate's README.
nixos-core aims to be a safe, independent core utility for NixOS and NixOS
derivatives that build their own tooling from scratch, such as MicrOS and
Finix. The main goals of this project is being a fast, portable and consistent
utilities written in clean Rust, from one coherent codebase, and designed
modular enough through feature flags and NixOS module knobs to fit into any
system and derivative project. It is an out-of-tree module to meet those goals
without the behavioral changes imposed by Nixpkgs alternatives like Userborn,
the /etc overlay, or nixos-init. That is not to say those are fundamentally
incompatible with this project, but they are different. There may be room for
collaboration in the future.
We're always open to new contributions. Please keep in mind that as a critical system utility, nixos-core has strict contribution requirements. We expect you to write safe, principled Rust and test your code accordingly through unit and integration tests. If you have a good idea, but can't exactly be sure how to proceed you may open an issue to discuss your changes with us beforehand.
nixos-core is built with the latest stable Rust available in Nixpkgs, which is
1.94.0 at the time of writing. The Minimum Supported Rust Version (MSRV) is
therefore set at 1.94.0, and may change as the language evolves.
unsafe code except for unavoidable syscalls (crypt, geteuid)? operatorThis repository provides a few VM test to verify correct behaviour. Those are rather limited at the time but should provide some amount of guidance for you.
# Run all VM tests that are exposed under `checks`
$ nix flake check
# Run a specific VM tests
$ nix build .#checks.x86_64-linux.boot
You can find the available NixOS VM tests in the nix/vm-tests directory. If you're adding new features, you should add a new test component or some subtests that verify that your code works exactly as expected. There is also this neat little command you can use to get a list of checks supported by each system:
# Get a list of checks supported by each system. For now all systems
# support the same group of checks, but it might differ in the future.
$ nix eval .#checks --apply 'x: builtins.mapAttrs (_: builtins.attrNames) x' --json
Pipe it into jq for a nicer result.
This project is derived from Nixpkgs, originally licensed under the MIT License.
Original copyright and MIT license text are preserved in licenses/MIT.txt
located in the repository root. This project and all project code/documentation
are distributed under the Mozilla Public License (MPL) version 2.0. See
LICENSE for more details on the exact conditions. An online copy is
provided here.
Multicall in Unix refers to a type of binary that allows multiple commands to be executed through a single executable, depending on the name used to invoke it. See here for a more comprehensive explanation. Historically multicall binaries have also been called "BusyBox-like", which should probably be what you're thinking of when you hear "multi-call" for the purposes of this project. ↩
Rust
70.4%
Nix
29.6%
Core NixOS utilities in safe, portable Rust for NixOS and friends
Rust
96
206 commits
updated Sep 19, 2026
nixos-core
nixos-core is a multi-call binary implementing core NixOS system utilities in
safe, portable Rust, replacing some of the Perl, Bash and Python scripts that
are generally load-bearing for safety and performance. While some of those
scripts _can_ be replaced through various means (such as the Perlless and
Bashless profiles in Nixpkgs) the available methods usually change how your
system behaves, and may yield general instability or even breakage as is the
case with the /etc overlay system.
This repository provides a multi-call 1 Rust binary that aims to replace some of the fragile and occasionally undesirable Bash, Perl and Python scripts as well as some utilities that were already written in Rust in a fast, portable and easy-to-audit codebase. See the motivation section for why we also try to replace Rust code with more Rust code, or why this repository exists in the first place.
The NixOS module and the nixos-core crate replaces legacy Bash and Perl
scripts that execute on every NixOS system during boot and activation. While the
amount of Bash and Perl has been steadily decreasing in Nixpkgs, non-Systemd
spins of NixOS don't always get the same luxury. Thus, nixos-core aims to be the
one-size-fits-all that you can use on both NixOS and spins of NixOS requiring a
solution to those common problems.
The multi-call design of nixos-core, like BusyBox, reduces binary size and
simplifies deployment so that it can fit on your NixOS or NixOS-like system. The
project is intentionally modular to fit the particular needs of any user through
the NixOS module and
feature flags.
The scope of this program is currently limited to what Nixpkgs permits in terms of replacing the legacy solutions cleanly through the module system. Here is a general overview of what can currently be replaced:
| Command | Original Component | Purpose | Status |
|---|---|---|---|
update-users-groups | update-users-groups.pl | Manage /etc/passwd, /etc/group, /etc/shadow | First-class |
setup-etc | setup-etc.pl | Atomically update /etc/static | First-class |
init-script-builder | init-script-builder.sh | Create generic /sbin/init | First-class |
stage-1-init | stage-1-init.sh | Initrd bootstrap | First-class |
stage-2-init | stage-2-init.sh | System activation | First-class |
persist | Impermanence | Project persistent paths into an ephemeral root | First-class |
While the project is rather new, base rewrites are complete and mostly verified
through VM tests and even in real systems. If you're interested in testing
nixos-core on your system, but are skeptical, you may be interested in
enabling it gradually through the NixOS module knobs and test each individual
component. As it stands, nixos-core does not change anything that can "brick"
your system, i.e., you can easily roll back a generation in case something goes
wrong.
The nixos-core crate provides a multi-call binary invocable either as a
symlink:
# Invoke the update-users-groups command
$ update-users-groups /nix/store/...-users-groups.json
Or explicitly as a subcommand:
# Subcommand of update-users-groups
$ nixos-core update-users-groups /nix/store/...-users-groups.json
This usage pattern, like the mono-repo design, is a deliberate choice that allows reusing code and shared patterns without the cognitive overhead of cross-referencing separate projects. It also lets us provide a relatively small binary that does everything.
All commands provided by the nixos-core binary are enabled by default, but
also feature-gated through Rust's feature flags. This design lets you disable
commands that you don't want or need at build time and choose which binaries
to install, and what components to replace. Feature flags work both with cargo
(--features) and as package arguments when building with Nix:
[(prev: final: {
nixos-core = prev.nixos-core.override {
withStage1 = false; # e.g., skip initrd bootstrap
}
})];
Additional feature flags, also exposed as overridable package attributes,
control the behavior of stage 2. These are bootspec,
systemd-integration, and full-nixos-init-compat, providing complete
compatibility with the pre-existing behavior of Nixpkgs' stage 2. If you are
developing a systemd-less NixOS variant but still want to manage stage 2, you
can disable systemd-integration while retaining bootspec support. Most of
these features are described in detail in the stage2 crate's README.
nixos-core aims to be a safe, independent core utility for NixOS and NixOS
derivatives that build their own tooling from scratch, such as MicrOS and
Finix. The main goals of this project is being a fast, portable and consistent
utilities written in clean Rust, from one coherent codebase, and designed
modular enough through feature flags and NixOS module knobs to fit into any
system and derivative project. It is an out-of-tree module to meet those goals
without the behavioral changes imposed by Nixpkgs alternatives like Userborn,
the /etc overlay, or nixos-init. That is not to say those are fundamentally
incompatible with this project, but they are different. There may be room for
collaboration in the future.
We're always open to new contributions. Please keep in mind that as a critical system utility, nixos-core has strict contribution requirements. We expect you to write safe, principled Rust and test your code accordingly through unit and integration tests. If you have a good idea, but can't exactly be sure how to proceed you may open an issue to discuss your changes with us beforehand.
nixos-core is built with the latest stable Rust available in Nixpkgs, which is
1.94.0 at the time of writing. The Minimum Supported Rust Version (MSRV) is
therefore set at 1.94.0, and may change as the language evolves.
unsafe code except for unavoidable syscalls (crypt, geteuid)? operatorThis repository provides a few VM test to verify correct behaviour. Those are rather limited at the time but should provide some amount of guidance for you.
# Run all VM tests that are exposed under `checks`
$ nix flake check
# Run a specific VM tests
$ nix build .#checks.x86_64-linux.boot
You can find the available NixOS VM tests in the nix/vm-tests directory. If you're adding new features, you should add a new test component or some subtests that verify that your code works exactly as expected. There is also this neat little command you can use to get a list of checks supported by each system:
# Get a list of checks supported by each system. For now all systems
# support the same group of checks, but it might differ in the future.
$ nix eval .#checks --apply 'x: builtins.mapAttrs (_: builtins.attrNames) x' --json
Pipe it into jq for a nicer result.
This project is derived from Nixpkgs, originally licensed under the MIT License.
Original copyright and MIT license text are preserved in licenses/MIT.txt
located in the repository root. This project and all project code/documentation
are distributed under the Mozilla Public License (MPL) version 2.0. See
LICENSE for more details on the exact conditions. An online copy is
provided here.
Multicall in Unix refers to a type of binary that allows multiple commands to be executed through a single executable, depending on the name used to invoke it. See here for a more comprehensive explanation. Historically multicall binaries have also been called "BusyBox-like", which should probably be what you're thinking of when you hear "multi-call" for the purposes of this project. ↩
Rust
70.4%
Nix
29.6%