Besides, technically, if you're chosing an OS in 2026, it sounds like a good plan to start with a system that has many reproducibility, correctness properties and separated packages designed in from the start.
Now, I'm not a NixOS user (altering mostly between win,fbsd,osX and some debians), maybe there's some horrible dragons lurking in using it in practice (do share in that case), but from reading about it sounds like a plan for a system used in a future where people don't need to curse too much about legacy decisions?
As for practical use, sure there are some rough corners (this is true for every Linux distro), but I don't think there's any horrible showstoppers. In fact it's particularly well-suited for use by organizations (as opposed to private individual use) because it's great for making highly customized but reproducible setups.
Nix has numerous properties that make it unsuitable for a normal desktop OS:
(1) It has no concept of libraries being backwards compatible, so if a 200kb core library changes in a backwards compatible way e.g. security hotfix, it will rebuild/redownload pretty much everything you have installed. This kills your ability to roll out security fixes quickly and ensures that updates are far more painful for end users than even on Windows.
(2) Nix advertises its main benefit as being that you can easily roll back bad updates, which is just false. It makes this false claim because Nix treats user state as being out of scope. Try upgrading Postgres across major versions with Nix and then rolling it back and see what happens, or really any program that stores stuff in $HOME and doesn't support rollback. It'll just die, make a mess, and Nix will wash its hands of the affair by saying it did the bit it wanted to do (change the binaries on your path) and the rest is just out of scope.
(3) It has no working concept of native plugins, related to point (1). If two plugins depend on slightly different versions of their host program, they'll just load incompatible libraries into the address space and things will crash.
(4) It cannot run binaries shipped for generic Linux without lots of fragile hacks like binary rewrites. But in the real world lots of important domain-specific programs are shipped as binaries, if they support Linux at all.
I imagine you have a lot more experience than I do packaging for NixOS and other distros given your product, but in the few cases that I've needed to run a binary, I just wrap it with a flake and it's done. I also stay on NixOS stable, so I avoid the sharp parts of "bleeding edge". In my experience as a desktop user, I've never had a failed rollback since using NixOS as my primary OS since around 2016. However, whenever I try to use it as a server OS, I often do hit the pain point you mentioned around statefulness. More specifically, the happy path is extremely happy, but once you need something off the happy path, you find yourself creating some really ugly glue to get it to interface with the happy path. The pattern I've settled on is using Podman quadlets for most services, but that isn't without pain either. Then you find that you've become a Unix sysadmin, managing different UIDs for rootless podman, different network domains, dealing with permissions issues, etc. I'm currently experimenting with microvm.nix to see if that will be cleaner, but no conclusions yet.
2: Doesn't really sound like a problem for most desktop stuff unless there's some components you use that depend on non-upgradable data. Users have their browser, word files, excel files, pdf files and so on.
3: Sounds annoying, but also like a fixable feature. How much common user software have native plugins ?
4: Binaries for Linux is a bit of a mess in general, I think someone in jest wrote that now that Wine has improved, win32 binaries is the preferable binary distribution format for Linux.
Incompatibilities can of course happen, but so can improvements. Nix throws the baby out with the bathwater. You can rerun CI of upstream (open source) projects against a new set of component versions if you want, it doesn't imply anything about how the distribution mechanism should work.
For (2) the issue is non-downgradeable data, not non-upgradeable. Apps basically never support downgrades. Consider your web browser changing the format of its HTTP cache or credentials store, consider your word processor adding a new feature that the user incorporates into their documents and then it's suddenly downgraded. There isn't even any way to downgrade Chrome via its normal user interfaces!
For (3) crashes aren't just annoying, they're indicative of a fatal design flaw. Native plugins were a common feature on other operating systems in the past and have historically been a feature of KDE and GNOME too. I don't know if there are new Linux-native apps of high complexity being written these days though. The dominance of Electron means plugins have moved server-side where the user's OS can't screw them up. Nonetheless, you can't have a serious productivity-focused desktop OS if apps can't be composed at all. You can at best maybe do a ChromeOS competitor.
For (4) sure it can be just defined as out of scope, same thing Nix[OS] does with lots of other important problems. It's embarrassing to present Linux as a solution if it depends on Microsoft to solve the hard stuff for you, though.
2: I hear you, I still think it's a minor inconvenience in the grand scheme of things, worst case administrators should manage for full user backups in case of breakage (people bad backups habits are more likely to cause havoc for other reasons like hardware failure than the occasional downgrade of system data).
3: only thing that immediately comes to mind is Blender, but there it's Python scripts and intentionally not supporting C++ plugins (last I checked you're supposed to rebuild the entire thing if you want C++ additions).
4: OSS unixy systems has always had tilt to the former in the conflict between the security/sysadmin view (no local binary searching due to security, binaries upgrade everywhere) vs users (who wants to run programs and don't care too much about what glibc version it was compiled with, even taking that big binary with all libraries bundled).
I see Nix as more like Windows SxS instead of just shipping everything like with flatpak,docker,etc. But it always boils down to the same dependency on absolute filepaths for everything that's hard to escape (because you can "just recompile").
flatpak exists though, doesn't it work well enough?
I'm no Nix user, but I want to build an alternative.
Do you think these problems could be fixed?
It's probably worth just going back to the drawing board and asking what the goals of a desktop OS should really be. You'd end up with something radically different to Nix, IMO, sort of like how how NeXT/macOS manages software is quite radically different to UNIX.
I actually have a little exploration of a new software distribution idea going on right now, but it's not trying to do the same things as Nix. It starts by asking what a desktop OS inspired by the success of the web would look like.
Your idea sounds interesting and (by your bio) right up your alley. I'd be interested to see the result.
Two new programs: `url` and `run`. I am creating reference implementations but they're simple and there's a spec, so they could be reimplemented in your language of choice.
`url https://...` resolves the given URL into a disk cache in $HOME and then prints the path. `url` understands archives and can resolve inside them:
$ url https://a.b/program.zip/bin/program
/home/foo/.cache/..../bin/program
It implements the HTTP caching spec, and - as browsers can do with HTML - can extract cache override headers from the given program if it's a script with hashbang. It does a few other things, like set +x automatically if the program is intended to be executable, sets quarantine bits on macOS and so on: $ open $(url https://downloads.mac-app.com/MacApp-1.2.zip/MacApp.app)
(scanned by gatekeeper and then run)
The disk cache is cleaned up automatically as disk space falls low or the cache exceeds the configured maximum.Running programs this way is possible, but not ideal. This is where `run` enters the picture:
$ run cool-tool.org --help
or if you have the zsh integration set up, you can skip the `run` prefix and just treat URLs as program names: $ cool-tool.org --help
`run` resolves this to https://cool-tool.org/run.zip/ which is a small metadata archive containing instructions for how to start the app. The instructions come in the form of a JavaScript that's run inside a restrictive sandbox. It is allowed to resolve URLs into the disk cache, to learn the current host OS and CPU architecture, and to yield an execution plan (basically the path to the binary/script to execute + optionally transformed CLI arguments). So by publishing a small run.zip file to the root of cool-tool.org it becomes possible for users on any OS, including macOS and Windows, to start the program purely by domain name. The script can do hash locking and override cache headers for URLs if the file server isn't cooperative. The tools will keep the app up to date and optimize out cache checks to keep startup fast when the cache is fresh enough.The run script has a few other options, like figuring out what system libraries are available and what their versions are, thus - if it wishes - it can choose to either download dependencies into the cache and use them (e.g. by setting LD_LIBRARY_PATH), or use the OS provided versions.
At the moment I'm also working on adding a form of sandboxing. The execution plans produced by run scripts can contain permission requests, similar in spirit to macOS entitlements. The permissions aren't tied to any specific sandboxing system or OS. The implementation of `run` may, at its leisure, use this information to sandbox the program before it executes it. The run script may also adapt the permissions requested based on things like what the host OS is, or even what the command line arguments are. For example:
$ cool-app.org --input ./in.mp4 --output ./out.mp4
or $ dry-run cool-app.org --input ./in.mp4 --output ./out.mp4
Requests permissions:
1. Read $PWD/in.mp4
2. Read/write $PWD/out.mp4
3. Read ~/.config/org.cool-app/config.yml
The run script can look at the command line arguments for this invocation, then produce a permission set that only allows access to the in.mp4 and out.mp4 paths, and a config in an OS specific location, but nothing else. Whether the implementation of run actually tightens things that much will depend on things like what the host OS is capable of, but the information to do so is there. For example on Linux it might use landlock, on macOS it might compare the declared permissions against the entitlements in the Mach-O and abort if there's a mismatch, and so on.run.zip files don't have to be produced by the upstream author of the code. They can come from anywhere and resolve URLs from anywhere. So if you are worried about the upstream code being malicious, you could use a run.zip from a third party app store or catalogue, and if you aren't, you can use the upstream's version which just sandboxes to limit the blast radius of compromises.
The goals here are deliberately modest, something like:
- Learn from the web, by making starting native CLI apps as convenient as starting a web app.
- Have a small spec that allows for cross-platform deployment without forcing a large declarative schema for how to assemble files and URLs.
- Don't require the user to manually manage installation/uninstallation.
- Experiment with a cross-platform declarative permissions schema that's computed imperatively, where the mapping to OS sandboxing primitives can flex and adapt over time as OS kernels change.
Redownloading everything doesn't protect against supply chain attacks. Those can still happen, no problem.
As a normal NixOS user, I know how to do this. It would be quite some effort, but not especially difficult. Additionally, for a government they have the servers to set up a build farm.
Why did those not work out? Why do they think things will be different with NixOS?
As a positive thing, maybe at least nixos will get a serious security pipeline rather than the current best-effort community approach.
I'm not sure why they chose nix. But it does make it easier to carry local patches than a lot of other systems. I hope they succeed.
This is the main issue NixOS solves for me. I don't have systemd units or cronjobs or random config files spread across the system. I have one config file/directory, which contains everything.
My beef with nix is the arcane syntax to get anything done. Yes, it's documented. No, it doesn't help that it reads like one of those strict, convoluted standards written by a committee of experts.
Also what causes problems for others may not be the same thing that causes problems for you. You could try accepting others' experiences.