internals - Tokyo-NixOS/Tokyo-NixOS-Meetup-Wiki GitHub Wiki

NixOSの仕組み

NixOSは他のリナックスディストリビューションと比べ、新しい概念をいくつか持っています。 その中心にあるのは「関数型パッケージマネジメント」です。

それに関連するコンポネントはつぎの様になります。

  • Nix: パッケージマネージャー
  • チャンネル: Nixのパッケージソース
  • Nixストア: パッケージがインストールされるストア
  • プロフィール
  • モジュールシステム
  • nixpkgs: パッケージレポジトリ
  • Hydra: ビルドファーム
  • Nix言語

Nix

関数型パッケージマネージャー。NixOSの基盤となります。

次の特徴を持っています。

  • ソースインストールとバイナリインストールを対応
  • 同時に同じパッケージの複数バージョンをインストールできます
  • 完結な依存関係保証
  • 一般ユーザパッケージインストール
  • ロールバック
  • アトミックアップグレード
  • LinuxとMac OS対応

NixはDerivation(導出)を評価し、パッケージをインストールします。 パッケージレポジトリ(nixpkgs)の導出はパッケージを作るレシピで、その評価結果はパッケージのインストールとなります。

Nixは関数型であるのは導出が関数でありからのです。 そのレシピ(導出)に同じ材料(依存関係等)を利用すれば、同じパッケージができます。

もう一つの関数型要素はグローバルステートを変更しない。 パッケージインストールでグローバルステートに当たる概念は共有ファイルとなります。 例えば、一般パッケージマネジャーに同じファイルを持つパッケージを同時にインストールする場合に衝突が起きます。

NixはパッケージをNixストア内に隔離された専用フォルダにインストールされますので、それ以外のファイルに影響は起きない。

導出 (Derivation)

導出はNix言語で書かれたパッケージをインストールる関数であります。 Nix言語は関数言語で参照透過性を守っているため、その関数は同じ引数を利用するとで同じ結果を評価します。 導出の引数は主にインストールするパッケージの依存関係です。

特定な導出に特定な引数が渡されると必ず同じパッケージができるのはNixでとても大事な概念です。

ソースインストールとバイナリインストールを対応

Nixは基本的にソースインストールをします。 導出を評価すれば、パッケージがビルドされ、Nixストアにインストールされます。

バイナリインストールは導出が参照透過性を守ってるのを利用しています。 参照透過性があれば、同じ導出に同じ引数を渡すと同じパッケージはできます。 それを利用して、導出を評価する際にNixは導出とその引数のハッシュを計算します。このハッシュでインストールするパッケージを特定できます。 ソースビルドする前に登録されたバイナリキャッシュにそのハッシュを問い合わせす、該当するバイナリパッケージが見つける場合にソースコンパイルせずバイナリパッケージをダウンロードし、インストールします。

パッケージビルドに参照透過性を守るのは簡単なものでなく、Nixはいろな仕組みで非決定的な部分をなくします。

同時に同じパッケージの複数バージョンをインストールできます

すべてのパッケージはNixストア(/nix/store/以下)へインストールされます。 Nixストア内でパッケージはフォルダーで隔離されています、そのフォルダーの名前は導出と導出に利用された引数のハッシュとなります。 そのため、別バージョンを別な導出にすれば、別なストアフォルダーになります。

それ以上、同じパッケージが変わらなくても、依存関係(導出の引数)が変わると別Nixストアフォルダーに保存されます。

完結な依存関係保証

Nixはパッケージをビルドする際に純粋なシェルを使います(環境が空なシェル)。 そのシェルには導出で設定されたもの以外にアクセスはできない。 そのため、導出に宣言されてない依存関係がシステムに存在しても、ビルドが失敗します。

この機能はビルドの再現性を保証します。

一般ユーザパッケージインストール

インストールされるパッケージはNixストアで隔離されて、システムに影響をする事が不可能です。 そのため、Nixでパッケージをインストールするにはリスクがなく、特別な権限が必要ない。

ロールバック

Nixストアでインストールされたパッケージはプロフィールにリンクされます。 ユーザがパッケージ操作をする際に新しいプロフィール世代が作成されます。 ロールバックするにはプロフィールを前の世代に切り替えるだけです。 ブート画面でも簡単に世代を切り替えれます、

アトミックアップグレード

新しいパッケージバージョンはNixストアで新しいフォルダで保存されますので、前のパッケージのファイルを変更されない。 プロフィールがアップデートされるのはパッケージがすべてインストールされた後となります。 そのため、インストールの途中に電源が切れても、プロフィールと利用パッケージが変更されないです。

LinuxとMac OS対応

ターゲット環境は導出の引数の一つであるため、環境毎にパッケージハッシュがことなります。 その上、環境別にビルダーが準備できるので、いろいろな環境を対応できます。 現時点ではLinux系とMac OSのみとなります。(Window対応を目指すプロジェクトもあります)

Nixストア

Nixでは各パッケージがストア内に専用フォルダインストールされます。 Nixストアのパスは/nix/store/となります。

各パッケージは専用フォルダで完全隔離されています。 そのフォルダの命名規則はハッシュ-パッケージ名-パッケージバージョンとなります。

$ ls -d /nix/store/*/ | grep wget
/nix/store/djji4n5c8lr6knfnpi4rqdxywwzpz8zv-wget-1.16.3/
/nix/store/q6q2rq529r16md0nlj39bgysgxydf4m2-wget-1.17.1/
/nix/store/z3ajmsxpwac1f382r43ckl0haz45gnw5-wget-1.17.1/

パッケージフォルダにはそのパッケージのすべてのファイルが含まれています。

tree /nix/store/nmg89z2dxrx87wdqfhfbgbm3jzvczwq0-tree-1.7.0/
/nix/store/nmg89z2dxrx87wdqfhfbgbm3jzvczwq0-tree-1.7.0/
├── bin
│   └── tree
└── share
    └── man
        └── man1
            └── tree.1.gz

Nixストアは読み取り専用となります。

プロフィール

プロフィールは環境を指します。 NixOSでは主にプロフィールが2つあります。

  • システムプロフィール
  • ユーザプロフィール

NixOS以外の環境はユーザプロフィールのみとなります。

プロフィールはNixストアのパッケージをユーザやシステムの環境にリンクする仕組みです。

プロフィールは世代で管理されているため、ロールバックは簡単にできます。

システムプロフィールは/nix/var/nix/profiles/以下となます。 ユーザプロフィールは/nix/var/nix/profiles/per-user/に入って、ユーザの~/.nix-profileからリンクされています。

各プロフィールはストア内で保存されます。

nixpkgs

Nixの導出レポジトリ、githubにあります。 簡単に言い舞うとすべてのパッケージとNixOSモジュールのレシピ集です。 チャンネルは特定なテストを通ったnixpkgsのバージョンを提供します。

nixpkgsにパッケージを追加するのは導出ファイルを追加するほど簡単です。

簡単に独自のnixpkgsフォークを利用できます。

$ nixos-rebuild -I nixpkgs=/path/to/nixpkgs switch

チャンネル

システムに利用するnixpkgsとそのアップデートの提供方法。

独自チャンネルも利用できます。

Hydra

Nix言語を評価するビルドファーム、主ににnixpkgsの継続的インテグレーションとテストに利用されています。 導出を評価する結果はバイナリパッケージとなりますので、Hydraは同時に継続的インテグレーション、テストとバイナリビルドファームを果たす強力なシステムです。

Hydraのジョブが成功する場合にそのジョブに該当するチャンネルがそのジョブに利用されたnixpkgsに更新され、生成されたバイナリパッケージはバイナリキャッシュサーバにコピーされます。

独自サーバに入れることはできます。

モジュールシステム(NixOSのみ)

モジュールシステムはNixOSの宣言設定システム。 設定ファイルでインストールするパッケージや利用するサービスを設定ができます。

モジュールはnixpkgs内でNixファイルとなりますので、簡単にカスタマイズできます。

例えば、次の設定でポート80を公開し、カーネルの4.4を利用できます。

  boot.kernelPackages = pkgs.linuxPackages_4_4;
  networking.firewall.allowedTCPPorts = 80;

システムの様々なカスタマイズを自動化できる強力なシステムであります。

Nix言語

パッケージマネジメントに特化した関数型と延長評価のプログラミング言語。 チューリング完全な言語のため、パッケージマネジメント以外にも利用できます。

nixpkgsには導出以外にテストインストールメディアを生成にも使われます。

⚠️ **GitHub.com Fallback** ⚠️