メインコンテンツへスキップ
中級20分で読める

Nixとは?宣言型パッケージ管理で開発環境の「壊れた」をなくす方法【2026年最新】

Nixパッケージマネージャーの特徴と仕組みを初心者向けに解説。再現可能な開発環境の構築、従来のパッケージ管理との違い、nix-shellやFlakesの使い方を紹介します。

🎯 この記事で学べること

  • 1
    Nixパッケージマネージャーとは何か、その設計思想を理解できます
  • 2
    従来のパッケージマネージャー(apt・Homebrew)との違いがわかります
  • 3
    nix-shellを使った再現可能な開発環境の構築方法を学べます
  • 4
    Nix Flakesによるモダンなプロジェクト管理の考え方を理解できます
  • 5
    Nixの導入判断に必要な知識を身につけられます

読了時間: 約20

「自分のPCでは動くのに」が起きる本当の理由

チーム開発で最も聞く言葉の一つ。

「自分のPCでは動くのに、なぜか他の人の環境だと動かない」

Node.js 18で書いたコードが、Node.js 20の環境でビルドエラーを起こす。Pythonの特定バージョンに依存するライブラリが、他のメンバーのPCにはインストールされていない。半日かけて原因を探った結果、OpenSSLのバージョンが0.0.1だけ違っていた——。

この問題の根本原因はシンプルだ。パッケージマネージャーが「環境の再現性」を保証していないからだ。

apt install nodejsbrew install nodeは「最新版をインストールする」という命令だ。今日と来週では、インストールされるバージョンが変わる可能性がある。同じコマンドを実行しても、同じ結果が得られるとは限らない。

2003年、オランダのユトレヒト大学で一人の研究者がこの問題に取り組み始めた。

Eelco Dolstraの博士論文のテーマは「純粋関数型のソフトウェアデプロイメントモデル」。彼が生み出したのがNixだ。

Nixとは:パッケージ管理を「数学」にする

Nixは、純粋関数型の設計思想に基づくパッケージマネージャーだ。

「純粋関数型」と聞くと難しそうだが、考え方はシンプルだ。数学の関数を思い出してほしい。

f(x) = x + 1

この関数に3を入れれば、いつでも4が返ってくる。昨日も今日も来年も。実行する場所がどこであろうと。結果は入力だけで決まり、外部の状態に影響されない。

Nixはこれをパッケージ管理に適用した。

従来のパッケージマネージャーでは、apt install nodejsの結果は「今のシステムの状態」に依存する。すでにインストールされているライブラリ、設定ファイル、環境変数——すべてが結果に影響を与える。

Nixでは、パッケージのビルド結果は入力(ソースコード + 依存関係 + ビルド手順)だけで決まる。システムの状態には一切依存しない。同じ入力からは、いつでも、どこでも、まったく同じバイナリが生成される。

これが**再現可能なビルド(Reproducible Builds)**だ。

Nixの3つの革新的な特徴

1. ハッシュベースのストア

Nixのもっとも特徴的な仕組みが /nix/store だ。

従来のパッケージマネージャーは、パッケージを/usr/bin//usr/lib/といった共有ディレクトリにインストールする。異なるバージョンのパッケージが同じファイルパスを奪い合い、衝突が発生する。

Nixは違う。すべてのパッケージを、ハッシュ値を含む一意のパスに格納する。

/nix/store/b6gvzjyb2pg0kjfwrjmg1vfhh54ad73z-nodejs-18.17.0/
/nix/store/x5w3yxmkn3q2vr9b1p0ywfaa7lf4qph8-nodejs-20.10.0/
/nix/store/4kj2r8csdvp0ahkhfz8qms3jlpdaxkml-python3-3.11.6/

ハッシュ値はソースコード、依存関係、ビルド手順のすべてから計算される。つまり、入力が少しでも変われば、まったく別のパスに格納される。

この仕組みにより、異なるバージョンのパッケージが完全に共存できる。Node.js 18と20を同時にインストールしても、互いに干渉しない。プロジェクトAではNode.js 18を、プロジェクトBではNode.js 20を使う——ということが自然にできる。

/nix/storeのサイズは大きくなりがちですが、nix-collect-garbageコマンドで使われていないパッケージを安全に削除できます。現在のプロファイルから参照されていないパッケージだけが削除対象になるため、必要なものが消えることはありません。

2. 宣言型パッケージ管理

従来のパッケージマネージャーは**命令型(Imperative)**だ。

# 命令型: 「これをインストールしろ」と一つずつ指示する
apt install nodejs
apt install python3
apt install git
npm install -g typescript

この方法では、「いつ」「どの順番で」コマンドを実行したかで結果が変わる。環境を再現するには、すべてのコマンド履歴を正確に記録し、同じ順番で再実行する必要がある。

Nixは**宣言型(Declarative)**だ。

# 宣言型: 「最終的にこうなっていてほしい」を記述する
{ pkgs, ... }:
{
  environment.systemPackages = with pkgs; [
    nodejs_18
    python311
    git
    nodePackages.typescript
  ];
}

命令型が「手順書」だとすれば、宣言型は「完成図」だ。

手順書は「ステップ3の前にステップ2が失敗したらどうする?」という問題を常に抱えている。完成図にはその問題がない。Nixが完成図を受け取り、現在の状態から完成図の状態へ到達する手順を自動的に計算する。

3. アトミックなアップグレードとロールバック

apt upgradeの途中でマシンが落ちたらどうなるか。一部のパッケージだけが更新された、半端な状態のシステムが残る。これを「部分的な更新」と呼び、依存関係の不整合を引き起こす典型的な原因だ。

Nixのアップグレードは**アトミック(不可分)**だ。すべてが成功するか、すべてが元の状態に戻るか。中途半端な状態は存在しない。

さらに、Nixはすべての状態を**世代(Generation)**として管理する。

# 現在の世代を確認
nix profile history

# 一つ前の世代にロールバック
nix profile rollback

# 特定の世代に戻る
nix profile rollback --to 42

「新しいパッケージを入れたらシステムが不安定になった」場合、一瞬で以前の安定した状態に戻せる。Gitのバージョン管理をシステム全体に適用したようなものだ。

NixOSではOS起動時のブートメニューから世代を選択できます。アップグレードで起動しなくなっても、前の世代を選ぶだけで元通り。Windowsの「システムの復元」に似ていますが、はるかに信頼性が高い仕組みです。

従来のパッケージマネージャーとの比較

比較項目apt (Debian/Ubuntu)Homebrew (macOS)Nix
設計思想命令型命令型宣言型・純粋関数型
バージョン共存困難(alternatives等で対応)限定的(keg-only)完全対応(ハッシュベース)
再現性低(時期やミラーに依存)低(ローリングリリース)高(ハッシュで一意に決定)
ロールバック困難困難ネイティブ対応(世代管理)
クロスプラットフォームLinux (Debian系) のみmacOSが主 (Linuxbrewあり)Linux + macOS
パッケージ数約60,000約7,000約100,000以上(Nixpkgs)
学習コスト低い低い高い
環境分離なし(venv等は別途)なしnix-shell / devShells

NixpkgsはGitHubで最も活発なリポジトリの一つで、100,000以上のパッケージが登録されています。コミュニティの規模と活発さでは、aptやHomebrewに引けを取りません。

Nixのインストールと基本操作

Nixのインストールは、Linux・macOSともにワンコマンドだ。

# 公式インストーラー(マルチユーザーインストール推奨)
sh <(curl -L https://nixos.org/nix/install) --daemon

Nixは /nix ディレクトリを作成します。macOSではAPFSボリュームとして自動作成されます。アンインストールも公式手順が用意されていますが、/nix/store のサイズが大きくなることがあるため、ディスク容量には注意してください。

インストール後、基本的な操作を見てみよう。

# パッケージの検索
nix search nixpkgs nodejs

# パッケージの一時的な利用(インストールせずに試す)
nix run nixpkgs#nodejs -- --version

# パッケージのインストール
nix profile install nixpkgs#nodejs_18

# インストール済みパッケージの一覧
nix profile list

# パッケージの削除
nix profile remove nodejs_18

# 不要なパッケージの掃除
nix-collect-garbage -d

注目すべきはnix runコマンドだ。パッケージをシステムにインストールすることなく、一時的に実行できる。「ちょっと試してみたい」ときに非常に便利だ。

# Pythonの特定バージョンをインストールせずに試す
nix run nixpkgs#python311 -- --version

# cowsayを一度だけ使いたい
nix run nixpkgs#cowsay -- "Hello from Nix!"

実行が終われば痕跡は残らない。システムを汚さずにツールを試せるのは、Nixならではの体験だ。

nix-shellで再現可能な開発環境を作る

Nixの真価が発揮されるのが、プロジェクトごとの開発環境構築だ。

nix-shellを使えば、プロジェクトに必要なツールがすべて揃った一時的なシェル環境を作れる。

shell.nixファイルの作成

プロジェクトのルートにshell.nixを作成する。

# shell.nix
{ pkgs ? import <nixpkgs> {} }:

pkgs.mkShell {
  buildInputs = with pkgs; [
    nodejs_18
    python311
    git
    jq
    curl
  ];

  shellHook = ''
    echo "開発環境が準備できました"
    echo "Node.js: $(node --version)"
    echo "Python: $(python3 --version)"
  '';
}
# プロジェクトディレクトリで実行
nix-shell

これだけで、Node.js 18、Python 3.11、Git、jq、curlがすべて利用可能なシェル環境が立ち上がる。exitでシェルを抜ければ、環境は消える。

このshell.nixファイルをGitリポジトリにコミットしておけば、チームの誰もがnix-shellの一言でまったく同じ開発環境を手に入れられる。

direnvとの組み合わせ

毎回nix-shellと打つのが面倒なら、direnvと組み合わせると便利だ。プロジェクトディレクトリに入るだけで自動的にNix環境が有効になる。

# .envrcファイルを作成
echo "use nix" > .envrc
direnv allow

これでプロジェクトディレクトリにcdするたびに、自動的にNix環境がロードされる。ディレクトリを出れば元の環境に戻る。

nix-shell + direnvの組み合わせは、Nixユーザーの間では定番のワークフローです。プロジェクトごとに異なるNode.jsやPythonのバージョンを使い分ける場合に特に威力を発揮します。

Nix Flakes:モダンなNixの使い方

Nixの伝統的な使い方には一つ弱点があった。<nixpkgs>のバージョンが環境によって異なるため、完全な再現性が保証されなかったのだ。

この問題を解決するのがNix Flakesだ。

Flakesは、Nixプロジェクトの依存関係をflake.lockファイルで厳密に固定する仕組みだ。npmのpackage-lock.jsonやRustのCargo.lockと同じ発想だ。

flake.nixの例

# flake.nix
{
  description = "My project development environment";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
    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; [
            nodejs_18
            python311
            git
          ];
        };
      }
    );
}
# Flakeベースの開発環境に入る
nix develop

# flake.lockが自動生成される(Gitにコミットすること)
git add flake.nix flake.lock

flake.lockが依存関係の正確なバージョン(Gitのコミットハッシュ)を記録するため、いつ・どこで実行しても完全に同じ環境が再現される。

Nix Flakesは2026年現在、まだ「実験的機能」という位置づけですが、事実上のデファクトスタンダードになっています。新しいNixプロジェクトではFlakesの使用が強く推奨されています。

Flakesを有効にする

Flakesを使うには、Nixの設定に以下を追加する。

# ~/.config/nix/nix.conf に追加
echo "experimental-features = nix-command flakes" >> ~/.config/nix/nix.conf

NixOSとの関係

Nixの思想をOS全体に適用したのがNixOSだ。

通常のLinuxディストリビューションでは、パッケージの追加・削除、設定ファイルの変更、サービスの有効化はそれぞれ異なる方法で行う。NixOSでは、これらすべてを一つの設定ファイル/etc/nixos/configuration.nixで宣言的に管理する。

# /etc/nixos/configuration.nix(抜粋)
{ config, pkgs, ... }:
{
  # インストールするパッケージ
  environment.systemPackages = with pkgs; [
    vim
    git
    firefox
  ];

  # Nginxを有効化
  services.nginx.enable = true;

  # ファイアウォール設定
  networking.firewall.allowedTCPPorts = [ 80 443 ];

  # ユーザー設定
  users.users.alice = {
    isNormalUser = true;
    extraGroups = [ "wheel" "docker" ];
  };
}

sudo nixos-rebuild switchの一発で、この設定が反映される。パッケージのインストール、サービスの起動、ファイアウォールの設定、ユーザーの作成——すべてが一つのコマンドで完了する。

設定ファイルをGitで管理すれば、OS全体をバージョン管理できる。インフラのコード化(Infrastructure as Code)をOS単体で実現するのがNixOSだ。

NixOSは強力ですが、通常のLinuxディストリビューションとは大きく異なります。FHS(Filesystem Hierarchy Standard)に従わないため、一部のバイナリが動かないことがあります。まずはNixパッケージマネージャー単体から始めることをおすすめします。

Nixのエコシステム

Nixの周辺には活発なエコシステムが広がっている。

Home Manager

NixOSを使わなくても、ユーザーの設定ファイル(dotfiles)をNixで宣言的に管理できるツールだ。.bashrc.gitconfig.vimrcなどをNixの設定ファイルで一元管理できる。

# home.nix(抜粋)
{ config, pkgs, ... }:
{
  programs.git = {
    enable = true;
    userName = "Your Name";
    userEmail = "you@example.com";
    extraConfig = {
      init.defaultBranch = "main";
      pull.rebase = true;
    };
  };

  programs.vim = {
    enable = true;
    plugins = with pkgs.vimPlugins; [ vim-nix vim-fugitive ];
    settings = {
      number = true;
      tabstop = 2;
    };
  };
}

PCを買い替えても、この設定ファイルがあればすべてのツールと設定が即座に復元される。

devenv

nix-shellnix developをより使いやすくするラッパーツールだ。Nixの知識がなくても、簡潔な設定で開発環境を定義できる。

# devenv.nix
{ pkgs, ... }:
{
  languages.javascript = {
    enable = true;
    package = pkgs.nodejs_18;
  };

  languages.python = {
    enable = true;
    version = "3.11";
  };

  services.postgres.enable = true;

  pre-commit.hooks = {
    eslint.enable = true;
    black.enable = true;
  };
}

開発言語、サービス(PostgreSQL等)、pre-commitフックまで、一つのファイルで宣言的に管理できる。

よくある質問(FAQ)

Q1. Nixは難しいと聞きますが、本当ですか?

正直に言えば、学習曲線は急です。Nix言語の独特な構文、関数型プログラミングの概念、従来と異なるファイルシステム構造——慣れるまでに時間がかかります。ただし、nix-shellで開発環境を作る程度の使い方なら、基本的なテンプレートをコピーして少し修正するだけで十分実用的です。

Q2. aptやHomebrewと併用できますか?

はい、できます。Nixは/nix/storeに独自のディレクトリを使うため、aptやHomebrewと干渉しません。既存の環境を壊さずにNixを追加できるので、段階的な導入が可能です。

Q3. macOSでもNixは使えますか?

はい、macOSを正式にサポートしています。nix-darwinというプロジェクトを使えば、NixOSと同じような宣言的設定でmacOSのシステム設定を管理することもできます。Apple Silicon(M1/M2/M3/M4)にも対応しています。

Q4. Dockerとの違いは何ですか?

Dockerはアプリケーションの実行環境を丸ごとコンテナ化します。Nixは開発環境のパッケージ管理に特化しています。Dockerが「部屋ごと段ボール箱に入れる」なら、Nixは「必要な道具だけを正確にリストアップして揃える」イメージです。両者は競合ではなく補完関係にあり、NixでDockerイメージをビルドするという使い方も人気です。

Q5. チームに導入する際のハードルは?

最大のハードルは学習コストです。チーム全員がNix言語を学ぶ必要はありませんが、shell.nixflake.nixを読み書きできるメンバーが少なくとも1人は必要です。まずは一つのプロジェクトでnix-shellを導入し、チームの反応を見ることをおすすめします。

Q6. CI/CDでNixは使えますか?

はい。GitHub ActionsにはNix用の公式アクション(cachix/install-nix-action)があり、簡単に導入できます。NixのキャッシュサービスCachixを使えば、ビルド済みパッケージをキャッシュしてCI/CDの高速化も可能です。

まとめ:Nixを選ぶべき人、まだ早い人

Nixを検討すべきケース:

  • 「自分のPCでは動く」問題に繰り返し悩んでいるチーム
  • プロジェクトごとに異なるバージョンのツールを使い分けたい開発者
  • 開発環境のセットアップ手順書が長くなりすぎているプロジェクト
  • Infrastructure as Codeの考え方をローカル環境にも適用したい人

まだ早いケース:

  • Linux/macOSのコマンド操作にまだ慣れていない初学者
  • チームにNixの経験者が一人もいない状況
  • 既存のツールチェーンで特に問題が発生していない場合
  • 短期間のプロジェクトで学習コストが見合わない場合

Nixは万人向けのツールではない。学習コストは高く、エコシステムの理解にも時間がかかる。

しかし、一度Nixの世界に入ると、「パッケージのバージョン衝突」「環境の再現ができない」「依存関係が壊れた」といった問題から完全に解放される。その体験は、学習コストを十分に上回る。

まずは既存の環境を壊さずにnix-shellから試してみましょう。プロジェクトにshell.nixを一つ追加するだけで、Nixの再現性の恩恵を受けられます。気に入ったらFlakesへ、さらにHome ManagerやNixOSへと段階的にステップアップできます。