Last active
August 13, 2025 12:02
-
-
Save kyokley/03e6a4e21f29171e0df2c3d51bfc47ce to your computer and use it in GitHub Desktop.
Uv2nix template
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
description = "My Python App with Nix and uv2nix"; | |
inputs = { | |
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; | |
flake-utils.url = "github:numtide/flake-utils"; | |
# Core pyproject-nix ecosystem tools | |
pyproject-nix.url = "github:pyproject-nix/pyproject.nix"; | |
uv2nix.url = "github:pyproject-nix/uv2nix"; | |
pyproject-build-systems.url = "github:pyproject-nix/build-system-pkgs"; | |
# Ensure consistent dependencies between these tools | |
pyproject-nix.inputs.nixpkgs.follows = "nixpkgs"; | |
uv2nix.inputs.nixpkgs.follows = "nixpkgs"; | |
pyproject-build-systems.inputs.nixpkgs.follows = "nixpkgs"; | |
uv2nix.inputs.pyproject-nix.follows = "pyproject-nix"; | |
pyproject-build-systems.inputs.pyproject-nix.follows = "pyproject-nix"; | |
}; | |
outputs = { self, nixpkgs, flake-utils, uv2nix, pyproject-nix, pyproject-build-systems, ... }: | |
flake-utils.lib.eachDefaultSystem (system: | |
let | |
pkgs = import nixpkgs { inherit system; }; | |
python = pkgs.python312; # Your desired Python version | |
# 1. Load Project Workspace (parses pyproject.toml, uv.lock) | |
workspace = uv2nix.lib.workspace.loadWorkspace { | |
workspaceRoot = ./.; # Root of your flake/project | |
}; | |
# 2. Generate Nix Overlay from uv.lock (via workspace) | |
uvLockedOverlay = workspace.mkPyprojectOverlay { | |
sourcePreference = "wheel"; # Or "sdist" | |
}; | |
# 3. Placeholder for Your Custom Package Overrides | |
myCustomOverrides = final: prev: { | |
# e.g., some-package = prev.some-package.overridePythonAttrs (...); */ | |
}; | |
# 4. Construct the Final Python Package Set | |
pythonSet = | |
(pkgs.callPackage pyproject-nix.build.packages { inherit python; }) | |
.overrideScope (nixpkgs.lib.composeManyExtensions [ | |
pyproject-build-systems.overlays.default # For build tools | |
uvLockedOverlay # Your locked dependencies | |
myCustomOverrides # Your fixes | |
]); | |
# --- This is where your project's metadata is accessed --- | |
projectNameInToml = "project-name"; # MUST match [project.name] in pyproject.toml! | |
thisProjectAsNixPkg = pythonSet.${projectNameInToml}; | |
# --- | |
# 5. Create the Python Runtime Environment | |
appPythonEnv = pythonSet.mkVirtualEnv | |
(thisProjectAsNixPkg.pname + "-env") | |
workspace.deps.default; # Uses deps from pyproject.toml [project.dependencies] | |
in | |
{ | |
# Development Shell | |
devShells.default = pkgs.mkShell { | |
packages = [ appPythonEnv pkgs.ruff pkgs.uv ]; | |
shellHook = '' # Your custom shell hooks */ ''; | |
}; | |
# Nix Package for Your Application | |
packages.default = pkgs.stdenv.mkDerivation { | |
pname = thisProjectAsNixPkg.pname; | |
version = thisProjectAsNixPkg.version; | |
src = ./.; # Source of your main script | |
nativeBuildInputs = [ pkgs.makeWrapper ]; | |
buildInputs = [ appPythonEnv ]; # Runtime Python environment | |
installPhase = '' | |
mkdir -p $out/bin | |
cp main.py $out/bin/${thisProjectAsNixPkg.pname}-script | |
chmod +x $out/bin/${thisProjectAsNixPkg.pname}-script | |
makeWrapper ${appPythonEnv}/bin/python $out/bin/${thisProjectAsNixPkg.pname} \ | |
--add-flags $out/bin/${thisProjectAsNixPkg.pname}-script | |
''; | |
}; | |
packages.${thisProjectAsNixPkg.pname} = self.packages.${system}.default; | |
# App for `nix run` | |
apps.default = { | |
type = "app"; | |
program = "${self.packages.${system}.default}/bin/${thisProjectAsNixPkg.pname}"; | |
}; | |
apps.${thisProjectAsNixPkg.pname} = self.apps.${system}.default; | |
} | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
For anyone that comes across this gist, I don't want to claim this template as my own creation but lost track of where I came across it originally. If you recognize this, contact me so I can add proper attribution