diff --git a/packages/projects.nix b/packages/projects.nix index aaff18f..99deb71 100644 --- a/packages/projects.nix +++ b/packages/projects.nix @@ -27,6 +27,7 @@ ./build-support ./websites/landing/project.nix + ./websites/stop-using-nix-env/project.nix ]; packages = filters.doFilter filters.packages rec { uptime-kuma = let diff --git a/packages/websites/stop-using-nix-env/project.nix b/packages/websites/stop-using-nix-env/project.nix new file mode 100644 index 0000000..9128de2 --- /dev/null +++ b/packages/websites/stop-using-nix-env/project.nix @@ -0,0 +1,17 @@ +{ pkgs, ... }: + +{ + packages.stop-using-nix-env = let + site = with pkgs; stdenvNoCC.mkDerivation rec { + name = "stop-using-nix-env"; + version = "1.0.0"; + src = ./src; + buildCommand = '' + install -Dm644 $src/* -t $out/share/www/${name} + ''; + passthru = { + webroot = "${site}/share/www/${name}"; + }; + }; + in site; +} diff --git a/packages/websites/stop-using-nix-env/src/index.html b/packages/websites/stop-using-nix-env/src/index.html new file mode 100644 index 0000000..11d038d --- /dev/null +++ b/packages/websites/stop-using-nix-env/src/index.html @@ -0,0 +1,209 @@ + + + + + +

Stop using nix-env.

+

For the sake of you and others.

+

+ nix-env was built as tool for Nix + as a way to manage packages in a traditional (imperative) fashion. + It tries to bridge the gap between the imperative and declarative + world. A replacement for the venerable + "just sudo apt install <anything>". + As a result of its design, it often causes unexpected bevahior. + This page is dedicated to explaining what its issues are and what + to use instead. +

+

Installing packages by derivation name

+

+ Packages in Nix are usually bundled in attribute sets. Each + attribute name represents the name of a package. When installing + packages declaratively through NixOS or Home Manager, or when declaring + a package's dependencies, these are referred to using their attribute + name. When installing packages via nix-env -i, + attribute names are ignored. Instead, nix-env traverses + the entire attribute set to find a package with a matching + derivation name. This can lead to fun surprises when + the derivation name does not match the attribute name, such as + installing an unwrapped package that requires a wrapper to function + properly. This can be avoided by using nix-env -iA + instead, which picks packages via attribute name, but does not + note down from which attribute path a package originally came from, + resulting in surprises when upgrading it. +

+
+    
+      {
+
+        package = < derivation package-wrapper-1.3 >;
+
+        package-unwrapped = < derivation package-1.3 >;
+
+      }
+    
+  
+

Name collisions when upgrading packages

+

+ nix-env -u will upgrade all packages in your profile + by searching through the attribute set for a derivation with the same + derivation name and a higher version number. When using large, + nested package collections like nixpkgs, derivations from different + language ecosystems may be stored under a distinct attribute path, + but their derivation name may be the same, despite the two packages + being clearly different otherwise. +

+
+    
+      {
+
+        zstd = < derivation zstd-2.0 >;
+
+        haskellPackages = {
+
+          zstd = < derivation zstd-3.0 >;
+
+        };
+
+      }
+    
+  
+

Unintentional major version jumps

+

+ Nixpkgs sometimes keeps multiple major versions for packages that have + multiple continuously maintained release trains, such as PostgreSQL. + Because the distinction between major versions is done via attribute + names, nix-env completely ignores it. When installing + postgresql_12 via its attribute name, you would + expect PostgreSQL to stay at major version 12, even when upgraded. + Even though postgresql_12 and + postgresql_14 may exist in parallel within the same + nixpkgs revision, nix-env ignores this fact and will + happily upgrade your PostgreSQL package to major version 14. +

+

Performance issues

+

+ As you may have already guessed, iterating over a large package set and + evaluating every derivation in it is + not very efficient. +

+

Non-obvious shadowing

+

+ nix-env installs packages into a user-specific + profile that has precedence over system-level directories in + $PATH. This means that you can install a + different version of any tool in your user profile without the rest of + the system having to use that version. If you forget that you installed + a program into your user profile like this, you may end up with a nasty + surprise later down the line. +

+

+ For example, installing busybox this way would shadow + common utilities such as ls, cat or + grep. The next time you would try to use a GNU-specific + feature of grep months down the line, you might end up + going on a wild goose chase to figure out why your version of + grep behaves differently than everyone else's. +

+

Informational Video by Matthew Croughan

+

Matthew Croughan demonstrates some of the issues with nix-env. + +

+

Alternatives

+

+ So, nix-env is bad. What do we use instead? First, + it's important to consider that Nix is a far more powerful package + manager than your garden variety ones like APT or DNF. As such, there + is more than one way to provide a package. Merely installing + the package is probably never your end goal. Consider what you want + to do with this package, and then choose how to expose the package + in the target environment appropriately. +

+

Declarative package management

+

+ This is the best choice for any packages you expect to be + long-living. Any applications that you commonly use should be + managed in this way. Packages can be managed declaratively through + tools such as NixOS configuration or Home Manager. These will often + also provide a set of options to configure the application in Nix code. + System services should only be configured through these options, + which will automatically define a suitable systemd service according + to your specifications. +

+

Ephemeral shell environments

+

+ Do you often run into a situation where you need a particular command + for a one-off thing, but don't feel like it should reside on your system + at all times? + Ephemeral shells + allow you to gain temporary access to a command and after you exit + out of the shell, it's as if the package was never installed. + If you're using Flakes, + nix shell + may be more up your alley. +

+

nix profile

+

+ Lastly, + nix profile + from the Nix 3.0 (Flakes) set of CLI commands aims to provide a more + polished imperative package management solution. If you really need to + imperatively manage some of your packages, this is your best option. + It picks packages by attribute name rather than derivation name and it + keeps track of the attribute path from which each package was installed, + meaning name collisions when upgrading are eliminated. Thanks to Flakes, + it also allows you to easily install packages from package collections + other than nixpkgs. +

+
+ +