> nix unlike all other distros can install multiple version of the same package
The above is sometimes true and sometimes not. For the most part, Nix can install multiple versions of a program but only one can be in use at any given time.
Nix is for the most part shell based workflow (as in bash, zsh, etc.). The `nix-shell` command lets you switch out the packages (and versions of packages) that are used in any given shell, but it works off of a configuration file written in the Nix language that you write. The programs that are available are controlled by environment variables such as PATH and MANPATH.
Nix is a big shift from the usual way of dealing with packages, programs, etc. It isn't really useful until you really make the effort to understand what is going on, learn the Nix language, etc. If you are not interested in "programming" your system, then it probably isn't for you.
> or the most part, Nix can install multiple versions of a program but only one can be in use at any given time.
That's a bit hand-wavey. More precisely: when you run a command, like `python3`, you can only associate that with one file. If you want multiple Python 3 interpreters, you'll have to use different names (e.g. making symlinks).
Alternatively, you don't need to bother "installing" anything; e.g. I use Nix for projects which use Scala, Maven, Python, NodeJS, etc. yet I don't have any of those installed. Instead, each project includes a `shell.nix` file which specifies the tools it wants. Running `nix-shell` in different folders gives me access to different tools.
Also, with Nix we only need to care about the end result: we can "install" a bunch of different programs, even if they have incompatible dependencies, since we're not "installing" those dependencies. ("Install" just means putting a symlink in some bin/ folder, like /run/current-system/sw/bin on NixOS or $HOME/.nix-profile/bin on non-NixOS)
I remember reading that nix unlike all other distros can install multiple version of the same package and I want this feature, but I guess programming a package config might be too much for me. Maybe I'll try nix package manager then.
> Nix can install multiple versions of a program but only one can be in use at any given time.
That’s not really true and is only a limitation of how PATH works on UNIXes (the first match is used). But you can for example add an aliased name for multiple versions of the same package, or for another meaning of use you can have different executables in the same environment different versions of the same lib (e.g. one bash script references python3, the other python3-at-specific-patch/minor-version/whatever)
Nix groups all of your installed packages in one environment. When you install a new package, it creates a new environment with the new package added to it. This alone may sound insignificant, but it enables having multiple nix environments (e.g. one per project) and switching between them very quickly and easily.
> But how does one solve the issue of security level updates for some dependency language? Or when a particular version of some application reaches EOL and is no longer maintained, or theres some functionality in a newer version of Nodejs|Ruby|etc thats needed?
Nix supports building packages from multiple package sources. e.g. maybe you want an old version of some package which is only available in an older release of nixpkgs. It would be possible to use the older nixpkgs release to install that old package, and a newer nixpkgs release for the others. -- You even don't have to use the main nixpkgs repository.
> But I suppose this would amount to the user arranging the structure of their filesystem correctly so its one "system" per dir/folder.
Nix handles its filesystem arrangement for all of the "multiple different versions of some package" already. That's part of Nix's value proposition.
This also allows being able have packages available in your shell without having to 'pollute' the rest of the system is a neat dynamic, particularly with direnv.
> Theres clearly more to Nix than just setting up language environments, which I'm guessing is where its usefuleness really kicks in.
Depends how often you (want to) jump into fresh environments, but e.g. Nix allows being able to have a consistent set of programs installed quite easily.
"Nix is a purely functional package manager. This means that it treats packages like values in purely functional programming languages such as Haskell — they are built by functions that don’t have side-effects, and they never change after they have been built. "
"You can have multiple versions or variants of a package installed at the same time. This is especially important when different applications have dependencies on different versions of the same package — it prevents the “DLL hell”."
"Nix helps you make sure that package dependency specifications are complete."
"Nix has multi-user support. This means that non-privileged users can securely install software. "
"Since package management operations never overwrite packages in the Nix store but just add new versions in different paths, they are atomic ... And since package aren’t overwritten, the old versions are still there after an upgrade. This means that you can roll back to the old version"
"In addition to downloading binaries automatically if they’re available, Nix can download binary deltas that patch an existing package in the Nix store into a new version."
"Nix can be used not only for rolling out packages, but also complete configurations of services. This is done by treating all the static bits of a service (such as software packages, configuration files, control scripts, static web pages, etc.) as “packages” that can be built by Nix expressions. As a result, all the features above apply to services as well: for instance, you can roll back a web server configuration if a configuration change turns out to be undesirable, you can easily have multiple instances of a service (e.g., a test and production server), and because the whole service is built in a purely functional way from a Nix expression, it is repeatable so you can easily reproduce the service on another machine."
"You can have multiple versions or variants of a package installed at the same time. This is especially important when different applications have dependencies on different versions of the same package — it prevents the “DLL hell”."
This sounds nice, and it's a direct quote from the product page, but I can guarantee that Nix does nothing of the sort. This would need to be addressed in ld.so. It's simply not possible for a packaging system to solve this problem on a typical unix system.
> I thought that one could just install packages with a package manager.
You could use the command
nix-env -iA mypackage
To install packages, which is like pacman -S mypackage or apt install mypackage.
But... the interesting part of Nix is that it lets you install packages declaratively, by editing a config (like vim and emacs packages). Besides installing packages, all configuration is done through this config file (or bunch of config files): nix generates all files in /etc for you, again, like vim or emacs, but for the whole OS
That way, you easily transfer your setup to another computer or even keep two machines in sync. And you can add it to version control. And you get a grub menu with all your previous setups (until you uninstall them)
If this doesn't appeal you, you probably won't like to use NixOS
Yes, this is what Nix offers. You can trivially have have multiple versions of stuff installed without conflicts. Personally, I have multiple versions of the GHC Haskell compiler, Clang/LLVM, Go, Node, etc. In fact, I keep shell.nix file in each of my repositories at work, and all I have to do is $ nix-shell in each project root and -- like magic -- I have all of the compilers/environment-variables/etc setup for work. Meanwhile, outside of that terminal window, my system is untouched.
Nix is quite different from just about any other package manager out there. If there's something that seems unfeasible or impossible, please feel free to ask specific questions to challenge my assertions. Nix is so different that it will be tempting to think "surely he means... no, that can't be possible, he must be mistaken... but how would that work?" Rather than silently thinking those things, please feel free to skip right to asking "how?"
(For more details, see also my long post to your original statement/question)
One of Nix's benefits is it aims to isolate where programs are installed; so you can have multiple versions of the same program available without conflict. (e.g. programs built with different feature flags, or multiple minor versions).
Nix achieves this by storing packages in a path as some hash of its inputs. -- This then allows either compiling or downloading a package, with confidence that it will behave the same way regardless.
But, since the files were under /nix, if you put them under /opt, then you wouldn't be able to make use of the compilation caches for /nix.
>"Nix is a purely functional package manager. This means that it treats packages like values in purely functional programming languages such as Haskell — they are built by functions that don’t have side-effects, and they never change after they have been built. Nix stores packages in the Nix store, usually the directory /nix/store, where each package has its own unique subdirectory such as
/nix/store/b6gvzjyb2pg0kjfwrjmg1vfhh54ad73z-firefox-33.1/
where b6gvzjyb2pg0… is a unique identifier for the package that captures all its dependencies (it’s a cryptographic hash of the package’s build dependency graph). This enables many powerful features.
Multiple versions
You can have multiple versions or variants of a package installed at the same time. This is especially important when different applications have dependencies on different versions of the same package —
it prevents the “DLL hell”.
Because of the hashing scheme, different versions of a package end up in different paths in the Nix store, so they don’t interfere with each other.
An important consequence is that operations like
upgrading or uninstalling an application cannot break other applications, since these operations never “destructively” update or delete files that are used by other packages."
Could NIX be used as a language package manager? Does it allow installing on cutting-edge code from random repositories? Can you only download something, without installing it? Can you access multiple versions of the same library from a single "project" (e.g. by using different aliases for different versions)?
Software Collections (https://www.softwarecollections.org/en/) give you the power to build, install, and use
multiple versions of software on the same system, without
affecting system-wide installed packages.
Is this what Nix OS is able to do? Install multiple versions of software and select which version to use before running?
It's kind of nice. So everything in nix revolves around /nix/store
This is where each package is stored in a form <hash>-<package name and version>
The second part is only useful for humans and is not really necessary. The hash is computed from package source, compilation flags, dependencies, architecture etc. (there's also experimental mechanism where you can use hash that is computed from the contents of the package, which solves some important problems).
The reason why hash is used, is so you can be able to have not only multiple version of the same package, but you can also have even the same version that maybe even depend on a different package.
For example in a traditional system you could have situation that you need to run two apps, but each of them perhaps depend on a different version of openssl. That situation is generally not possible with some kind of tricks, you either have to recompile one application to use the same library or you will have do some kind of tricks, like compiling statically, or placing openssl in some other location. In Nix you can have two openssl side by side and each package is referencing the one it was compiled with.
The store also is designated that it supposed to only adding packages or removing, you no renames and definitively no changes of the files there. If you do that (well it's linux, you can also change permissions and do that if you really want to, but you're asking for problems)
Now this makes caching easy. Because when you need an application you not only know its name, you know down even to compilation of the flags what it needs to be. So you can simply compute the hash of it. So when it is needed Nix will first check /nix/store. If the package is there, success, you use it, if package is missing, nix can contact configured cache (which can be even an S3 bucket) and check for the package. If package is there it'll download and extract it in your store. If object is missing in remote cache, then nix will begin downloading source code and compiling, because that's how every package is defined (how to build it).
Now that explained the basics, when you invoke nix-shell to enter. The Nix will perform these steps, it'll check if you have the package in your store, if it is missing it'll download from cache, if it is missing in the cache it will begin building, if another dependency is needed it will do that step to it recursively.
Ultimately when the package is present nix-shell will enter a shell, with modified PATH that includes the package(s) that you referenced. You exit the shell you land back in old shell with old PATH. If you use nix for development you can also combine it with a tool like direnv, which can make it so when you cd into a project directory it will ensure that your dev tools are automatically available. And they will disappear when you exit it.
If you were paying attention you might realize that this approach will generally make /nix/store just continue to grow, the new packages are being added all the time. This is especially when you use it for development and you're changing your application, you will get tons of versions of the single app. That indeed is happening and is kind of a drawback, but there's a garbage collection method which you can invoke manually, or you can also schedule it to run periodically. There is also an option (I think more useful for a build machine) where you can specify how much disk space you want to use it, and it will just clean old stuff as you're hitting the disk usage limit.
Anyway, changing PATH is what nix-shell does (originally author said it was meant for debugging (you could enter shell that was used for building the application so you could troubleshoot why build is failing), but it turned out a great feature of its own). NixOS on the other hand works in a way that you have central configuration system where you have a configuration.nix file with all system configuration. When you invoke nixos-rebuild command (typically called with switch parameter to immediately switch to the new config) the NixOS actually is rebuilding the entire system from scratch, the only reason it does not take so long is because all needed files are mostly already in /nix/store and all NixOS needs to do is to recreate symlinks in the root to point to proper packages. This is great, because:
1. you get system exactly as described, unlike SCM like saltstack, ansiblem chef, puppet the nix configuration is truly declarative, and not just imitation of it. For example if you define a package in the configuration file and configure system, then remove that package, after rebuild that package won't be referenced anymore and available (it still will be in the store, but it would be just taking space that you can reclaim with GC)
2. because symlinks are used, and packages aren't replaced in-place. You can actually make a rollback. Let say you have your system running and you want to try Wayland. You make changes to the configuration to install it, maybe the process failed for some reason or you realized you want restore things back to where they were. You can just revert to a previous version. This also will be a very quick process since you likely still have your old packages installed and nothing new needs to be downloaded.
It's really a new very different way of thinking about packages and about OS, and this approach solves so many problems with the status quo we have right now. Also, removes need for the SCM tools as mentioned above.
> Yet there is no way of "declaring" which version of given package you want to install
But there is? First, by pinning nixpkgs you pin to whatever set of versions was within nixpkgs at the time. Then, if you want to change the version of a package, you can use overlays to poke at what source version is being used to build a package (or what flags it's being built with, etc). There's also nothing preventing your from mixing derivations from multiple nixpkgs pins within a single nixpkgs/nixos fixpoint for your system.
Stuff that in your shell.nix or /etc/nixos/configuration.nix or just nix-build it straight from a small .nix file.
Yes. NixOs uses the NiX package manager (that you can install in any other distro too).
The NiX package manager installs each version of a package to a directory, the trick being that each version of each package goes to a folder whose name is a hash of all the inputs of the build (files, build parameters, specific build folders of this builds dependencies, etc).
As a result, not only can you have different versions of a package: you can even have different builds of the same version (that you built with different build configuration and/or versiona of its dependencies).
The concept is sound. The issue is that you need the ability to actually build the application (you need the source) and you probably have to adjust its own build process to get it to work properly with NiX.
> Actually, I already find it strand that you can call the package manager like that, shouldn't there be a declaration of the packages I want somewhere, should I not add the package that list (maybe a Yaml, like my docker-compose.yaml?) then ask Nix to make the installation consistent with the declaration?
Yes, I completely avoid 'nix-env' for that reason. It maintains a bunch of symlinks behind-the-scenes, but the 'nix-env' command itself is imperative.
If you use NixOS, the config option 'env.systemPackages' specifies which programs to install. This can be declared in the /etc/nixos/configuration.nix file. There are similar approaches when using Nix on non-NixOS systems (e.g. using the 'buildEnv' function from Nixpkgs to combine multiple programs into a single derivation/package, and install that)
The above is sometimes true and sometimes not. For the most part, Nix can install multiple versions of a program but only one can be in use at any given time.
Nix is for the most part shell based workflow (as in bash, zsh, etc.). The `nix-shell` command lets you switch out the packages (and versions of packages) that are used in any given shell, but it works off of a configuration file written in the Nix language that you write. The programs that are available are controlled by environment variables such as PATH and MANPATH.
Nix is a big shift from the usual way of dealing with packages, programs, etc. It isn't really useful until you really make the effort to understand what is going on, learn the Nix language, etc. If you are not interested in "programming" your system, then it probably isn't for you.
reply