3 ms·
You’re right. That’s what NixOS is, a Linux distro where all software is managed by Nix, so the users environment is fully compartmentalized, declarative, and r
by alxmng 4y ago
You’re right. That’s what NixOS is, a Linux distro where all software is managed by Nix, so the users environment is fully compartmentalized, declarative, and reproducible.
- MuffinFlavored 4y ago> so the users environment is fully compartmentalized, declarative, and reproducible. I have a question about this, please forgive my ignorance. I see this statement repeated a lot about NixOS and I've kind of had some "success" in the comments section being "critical" / "asking hard questions" about NixOS. If I have a build script that pulls + compiles + validates with hashes/checksums say, Linux kernel, some userspace tools, init system, etc. for a boring ol' distribution like Alpine or Debian, why isn't that classified as "reproducible" the same way NixOS is?
- edgyquant 4y agoIt would be, the problem is that you can not write such a script at the moment. As far as I know those checksums are almost always for the source code/file itself and not the compiled binary.
- yjftsjthsd-h 4y agoThe situation has improved, actually - you'd still have to do custom scripting to check the output checksums AFAIK but ex. https://tests.reproducible-builds.org/debian/reproducible.html https://tests.reproducible-builds.org/debian/reproducible.ht... tracks Debian's attempts to make it possible to reproduce packages perfectly. It's just that nixos made it pervasive and normal through the whole system.
- mikepurvis 4y agoI think the main thing to understand is that Debian is reproducible as a consequence of significant unenforced contracts around what the pristine build environment will be, what the state of the package repo will be when dependencies are fetched and installed, and so on (see: https://www.debian.org/doc/debian-policy/ch-source.html#reproducibility https://www.debian.org/doc/debian-policy/ch-source.html#repr...). Your local dpkg-buildpackage invocation has pretty much a 0% chance of being a bit-for-bit reproduction of what you pulled from the archive unless you cooperate with all this ceremony. Nix, on the other hand, is reproducible by default. If you `nix build <nixpkgs/gitsha#pkgname>` you are automatically getting a local build that takes place in the same hermetic sandbox as the build you pulled from cache.nixos.org, and will be identical or very close to it. (Contrary to popular belief, not all of nixpkgs is reproducible— many packages require patching for various sources of nondeterminism, and this is an ongoing effort: https://github.com/NixOS/nixpkgs/labels/6.topic%3A%20reproducible%20builds https://github.com/NixOS/nixpkgs/labels/6.topic%3A%20reprodu...)
- odo1242 4y agomany compilers aren't guaranteed to be fully deterministic tho (e.g. __DATE__ macro)
- Karellen 4y agoThe "Reproducable Builds" project has been working on this for a few years now, and introduced the SOURCE_DATE_EPOCH environment variable, which is supported by most compilers, as a way to fix the date in build environments. Other previously nondeterministic build issues have some similar opt-in workarounds. Have a look around the Reproducable Builds project website for more info/examples. https://reproducible-builds.org/docs/source-date-epoch/ https://reproducible-builds.org/docs/source-date-epoch/ https://gcc.gnu.org/onlinedocs/cpp/Environment-Variables.html https://gcc.gnu.org/onlinedocs/cpp/Environment-Variables.htm...
- duped 4y agoIt's only reproducible if you can actually reproduce it in a different environment (different time/locale/machine/etc).
- sparkie 4y agoThe problem might not be your script, but that the system is stateful. Users can access and mutate the /usr directory, and some software will do this outside of the system's built-in package manager. You can also compile and link against a shared library in /usr, but then later this library may be updated, so now your app links against a different library than the one you built against. Older package managers use a "name-version" scheme to try and avoid package conflicts, but in practice there can be different binaries which have the same "name-version" identifier and they're not always compatible. The way Nix solves the issue is to store everything in a content-addressible store `/nix/store`, where multiple concurrent versions can be installed without naming conflicts (the directories are named with the content hash). When an app is compiled, it is linked to specific shared libraries in the nix store which will always be present on the system. The `/usr` directory then, is just a collection of symlinks to the actual content in the nix store (most recent versions), for compatibility. Because derived packages are reproducible, they will always have the same content hash on every system on which they are deployed. As a developer then, you can target very specific shared libraries when building your software, and you know that when you deploy them, users are going to have the exact same dependencies you had when you built it.
- pxc 4y ago> If I have a build script that pulls + compiles + validates with hashes/checksums say, Linux kernel, some userspace tools, init system, etc. for a boring ol' distribution like Alpine or Debian, why isn't that classified as "reproducible" the same way NixOS is? It might be! Nix uses that very same strategy for enforcing reproducible outcomes when dealing with non-reproducible operations, like fetching things from the great mutating mass of the internet. I would say that Nix differs from that approach mainly in the way it divides up the problem. So-called binary package managers like you use on Alpine and Debian perform runtime dependency resolution against a mutating global namespace that usually lives on the internet— the binary repos themselves. Generally, those repos include only one copy of each package. So to halt the forward march of all those versions, you have to mirror each repo of binary artifacts you're interested in using. With Nix, outcomes also depend on the state of the repo, but the repo is just a collection of build recipes which are the mapped onto their outputs in a single, huge binary cache. Every new build gets added to the same binary cache, for every Nixpkgs/NixOS release. It just grows and grows. And of course, Nix builds work even without enabling the binary cache at all. So to get the same kind of reproducibility out of many other package managers, you generally have to set up additional infrastructure. But if you do everything right, you can certainly have a fully reproducible OS image based on Alpine or whatever else.
- yepguy 4y agoNix's main innovation with regard to reproducibility is that it actually fully specifies the dependency graph. I'm not going to say anything about bit reproducibility as that's another thing entirely, but virtually every other package manager and build system has holes in its dependency graph, coming in 2 main forms: 1. Implicit dependencies that are needed to build the software but not managed by the package manager or build system itself. For example, if your language package manager depends on a C library that it can't build itself. Or Linux distribution package managers that implicitly assume the presence of a "base system". 2. SAT solvers for version selection. Using one of these usually introduces an implicit dependency on the clock time, because your dependencies will resolve to different versions at different times. The reason your script wouldn't classify as reproducible is simply that you would probably fail to fully specify your dependencies. It's harder than you'd expect once you start moving up the software stack to complicated high-level applications.