bedHedd's dip into NixOS

getting uv to be my python environment manager in nix

I wanted uv to manage my python environments rather than nix. While trying to use a uv venv with the a vscodium jupyter notebook, I kept getting these errors

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/bedhedd/Documents/development-projects/.venv/lib/python3.12/site-packages/zmq/backend/cython/__init__.py", line 6, in <module>
    from . import _zmq
ImportError: libstdc++.so.6: cannot open shared object file: No such file or directory

When I run find /nix/store -name 'libstdc++.so.6', the package shows up, but for whatever reason uv couldn’t get it working.

This page was helpful in configuring it to resolve
https://wiki.nixos.org/wiki/Python#Using_nix-ld

specifically this block, where they set a environment variable called LD_LIBRARY_PATH which points a valid libstdc++.so.6 path found with the find command

to apply these changes

{
  programs.nix-ld = {
    enable = true;
    libraries = with pkgs; [
      zlib zstd stdenv.cc.cc curl openssl attr libssh bzip2 libxml2 acl libsodium util-linux xz systemd
    ];
  };
  # https://github.com/nix-community/nix-ld?tab=readme-ov-file#my-pythonnodejsrubyinterpreter-libraries-do-not-find-the-libraries-configured-by-nix-ld
  environment.systemPackages = [
    (pkgs.writeShellScriptBin "python" ''
      export LD_LIBRARY_PATH=$NIX_LD_LIBRARY_PATH
      exec ${pkgs.python3}/bin/python "$@"
    '')
  ];
  # another (dangerous) solution
  # environment.systemPackages = with pkgs; [ python3 ];
  # programs.bash = {
  #   enable = true;
  #   initExtra = ''
  #     export LD_LIBRARY_PATH=$LD_LIBRARY_PATH''${LD_LIBRARY_PATH:+:}$NIX_LD_LIBRARY_PATH
  #   '';
  # };
}

I had chatgpt rewrite the solution to work with my config. There was a lot of trial and error, but this is the solution that ultimately worked.

While researching solutions, I came across this post.

While the author is correct of using the nix way, the post was not helpful as the suggestion to use devshells, but did not link a best practice or reference. Furthermore, I wanted uv to manage all my python environments it is much faster than nix at building dependencies.

git diffs

Here’s the git diff of the changes that I applied to get it working with my environment.

fish config

I added the pkgs inheritance so that the environment variable UV_PYTHON would be able to point to the nix package. I also added a fish function so that if vscodium creates a terminal, it will be able to activate into the fish file rather than get stuck on the bash version

diff --git a/dotfiles/fish-config.nix b/dotfiles/fish-config.nix
index eb09839..20a6d61 100644
--- a/dotfiles/fish-config.nix
+++ b/dotfiles/fish-config.nix
@@ -1,4 +1,4 @@
-{ }:
+{ pkgs }:
 ''
 # Custom Fish configuration extras
 set -g fish_key_bindings fish_default_key_bindings
@@ -22,4 +22,25 @@ set -gx EDITOR nvim
 set -gx VISUAL nvim
 
 
+set -x UV_PYTHON_PREFERENCE only-system
+set -x UV_PYTHON ${pkgs.python312Full}/bin/python
+
+function source --wraps=source
+    set -l file $argv[1]
+    if test -n "$file"
+        if string match -q "*.venv/bin/activate" "$file"
+            set -l fish_file "$file.fish"
+            if test -f "$fish_file"
+                echo "activating environment: $fish_file"
+                builtin source "$fish_file"
+                return $status
+            else
+                echo "No fish activation script found!" 1>&2
+                return 1
+            end
+        end
+    end
+    builtin source $argv
+end
+
 ''

home changes

I also moved uv from a user specific to a system wide install. I also applied the changes to update python to include the environment variable for LD_LIBRARY_PATH.

While searching for jupyter on nixpkgs I came across the vscode extensions. I added them because it made sense to have for all users.

The last change is making sure fish is able to import/inherit the pkgs so that the environment variable works

diff --git a/modules/home.nix b/modules/home.nix
index b3fcfc8..f18c43e 100644
--- a/modules/home.nix
+++ b/modules/home.nix
@@ -29,6 +29,15 @@
       tree
       fastfetch
       tealdeer
+      
+      gcc
+      uv
+      (pkgs.writeShellScriptBin "python3" ''
+        export LD_LIBRARY_PATH=$NIX_LD_LIBRARY_PATH
+        exec ${pkgs.python3}/bin/python3 "$@"
+      '')
+      vscode-extensions.ms-toolsai.jupyter
+      vscode-extensions.ms-python.python
 
       # dictionaries
       # aspell
@@ -43,6 +52,11 @@
     stateVersion = "22.05";
   };
 
+  home.sessionVariables = {          # <── needs the `home.` prefix
+    LD_LIBRARY_PATH =
+      "${pkgs.lib.makeLibraryPath [ pkgs.stdenv.cc.cc.lib ]}:$LD_LIBRARY_PATH";
+  };
+  
   #nix = {
     #package = pkgs.nixUnstable;
     #settings = {
@@ -56,7 +70,7 @@
     direnv.enable = true;
     fish = {
       enable = true;
-      interactiveShellInit = import ../dotfiles/fish-config.nix {};
+      interactiveShellInit = import ../dotfiles/fish-config.nix { inherit pkgs; };
       plugins = [
         #{ name = "grc"; src = pkgs.fishPlugins.grc.src; }
         #{

If you want to replicate my environment, you can find it at this git repo