️ The pain of the traditional approach#
On Arch Linux, if you install gcc, libxml2, libxslt to compile a Python project, those packages remain in the global environment until explicitly removed, and may cause version conflicts between projects.
On NixOS: You can define an environment in the project directory and return to the outer shell when you exit; objects in the store remain until garbage collection removes them.
️ Stage 1: nix-shell#
Enter a temporary environment.
nix-shell -p python311 python311Packages.requests gcc
# 此时你进入了一个包含这些包的子 shell
# 退出后,这些包依然在 /nix/store,但你的 PATH 会被恢复原状Stage 2: Flake-driven devShells#
In a modern workflow, we define the environment in the project’s flake.nix:
{
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
outputs = { self, nixpkgs, ... }:
let
pkgs = nixpkgs.legacyPackages.x86_64-linux;
in {
devShells.x86_64-linux.default = pkgs.mkShell {
# 运行时依赖
buildInputs = [ pkgs.python3 ];
# 构建时环境变量
shellHook = ''
echo "欢迎进入 Python 开发环境!"
export MY_VAR="foo"
'';
};
};
}Run nix develop to enter it.
Stage 3: Automation with Direnv#
Manually running nix develop every time is tedious. With direnv, the environment loads automatically as soon as you enter the directory.
1. Enable direnv
In Home Manager:
{
programs.direnv = {
enable = true;
nix-direnv.enable = true;
};
}2. Use it in a project
Create an .envrc in the project root:
use flakeRun direnv allow once. The next time you cd into this directory, the terminal will automatically display direnv: loading..., and all your tools and environment variables will be ready!
Why is this useful?#
- Version isolation: Project A uses Python 3.9 and project B uses Python 3.12, without interfering with each other.
- Team consistency: Share
flake.nix,flake.lock, and.envrcwith your colleagues, and match the target platform. The lock file pins input revisions, while running services, external downloads, and system state can still affect the actual result.
Authorization and shell integration
direnv allow authorizes the .envrc in the current directory to execute shell code, so read it first. Home Manager configuration must be paired with the appropriate shell integration. Changing directories restores environment variables; it does not automatically stop a database started by shellHook.
References & further reading
Adapted from technical notes. Examples use generic names.