nix-best-practices by 0xbigboss/claude-code
npx skills add https://github.com/0xbigboss/claude-code --skill nix-best-practices标准的 flake.nix 结构:
{
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; [
# 此处添加包
];
};
});
}
添加 overlay 输入时,使用 follows 来共享父级 nixpkgs,避免下载多个版本:
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
# Overlay 跟随父级 nixpkgs
some-overlay.url = "github:owner/some-overlay";
some-overlay.inputs.nixpkgs.follows = "nixpkgs";
# 通过中间输入链式跟随
another-overlay.url = "github:owner/another-overlay";
another-overlay.inputs.nixpkgs.follows = "some-overlay";
};
所有输入必须在 outputs 函数中列出,即使没有直接使用:
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
outputs = { self, nixpkgs, some-overlay, another-overlay, ... }:
Overlays 用于修改或向 nixpkgs 添加包:
let
pkgs = import nixpkgs {
inherit system;
overlays = [
overlay1.overlays.default
overlay2.overlays.default
# 内联 overlay
(final: prev: {
myPackage = prev.myPackage.override { ... };
})
];
};
in
使用 numtide/nixpkgs-unfree 处理需要 EULA 许可的软件包,无需用户配置:
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
nixpkgs-unfree.url = "github:numtide/nixpkgs-unfree/nixos-unstable";
nixpkgs-unfree.inputs.nixpkgs.follows = "nixpkgs";
# 非自由 overlay 跟随 nixpkgs-unfree
proprietary-tool.url = "github:owner/proprietary-tool-overlay";
proprietary-tool.inputs.nixpkgs.follows = "nixpkgs-unfree";
};
链式关系:proprietary-tool → nixpkgs-unfree → nixpkgs
用户添加到 ~/.config/nixpkgs/config.nix:
{ allowUnfree = true; }
let
pkgs = import nixpkgs {
inherit system;
config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [
"specific-package"
];
};
in
注意:flake.nix 中的 config.allowUnfree 对 nix develop 无效 - 使用 nixpkgs-unfree 或用户配置。
当 nixpkgs 构建的社区版本缺少功能时(常见于开源核心工具),创建一个获取官方二进制文件的 overlay。
{
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";
# 平台特定的二进制文件
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 = "工具描述";
homepage = "https://example.com";
license = licenses.unfree; # 或适当的许可证
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-prefetch-url https://example.com/tool-linux-amd64-v1.0.0
# 返回 base32 格式的哈希值,转换为 SRI 格式:
nix hash to-sri --type sha256 <base32-hash>
或直接使用 SRI:
nix-prefetch-url --type sha256 https://example.com/tool-linux-amd64-v1.0.0
devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [
nodejs
python3
];
shellHook = ''
echo "开发环境准备就绪"
'';
};
devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [ postgresql ];
# 在 shell 入口设置
DATABASE_URL = "postgres://localhost/dev";
# 或在 shellHook 中设置动态值
shellHook = ''
export PROJECT_ROOT="$(pwd)"
'';
};
devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [
openssl
postgresql
];
# 暴露头文件和库
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"
'';
};
flake 项目的 .envrc:
use flake
对于没有使用 nixpkgs-unfree 的非自由软件包:
export NIXPKGS_ALLOW_UNFREE=1
use flake --impure
# 更新所有输入
nix flake update
# 更新特定输入
nix flake update some-input
# 检查 flake 有效性
nix flake check
# 显示 flake 元数据
nix flake metadata
# 进入开发环境
nix develop
# 在开发环境中运行命令
nix develop -c <command>
# 构建软件包
nix build .#packageName
# 运行软件包
nix run .#packageName
所有输入必须在 outputs 函数中列出:
# 错误
outputs = { self, nixpkgs }: ...
# 正确(如果有更多输入)
outputs = { self, nixpkgs, other-input, ... }: ...
flake.nix 中的 config.allowUnfree 不会传播到 nix develop。使用:
~/.config/nixpkgs/config.nixNIXPKGS_ALLOW_UNFREE=1 nix develop --impure使用 follows 将输入链式连接到单个 nixpkgs 源。
确保在导入 nixpkgs 时 overlay 在 overlays 列表中:
pkgs = import nixpkgs {
inherit system;
overlays = [ my-overlay.overlays.default ];
};
使用 nix-prefetch-url 重新获取并更新哈希值。当上游在同一 URL 更新二进制文件时,哈希值会改变。
每周安装次数
152
仓库
GitHub 星标数
37
首次出现
2026年1月21日
安全审计
安装于
opencode125
codex122
gemini-cli118
github-copilot112
claude-code106
amp98
Standard flake.nix structure:
{
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
];
};
});
}
When adding overlay inputs, use follows to share the parent nixpkgs and avoid downloading multiple versions:
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:
outputs = { self, nixpkgs, some-overlay, another-overlay, ... }:
Overlays modify or add packages to nixpkgs:
let
pkgs = import nixpkgs {
inherit system;
overlays = [
overlay1.overlays.default
overlay2.overlays.default
# Inline overlay
(final: prev: {
myPackage = prev.myPackage.override { ... };
})
];
};
in
Use numtide/nixpkgs-unfree for EULA-licensed packages without requiring user config:
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-tool → nixpkgs-unfree → nixpkgs
Users add to ~/.config/nixpkgs/config.nix:
{ allowUnfree = true; }
let
pkgs = import nixpkgs {
inherit system;
config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [
"specific-package"
];
};
in
Note: config.allowUnfree in flake.nix doesn't work with nix develop - use nixpkgs-unfree or user config.
When nixpkgs builds a community version lacking features (common with open-core tools), create an overlay that fetches official binaries.
{
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-prefetch-url https://example.com/tool-linux-amd64-v1.0.0
# Returns hash in base32, convert to SRI format:
nix hash to-sri --type sha256 <base32-hash>
Or use SRI directly:
nix-prefetch-url --type sha256 https://example.com/tool-linux-amd64-v1.0.0
devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [
nodejs
python3
];
shellHook = ''
echo "Dev environment ready"
'';
};
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)"
'';
};
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"
'';
};
.envrc for flake projects:
use flake
For unfree packages without nixpkgs-unfree:
export NIXPKGS_ALLOW_UNFREE=1
use flake --impure
# Update all inputs
nix flake update
# Update specific input
nix flake update some-input
# Check flake validity
nix flake check
# Show flake metadata
nix flake metadata
# Enter dev shell
nix develop
# Run command in dev shell
nix develop -c <command>
# Build package
nix build .#packageName
# Run package
nix run .#packageName
All inputs must be listed in outputs function:
# Wrong
outputs = { self, nixpkgs }: ...
# Right (if you have more inputs)
outputs = { self, nixpkgs, other-input, ... }: ...
config.allowUnfree in flake.nix doesn't propagate to nix develop. Use:
~/.config/nixpkgs/config.nixNIXPKGS_ALLOW_UNFREE=1 nix develop --impureUse follows to chain inputs to a single nixpkgs source.
Ensure overlay is in the overlays list when importing nixpkgs:
pkgs = import nixpkgs {
inherit system;
overlays = [ my-overlay.overlays.default ];
};
Re-fetch with nix-prefetch-url and update the hash. Hashes change when upstream updates binaries at the same URL.
Weekly Installs
152
Repository
GitHub Stars
37
First Seen
Jan 21, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykWarn
Installed on
opencode125
codex122
gemini-cli118
github-copilot112
claude-code106
amp98
Azure Data Explorer (Kusto) 查询技能:KQL数据分析、日志遥测与时间序列处理
119,800 周安装