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.
+
+
+
+