nix-best-practices
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseNix Best Practices
Nix 最佳实践
Flake Structure
Flake 结构
Standard flake.nix structure:
nix
{
description = "Project description";
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 = import nixpkgs {
inherit system;
};
in {
devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [
# packages here
];
};
});
}标准的flake.nix结构:
nix
{
description = "Project description";
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 = import nixpkgs {
inherit system;
};
in {
devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [
# packages here
];
};
});
}Follows Pattern (Avoid Duplicate Nixpkgs)
遵循依赖跟随模式(避免重复下载Nixpkgs)
When adding overlay inputs, use to share the parent nixpkgs and avoid downloading multiple versions:
followsnix
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
# Overlay follows parent nixpkgs
some-overlay.url = "github:owner/some-overlay";
some-overlay.inputs.nixpkgs.follows = "nixpkgs";
# Chain follows through intermediate inputs
another-overlay.url = "github:owner/another-overlay";
another-overlay.inputs.nixpkgs.follows = "some-overlay";
};All inputs must be listed in outputs function even if not directly used:
nix
outputs = { self, nixpkgs, some-overlay, another-overlay, ... }:添加overlay输入时,使用来共享父级nixpkgs,避免下载多个版本:
followsnix
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
# Overlay follows parent nixpkgs
some-overlay.url = "github:owner/some-overlay";
some-overlay.inputs.nixpkgs.follows = "nixpkgs";
# Chain follows through intermediate inputs
another-overlay.url = "github:owner/another-overlay";
another-overlay.inputs.nixpkgs.follows = "some-overlay";
};所有输入必须在outputs函数中列出,即使没有直接使用:
nix
outputs = { self, nixpkgs, some-overlay, another-overlay, ... }:Applying Overlays
应用Overlays
Overlays modify or add packages to nixpkgs:
nix
let
pkgs = import nixpkgs {
inherit system;
overlays = [
overlay1.overlays.default
overlay2.overlays.default
# Inline overlay
(final: prev: {
myPackage = prev.myPackage.override { ... };
})
];
};
inOverlays用于修改或向nixpkgs中添加软件包:
nix
let
pkgs = import nixpkgs {
inherit system;
overlays = [
overlay1.overlays.default
overlay2.overlays.default
# Inline overlay
(final: prev: {
myPackage = prev.myPackage.override { ... };
})
];
};
inHandling Unfree Packages
处理非自由软件
Option 1: nixpkgs-unfree (Recommended for Teams)
选项1:nixpkgs-unfree(团队推荐方案)
Use numtide/nixpkgs-unfree for EULA-licensed packages without requiring user config:
nix
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
nixpkgs-unfree.url = "github:numtide/nixpkgs-unfree/nixos-unstable";
nixpkgs-unfree.inputs.nixpkgs.follows = "nixpkgs";
# Unfree overlay follows nixpkgs-unfree
proprietary-tool.url = "github:owner/proprietary-tool-overlay";
proprietary-tool.inputs.nixpkgs.follows = "nixpkgs-unfree";
};This chains: → →
proprietary-toolnixpkgs-unfreenixpkgs使用numtide/nixpkgs-unfree来获取受EULA许可的软件包,无需用户配置:
nix
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
nixpkgs-unfree.url = "github:numtide/nixpkgs-unfree/nixos-unstable";
nixpkgs-unfree.inputs.nixpkgs.follows = "nixpkgs";
# Unfree overlay follows nixpkgs-unfree
proprietary-tool.url = "github:owner/proprietary-tool-overlay";
proprietary-tool.inputs.nixpkgs.follows = "nixpkgs-unfree";
};依赖链为: → →
proprietary-toolnixpkgs-unfreenixpkgsOption 2: User Config
选项2:用户配置
Users add to :
~/.config/nixpkgs/config.nixnix
{ allowUnfree = true; }用户添加配置到:
~/.config/nixpkgs/config.nixnix
{ allowUnfree = true; }Option 3: Specific Packages (Flake)
选项3:指定软件包(Flake中)
nix
let
pkgs = import nixpkgs {
inherit system;
config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [
"specific-package"
];
};
inNote: in flake.nix doesn't work with - use nixpkgs-unfree or user config.
config.allowUnfreenix developnix
let
pkgs = import nixpkgs {
inherit system;
config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [
"specific-package"
];
};
in注意:flake.nix中的在中不生效 - 请使用nixpkgs-unfree或用户配置。
config.allowUnfreenix developCreating Binary Overlay Repos
创建二进制Overlay仓库
When nixpkgs builds a community version lacking features (common with open-core tools), create an overlay that fetches official binaries.
当nixpkgs构建的社区版本缺少功能时(开源核心工具中常见),可以创建一个获取官方二进制文件的overlay。
Pattern (see 0xBigBoss/atlas-overlay, 0xBigBoss/bun-overlay)
模式参考(可查看0xBigBoss/atlas-overlay, 0xBigBoss/bun-overlay)
nix
{
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};
version = "1.0.0";
# Platform-specific binaries
sources = {
"x86_64-linux" = {
url = "https://example.com/tool-linux-amd64-v${version}";
sha256 = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};
"aarch64-linux" = {
url = "https://example.com/tool-linux-arm64-v${version}";
sha256 = "sha256-BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=";
};
"x86_64-darwin" = {
url = "https://example.com/tool-darwin-amd64-v${version}";
sha256 = "sha256-CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC=";
};
"aarch64-darwin" = {
url = "https://example.com/tool-darwin-arm64-v${version}";
sha256 = "sha256-DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD=";
};
};
source = sources.${system} or (throw "Unsupported system: ${system}");
toolPackage = pkgs.stdenv.mkDerivation {
pname = "tool";
inherit version;
src = pkgs.fetchurl {
inherit (source) url sha256;
};
sourceRoot = ".";
dontUnpack = true;
installPhase = ''
mkdir -p $out/bin
cp $src $out/bin/tool
chmod +x $out/bin/tool
'';
meta = with pkgs.lib; {
description = "Tool description";
homepage = "https://example.com";
license = licenses.unfree; # or appropriate license
platforms = builtins.attrNames sources;
};
};
in {
packages.default = toolPackage;
packages.tool = toolPackage;
overlays.default = final: prev: {
tool = toolPackage;
};
})
// {
overlays.default = final: prev: {
tool = self.packages.${prev.system}.tool;
};
};
}nix
{
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};
version = "1.0.0";
# Platform-specific binaries
sources = {
"x86_64-linux" = {
url = "https://example.com/tool-linux-amd64-v${version}";
sha256 = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};
"aarch64-linux" = {
url = "https://example.com/tool-linux-arm64-v${version}";
sha256 = "sha256-BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=";
};
"x86_64-darwin" = {
url = "https://example.com/tool-darwin-amd64-v${version}";
sha256 = "sha256-CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC=";
};
"aarch64-darwin" = {
url = "https://example.com/tool-darwin-arm64-v${version}";
sha256 = "sha256-DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD=";
};
};
source = sources.${system} or (throw "Unsupported system: ${system}");
toolPackage = pkgs.stdenv.mkDerivation {
pname = "tool";
inherit version;
src = pkgs.fetchurl {
inherit (source) url sha256;
};
sourceRoot = ".";
dontUnpack = true;
installPhase = ''
mkdir -p $out/bin
cp $src $out/bin/tool
chmod +x $out/bin/tool
'';
meta = with pkgs.lib; {
description = "Tool description";
homepage = "https://example.com";
license = licenses.unfree; # or appropriate license
platforms = builtins.attrNames sources;
};
};
in {
packages.default = toolPackage;
packages.tool = toolPackage;
overlays.default = final: prev: {
tool = toolPackage;
};
})
// {
overlays.default = final: prev: {
tool = self.packages.${prev.system}.tool;
};
};
}Getting SHA256 Hashes
获取SHA256哈希值
bash
nix-prefetch-url https://example.com/tool-linux-amd64-v1.0.0bash
nix-prefetch-url https://example.com/tool-linux-amd64-v1.0.0Returns hash in base32, convert to SRI format:
Returns hash in base32, convert to SRI format:
nix hash to-sri --type sha256 <base32-hash>
Or use SRI directly:
```bash
nix-prefetch-url --type sha256 https://example.com/tool-linux-amd64-v1.0.0nix hash to-sri --type sha256 <base32-hash>
或者直接使用SRI格式:
```bash
nix-prefetch-url --type sha256 https://example.com/tool-linux-amd64-v1.0.0Dev Shell Patterns
Dev Shell 模式
Basic Shell
基础Shell
nix
devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [
nodejs
python3
];
shellHook = ''
echo "Dev environment ready"
'';
};nix
devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [
nodejs
python3
];
shellHook = ''
echo "Dev environment ready"
'';
};With Environment Variables
带环境变量的Shell
nix
devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [ postgresql ];
# Set at shell entry
DATABASE_URL = "postgres://localhost/dev";
# Or in shellHook for dynamic values
shellHook = ''
export PROJECT_ROOT="$(pwd)"
'';
};nix
devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [ postgresql ];
# Set at shell entry
DATABASE_URL = "postgres://localhost/dev";
# Or in shellHook for dynamic values
shellHook = ''
export PROJECT_ROOT="$(pwd)"
'';
};Native Dependencies (C Libraries)
原生依赖(C库)
nix
devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [
openssl
postgresql
];
# Expose headers and libraries
shellHook = ''
export C_INCLUDE_PATH="${pkgs.openssl.dev}/include:$C_INCLUDE_PATH"
export LIBRARY_PATH="${pkgs.openssl.out}/lib:$LIBRARY_PATH"
export PKG_CONFIG_PATH="${pkgs.openssl.dev}/lib/pkgconfig:$PKG_CONFIG_PATH"
'';
};nix
devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [
openssl
postgresql
];
# Expose headers and libraries
shellHook = ''
export C_INCLUDE_PATH="${pkgs.openssl.dev}/include:$C_INCLUDE_PATH"
export LIBRARY_PATH="${pkgs.openssl.out}/lib:$LIBRARY_PATH"
export PKG_CONFIG_PATH="${pkgs.openssl.dev}/lib/pkgconfig:$PKG_CONFIG_PATH"
'';
};Direnv Integration
Direnv 集成
.envrcbash
use flakeFor unfree packages without nixpkgs-unfree:
bash
export NIXPKGS_ALLOW_UNFREE=1
use flake --impure适用于Flake项目的:
.envrcbash
use flake对于未使用nixpkgs-unfree的非自由软件:
bash
export NIXPKGS_ALLOW_UNFREE=1
use flake --impureCommon Commands
常用命令
bash
undefinedbash
undefinedUpdate all inputs
Update all inputs
nix flake update
nix flake update
Update specific input
Update specific input
nix flake update some-input
nix flake update some-input
Check flake validity
Check flake validity
nix flake check
nix flake check
Show flake metadata
Show flake metadata
nix flake metadata
nix flake metadata
Enter dev shell
Enter dev shell
nix develop
nix develop
Run command in dev shell
Run command in dev shell
nix develop -c <command>
nix develop -c <command>
Build package
Build package
nix build .#packageName
nix build .#packageName
Run package
Run package
nix run .#packageName
undefinednix run .#packageName
undefinedTroubleshooting
故障排除
"unexpected argument" Error
"unexpected argument" 错误
All inputs must be listed in outputs function:
nix
undefined所有输入必须在outputs函数中列出:
nix
undefinedWrong
Wrong
outputs = { self, nixpkgs }: ...
outputs = { self, nixpkgs }: ...
Right (if you have more inputs)
Right (if you have more inputs)
outputs = { self, nixpkgs, other-input, ... }: ...
undefinedoutputs = { self, nixpkgs, other-input, ... }: ...
undefinedUnfree Package Errors with nix develop
使用nix develop时的非自由软件错误
config.allowUnfreenix develop- nixpkgs-unfree input (recommended)
- User's
~/.config/nixpkgs/config.nix NIXPKGS_ALLOW_UNFREE=1 nix develop --impure
flake.nix中的不会传递到中。请使用:
config.allowUnfreenix develop- nixpkgs-unfree输入(推荐方案)
- 用户的配置
~/.config/nixpkgs/config.nix NIXPKGS_ALLOW_UNFREE=1 nix develop --impure
Duplicate Nixpkgs Downloads
重复下载Nixpkgs
Use to chain inputs to a single nixpkgs source.
follows使用将输入链接到单个nixpkgs源。
followsOverlay Not Applied
Overlay未生效
Ensure overlay is in the list when importing nixpkgs:
overlaysnix
pkgs = import nixpkgs {
inherit system;
overlays = [ my-overlay.overlays.default ];
};确保在导入nixpkgs时将overlay添加到列表中:
overlaysnix
pkgs = import nixpkgs {
inherit system;
overlays = [ my-overlay.overlays.default ];
};Hash Mismatch
哈希不匹配
Re-fetch with and update the hash. Hashes change when upstream updates binaries at the same URL.
nix-prefetch-url使用重新获取并更新哈希值。当上游在同一URL更新二进制文件时,哈希值会发生变化。
nix-prefetch-url