Nix
The Nix extension adds the Nix package manager and its multi-user daemon to a Frostyard bootc image. Use it when you want Nix packages and profiles next to the software the image ships. Every image carries the extension’s definition, switched off. The extension itself is not in the image: Updex turns it on and downloads it.
Before you start
Section titled “Before you start”You need:
- A Frostyard bootc image. Every image built on Base has
systemd-sysextandfrostyard-updex. - Root access to enable, update, and remove the extension.
- Network access to
https://repository.frostyard.org/ext/nix/, and to the sources your Nix expressions fetch. - Free space in
/varfor the image and for the Nix store and profiles. The store grows with each package and profile you add. - The user names you will add to the
nix-usersgroup.
In lab tests on Snow in October 2026, the Nix units of revision 5 loaded and started. The tests built and installed no packages. The current revision has no test results yet. Try it on a machine you can spare first.
Enable Nix
Section titled “Enable Nix”See what Updex found, then enable the feature and download it now:
updex features list --component=nixsudo updex features enable nix --nownix appears as a component, with its feature disabled. The enable command
downloads the image, checks its checksum and signature, links it, and refreshes
the merge.
Check that the image is merged, the mount is up, and the daemon runs:
systemd-sysext statussystemctl status nix.mount nix-daemon.servicesystemd-sysext status lists nix. nix.mount puts /var/lib/nix at /nix,
and the daemon is bound to that mount, so it stops when the mount fails.
A refresh by Updex v2.1.3 and later runs systemd-sysusers and
systemd-tmpfiles --create, so the nix-users and nixbld groups and
/etc/nix exist at once. The extension sets EXTENSION_RELOAD_MANAGER=1, so
the refresh also reloads systemd, and the mount and the daemon start in the
same boot. If they do not, reboot and check again.
If enable --now exits with a refresh error (refresh_error in JSON), the
download worked, but the activation did not. If the output says
activation did not finish, the extension is merged, but users and groups can
be missing: reboot. Otherwise the merge state is unknown: reboot. A
sudo systemd-sysext refresh by hand does not create users and groups. Then run
the two checks above again.
Use Nix
Section titled “Use Nix”Client access is opt-in. The extension recreates Debian’s nix-users group and
adds nobody to it. Add your account:
sudo usermod -aG nix-users USERReplace USER with your user name. Log out and in again: the new session has
the group. This grants access to the daemon socket. It does not grant Nix
trusted-users privileges.
Check the command and the store:
command -v nixls /nix/storeEvery user can read the store. Only the nix-users group can reach the daemon
socket, and the daemon does the writes.
Multi-user builds run as nixbld1 to nixbld10, all members of the nixbld
group, at the UIDs and GIDs that the official Nix installer uses. Per-user
profiles and garbage-collection roots live under
/nix/var/nix/profiles/per-user and /nix/var/nix/gcroots/per-user, stored in
/var/lib/nix/var/nix. Both directories are world-writable, so any user can
create a profile or register a root.
The Nix configuration lives in /etc/nix. The extension keeps a default copy
in /usr/share/factory/etc and copies it into /etc when /etc/nix is
missing: at boot, and at a refresh by Updex v2.1.3 and later. Edit the files in
/etc/nix; your edits survive reboots and updates. The copy happens only once,
so a later update with new Nix defaults does not change an existing /etc/nix.
Update and remove
Section titled “Update and remove”An update refreshes the merged /usr while the daemon runs. Let running
builds finish before you update by hand. Your store, profiles, and roots in
/var/lib/nix stay.
Remove Nix now:
sudo updex features disable nix --now --forceUpdex unmerges all extensions on the host, deletes the Nix image, and merges
the rest again. The mount unit and the daemon go. /var/lib/nix stays, with
every store path and profile you built. Reboot when the command finishes.
The unmerge reloads systemd, because the extension sets
EXTENSION_RELOAD_MANAGER=1. A unit that still runs stays loaded until it
stops or the host reboots. Without --force, Updex refuses while the image is
merged.
Roll back
Section titled “Roll back”Roll back with sudo updex features rollback nix. It takes effect at the next boot. Updex then holds updates until a newer version is published. To stop future updates instead, run sudo updex features disable nix. /var/lib/nix stays either way. See Roll back.
See Manage system extensions for the update check, the
timer, and plain disable.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Check | Fix |
|---|---|---|
| A Nix command fails with a permission error | id -nG USER and systemctl status nix-daemon.service |
Add the user to nix-users with sudo usermod -aG nix-users USER, then start a new login session. |
nix-users is missing |
getent group nix-users |
The group comes from usr/lib/sysusers.d/nix.conf. Boot and a refresh by Updex v2.1.3 and later apply the rules. Reboot and check again. |
| The daemon is not running | systemctl status nix.mount nix-daemon.service |
The daemon is bound to nix.mount. Check the mount and /var/lib/nix, then start nix.mount. |
/nix/store is empty or missing |
systemctl status nix.mount |
The bind mount is not active. Start nix.mount, or reboot. |
/etc/nix is missing |
ls /etc/nix |
Boot and a refresh by Updex v2.1.3 and later make the copy. Reboot and check again. |
enable --now exits non-zero after the download |
The output shows Error: sysext refresh failed (refresh_error with --json) |
If the output says activation did not finish, reboot. Otherwise reboot too: a refresh by hand does not create the extension’s users and groups. Then check systemd-sysext status. |
What ships
Section titled “What ships”| Item | What you get |
|---|---|
| Package | nix-setup-systemd, which brings the Nix binaries and the daemon units |
| Version | The image file name carries the nix-setup-systemd version, plus a +rN snosi revision when one is set |
| Image file | nix_<version>_<os>_<arch>.raw.zst; .raw.xz, .raw.gz, and .raw also work |
| Download | From https://repository.frostyard.org/ext/nix/, signature required (Verify=true), into /var/lib/extensions.d/ |
| Command | /usr/bin/nix |
| Services | nix.mount, nix-daemon.socket, and nix-daemon.service, enabled by 40-nix.preset. 10-nix.conf upholds nix.mount and nix-sysext-setup.service, which pulls in the daemon units at boot |
| Mount | /nix is a bind mount of /var/lib/nix |
| Users and groups | nix-users with no members, and nixbld with nixbld1 to nixbld10 |
| Configuration | A default /etc/nix, held in /usr/share/factory/etc |
| State | /var/lib/nix: the store, profiles, and garbage-collection roots |
Each build checks that the Nix binary, the user rules, the tmpfiles rules,
nix-daemon.service, nix.mount, nix-sysext-setup.service, the boot drop-in,
the reload setting, and the factory nix.conf are present. A build that is
missing one fails. The image is an overlay, so a later Base can break an older
Nix image.
See also
Section titled “See also”- System extension catalog
- Dev tools system extension
- Manage system extensions
- System extension model
- Updex v2.1.4 command reference
Sources
Section titled “Sources”Reviewed 2026-10-27; Updex facts reviewed 2026-10-30; snosi facts reviewed 2026-10-31. snosi commit
859f45434aa7960d42b1f7ad35e01f12fd4aafb3;
Updex v2.1.4 commit
1843ea8ded298fbde42390a0c8b2842d09a92757.
mkosi.images/nix/mkosi.confmkosi.images/nix/mkosi.finalizemkosi.images/nix/required-paths.txtmkosi.images/nix/mkosi.extra/usr/lib/systemd/system/nix-sysext-setup.servicemkosi.images/nix/mkosi.extra/usr/lib/systemd/system/nix.mountmkosi.images/nix/mkosi.extra/usr/lib/systemd/system/nix-daemon.service.d/mount-binding.confmkosi.images/nix/mkosi.extra/usr/lib/systemd/system/multi-user.target.d/10-nix.confmkosi.images/nix/mkosi.extra/usr/lib/systemd/system-preset/40-nix.presetmkosi.images/nix/mkosi.extra/usr/lib/sysusers.d/nix.confmkosi.images/nix/mkosi.extra/usr/lib/tmpfiles.d/nix-sysext.confmkosi.images/base/mkosi.extra/usr/lib/sysupdate.nix.d/nix.featuremkosi.images/base/mkosi.extra/usr/lib/sysupdate.nix.d/nix.transfertest/nix-client-group-test.pydocs/design/sysexts.md- snosi#1193, merged as
20a569e: the extension setsEXTENSION_RELOAD_MANAGER=1, so a refresh reloads systemd docs/adr/0026-sysexts-with-system-units-reload-the-manager.md(lab runsdev-snow-bootc-lifecycle-mm4s5anddev-snow-bootc-lifecycle-4hr54, revision 5: they checked that the units load and start, not workloads)mkosi.images/nix/mkosi.extra/usr/lib/extension-release.d/extension-release.nix- Updex v2.1.4
README.md - Updex v2.1.4
updex/features.go - Updex v2.1.4
sysext/runner.go(disable --nowunmerges first, with a plainsystemd-sysext unmerge) - Updex v2.1.4 release
- Updex
docs/adr/0019-apply-merged-sysusers-and-tmpfiles-on-a-live-refresh.md(a live refresh runssystemd-sysusersandsystemd-tmpfiles --create; when the last refresh fails, the merge state is unknown; a refresh by hand does not runsystemd-sysusers) src/data/extensions.jsondocs/adr/0016-automatic-sysext-updates-apply-at-next-boot.md