nix-best-practices について
Nix Best Practices は、Nix flake、オーバーレイ、開発シェル、非フリーソフトウェアの設定を扱うリファレンススキルです。Nix プロジェクトの開発者向けに、コマンド例とトラブルシューティングを掲載しています。
主な機能
- 01flake の構成と入力の宣言
- 02follows による nixpkgs 入力の共有
- 03パッケージオーバーレイの適用
- 04非フリーパッケージの設定
- 05開発シェルと direnv の設定
活用シーン
- 01プロジェクト用 Nix flake の構築
- 02nixpkgs 入力の重複回避
- 03開発シェルでのネイティブ依存関係の提供
- 04flake やパッケージの一般的なエラーの調査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ alleneubank/ claude-code --skill nix-best-practicesインストール後、Claude Code で/nix-best-practicesを入力して読み込まれたか確認します。
詳細
Nix のベストプラクティス
Flake の構成
標準的な flake.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 パターン(Nixpkgs の重複を回避)
オーバーレイの入力を追加するときは、follows を使って親の nixpkgs を共有し、複数のバージョンのダウンロードを避けます:
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 関数に記載する必要があります:
outputs = { self, nixpkgs, some-overlay, another-overlay, ... }:
オーバーレイの適用
オーバーレイは nixpkgs のパッケージを変更または追加します:
let
pkgs = import nixpkgs {
inherit system;
overlays = [
overlay1.overlays.default
overlay2.overlays.default
# Inline overlay
(final: prev: {
myPackage = prev.myPackage.override { ... };
})
];
};
in
非フリーパッケージの扱い
オプション 1:nixpkgs-unfree(チームにおすすめ)
ユーザー側の設定を必要とせずに EULA でライセンスされたパッケージを使用するには、numtide/nixpkgs-unfree を使います:
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-tool → nixpkgs-unfree → nixpkgs
オプション 2:ユーザー設定
ユーザーは ~/.config/nixpkgs/config.nix に追加します:
{ allowUnfree = true; }
オプション 3:特定のパッケージ(Flake)
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 でビルドしたコミュニティ版に機能が不足している場合(オープンコアのツールでよくあります)、公式バイナリを取得するオーバーレイを作成します。
パターン(0xBigBoss/atlas-overlay、0xBigBoss/bun-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";
# 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;
};
};
}
SHA256 ハッシュの取得
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>
または、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 "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)"
'';
};
ネイティブ依存関係(C ライブラリ)
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 との統合
Flake プロジェクトの .envrc:
use flake
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
トラブルシューティング
「unexpected argument」エラー
すべての入力を outputs 関数に記載する必要があります:
# Wrong
outputs = { self, nixpkgs }: ...
# Right (if you have more inputs)
outputs = { self, nixpkgs, other-input, ... }: ...
nix develop での非フリーパッケージのエラー
flake.nix の config.allowUnfree は nix develop に引き継がれません。次のいずれかを使ってください:
- nixpkgs-unfree の入力(おすすめ)
- ユーザーの
~/.config/nixpkgs/config.nix NIXPKGS_ALLOW_UNFREE=1 nix develop --impure
Nixpkgs が重複してダウンロードされる
follows を使って、入力を単一の nixpkgs ソースにつなぎます。
オーバーレイが適用されない
nixpkgs をインポートするときに、オーバーレイが overlays リストに含まれていることを確認してください:
pkgs = import nixpkgs {
inherit system;
overlays = [ my-overlay.overlays.default ];
};
ハッシュの不一致
nix-prefetch-url で再取得し、ハッシュを更新します。上流で同じ URL のバイナリが更新されると、ハッシュも変わります。