跳转至

Nix 包管理

为什么要学

Nix 是一个革命性的包管理器和构建系统,核心特性是完全可复现

  • 可复现构建:同样的输入永远产生同样的输出
  • 环境隔离:每个项目有独立的依赖环境,不冲突
  • 声明式配置:用代码描述你要什么环境/系统
  • 原子升级/回滚:更新失败?一秒回滚
  • 80000+ 包:Nixpkgs 是最大的包仓库之一
  • 多用途:包管理/开发环境/系统配置/Docker 镜像构建

如果你受够了"在我机器上能跑"的问题,Nix 是终极解决方案。

核心概念

白话解释

  • Nix Store (/nix/store/):所有包的"仓库",每个版本独立存放
  • Hash 路径/nix/store/abc123-python-3.11.0/ — 路径包含内容哈希,不同版本不冲突
  • Nix 表达式:描述"如何构建"的纯函数式语言
  • Flake:现代化的项目配置方式(类似 package.json)
  • devShell:声明式的开发环境(替代 conda/virtualenv/nvm)

核心概念对照表

Nix传统方式说明
nix-shell / devShellvirtualenv/conda开发环境
Nixpkgsapt/brew/pip包仓库
Flakepackage.json项目配置
/nix/store/usr/lib, site-packages包存储
nixos-rebuildapt upgrade系统更新
Home Managerdotfiles用户配置管理
DerivationMakefile target构建描述
NixOSUbuntu/Fedora声明式Linux发行版

安装配置

# 单用户安装(Linux/macOS)
sh <(curl -L https://nixos.org/nix/install)

# 多用户安装(推荐,需要sudo)
sh <(curl -L https://nixos.org/nix/install) --daemon

# 启用Flakes(新特性)
mkdir -p ~/.config/nix
echo "experimental-features = nix-command flakes" >> ~/.config/nix/nix.conf

# 验证
nix --version

快速上手

临时使用包

# 临时进入有python3的环境(不永久安装)
nix shell nixpkgs#python3

# 运行一次性命令
nix run nixpkgs#cowsay -- "Hello Nix!"

# 同时使用多个包
nix shell nixpkgs#python3 nixpkgs#nodejs nixpkgs#ripgrep

开发环境(Flake)

# flake.nix - 项目根目录
{
  description = "我的Python项目";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    flake-utils.url = "github:numtide/flake-utils";
  };

  outputs = { self, nixpkgs, flake-utils }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = nixpkgs.legacyPackages.${system};
      in {
        devShells.default = pkgs.mkShell {
          buildInputs = with pkgs; [
            python311
            python311Packages.pandas
            python311Packages.numpy
            python311Packages.jupyter
            nodejs_20
            postgresql_16
            redis
          ];

          shellHook = ''
            echo "开发环境已就绪!"
            echo "Python: $(python --version)"
            echo "Node: $(node --version)"
          '';
        };
      }
    );
}
# 进入开发环境
nix develop

# 或自动进入(配合direnv)
echo "use flake" > .envrc
direnv allow
# 进入目录自动加载环境!

搜索包

# 搜索可用包
nix search nixpkgs python
nix search nixpkgs nodePackages.typescript

# 在线搜索: https://search.nixos.org

进阶用法

1. Home Manager(用户环境管理)

# home.nix - 声明式管理你的工具和配置
{ config, pkgs, ... }:
{
  home.packages = with pkgs; [
    ripgrep
    fd
    bat
    eza
    starship
    neovim
    git
    gh
  ];

  programs.git = {
    enable = true;
    userName = "Your Name";
    userEmail = "you@example.com";
    extraConfig = {
      init.defaultBranch = "main";
      pull.rebase = true;
    };
  };

  programs.starship = {
    enable = true;
    settings = {
      character.success_symbol = "[➜](bold green)";
    };
  };
}

2. Docker 镜像构建

# 用Nix构建极小Docker镜像(无基础镜像层)
{ pkgs }:
pkgs.dockerTools.buildImage {
  name = "my-app";
  tag = "latest";

  contents = [
    pkgs.python311
    pkgs.python311Packages.flask
  ];

  config = {
    Cmd = [ "python" "-m" "flask" "run" "--host=0.0.0.0" ];
    WorkingDir = "/app";
    ExposedPorts = { "5000/tcp" = {}; };
  };
}
# 产出: 极小镜像(只包含需要的)

3. NixOS(声明式操作系统)

# /etc/nixos/configuration.nix
{ config, pkgs, ... }:
{
  # 系统包
  environment.systemPackages = with pkgs; [
    vim git wget curl
  ];

  # 服务
  services.postgresql.enable = true;
  services.nginx = {
    enable = true;
    virtualHosts."mysite.com" = {
      root = "/var/www";
      enableACME = true;
      forceSSL = true;
    };
  };

  # 用户
  users.users.myuser = {
    isNormalUser = true;
    extraGroups = [ "wheel" "docker" ];
  };

  # 防火墙
  networking.firewall.allowedTCPPorts = [ 80 443 ];
}
# 应用配置(原子性!)
sudo nixos-rebuild switch

# 回滚到上一版本
sudo nixos-rebuild switch --rollback

4. 多语言项目环境

# 一个项目同时需要Python + Rust + Node
devShells.default = pkgs.mkShell {
  buildInputs = with pkgs; [
    # Python
    python311
    python311Packages.pip

    # Rust
    rustc
    cargo
    rust-analyzer

    # Node.js
    nodejs_20
    nodePackages.pnpm

    # 工具
    docker-compose
    awscli2
    terraform
  ];

  # 环境变量
  RUST_LOG = "debug";
  DATABASE_URL = "postgresql://localhost/dev";
};

5. CI/CD 中使用 Nix

# GitHub Actions
name: Build
on: push
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: cachix/install-nix-action@v25
      - uses: cachix/cachix-action@v14
        with:
          name: my-cache
      - run: nix build
      - run: nix flake check

常见问题

Q1: 学习曲线陡峭?

确实。Nix 语言和概念需要时间适应。建议渐进式采用: 1. 先用 nix shell 临时使用包 2. 再用 flake.nix 管理项目环境 3. 然后尝试 Home Manager 4. 最后考虑 NixOS

Q2: 占用空间大?

/nix/store 会累积旧版本。定期清理:

nix-collect-garbage -d  # 删除所有旧版本
nix store gc            # 清理未引用的路径

Q3: macOS 支持如何?

完全支持。nix-darwin 项目让你在 macOS 上也能享受声明式系统配置。

Q4: vs Docker?

方面NixDocker
定位构建+环境打包+运行
隔离级别依赖级系统级
开发体验原生工具链容器内开发
性能原生有开销
可组合
互补可以用Nix构建Docker镜像

Q5: vs asdf/mise?

Nix 比 asdf/mise 更底层更强大(不仅管理语言版本,还管理系统包、库、配置),但也更复杂。简单版本管理用 mise,完整环境管理用 Nix。

参考资源