Simple uv usage

Hello,

I usually use python with a simple shell generated like this

{
  description = "Python env";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
  };

  outputs =
    { self, nixpkgs }:
    let
      pkgs = nixpkgs.legacyPackages."x86_64-linux";
    in
    {
      devShells."x86_64-linux".default = pkgs.mkShell {
        packages =
          with pkgs;
          [ python312 ]
          ++ (with pkgs.python312Packages; [
            numpy
          ]);

        DIRENV = "python";
      };
    };
}

So I simply install python and python packages in nixpkgs. However I need to use uv which seems great and I can’t figure it out. If I simply try to uv init project and uv add <package> I get an error ImportError: libstdc++.so.6: cannot open shared object file: No such file or directory

I know there’s uv2nix but it seems overly complicated and I didn’t find a simple solution. Ideally I would like to adapt my flake.nix for the shell that makes uv works like in traditional distro with uv add or uv run, whether it translate to nix derivation or directly run the package from uv, i don’t care.

Do you have working example ?

1 Like

Did you install uv as a Nix package? What do you get when you run nix-shell -p uv?

I installed uv as a package and with nix-shell -p uv. This works well and I can create and run project, but as soon as I try to add package (like numpy) that need shared C library, it doens’t work because it isn’t able to properly locate and link the libraries. This is a typical issue with nix but I don’t know how to solve it in this case

This is a very common problem. You need a buildFHSenv to emulate an FHS filesystem with library locations that the precompiled packages from PyPI expect. This is mine:

https://gitlab.com/nobodyinperson/nixconfig/-/blob/main/modules/fhs.nix?ref_type=heads

This produces an fhs executable that I execute before doing Python stuff like that. It drops me into a shell where it just works.

Is it possible to combine this with a shell you create using mkShell? The idea is to have a single flake.nix that activates a shell with direnv when I enter my project, specifies some packages, and, in addition, activates this FHS environment you mentioned so I can do stuff like pip install or uv add.

Yep!

# shell.nix
buildFHSEnv {
  name = "my-env";

  targetPkgs = pkgs: with pkgs; [ ... ];
}).env # important part

Running nix-shell or nix develop will drop you into a shell inside of an FHS env. Everything will be linked into their respective FHS locations, like /usr/lib, /usr/bin, /usr/include, etc.

Weirdly, for me, when uv manages its own Python, I don’t have problems with numpy et al. I think uv downloads a kinda portable Python executable that somehow fixes the basic library problems idk? I don’t use nix-ld or an fhsenv, it just magically works and I really wonder why :sweat_smile:

EDIT: Whoops, I do in fact use nix-ld :man_facepalming: modules/fhs.nix · da888166967368457eeee3e8dbffeed23a16b098 · Yann Büchau / 📦 Yanns NixOS Config · GitLab Apparently that just makes uv work as anywhere else. If you make your nix shell also for non-nixos, then you could just let uv do its magic for packaging on all platforms and only use nix to pin the uv itself and external deps. That’s how I do it now.

I made a recipe on Substack and Medium about using uv on NixOS. I think it will help you.

starts a temporary Nix shell that includes the uv package.
uv is not installed system**-**wide; it is available only inside that shell.
Once the shell exits, uv is no longer available.

for a reproducible, VM-like environment, use a dev shell with shell.nix or flakes via flake.nix.