NixOS と Nix Flakes の紹介
この記事は「慶應義塾大学 SFC 村井研 (RG) Advent Calendar 2022」の 15 日目の記事です.
概要
この記事では,Linux ディストリビューションである NixOS と,その関連ツールである Nix Flakes について紹介します.
NixOS とは,純粋関数型言語である Nix 言語 で設定を記述したり, Nix パッケージマネージャ を使ってパッケージ管理を行える Linux ディストリビューションです.
Nix Flakes とは, Nix パッケージマネージャで今後主流となっていく,パッケージ・プロジェクト管理機能です.
この記事では,各ソフトウェアの詳細な使い方は説明しません.
雰囲気を紹介して,興味を持っていただくことを目的としています.
実際に使い始めてみる方は,公式マニュアルや有志の Web サイトを参照してみてください.
以下, NixOS と Nix Flakes それぞれについて紹介します.
NixOS
NixOS とは, Linux ディストリビューションです.
システムの設定を純粋関数型言語 Nix で記述することにより,システム環境の再現性を高められることが特徴です.
この宣言的なシステム設定はバージョン管理され,過去の設定に戻りたい時も簡単にロールバックすることができます.
また, NixOS には Nix パッケージマネージャが標準で付属しています. Nix パッケージマネージャも,パッケージのビルド方法を Nix 言語で記述でき,パッケージの再現性と信頼性が高くなっています.
NixOS のインストール
GUI でインストールする方法と,手動でインストールする方法の二つがあります.
ここでは詳しく紹介しませんが, NixOS に興味を持ってくださった方は上記マニュアルを読んでインストールしてみてください.
NixOS のシステム設定
NixOS では, /etc/nixos/configuration.nix
にシステム設定を記述します.
以下がサンプルの configuration.nix
です.
Nix 言語について説明していませんが,雰囲気で読んでください.
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running ‘nixos-help’).
{ config, pkgs, ... }:
{
imports =
[ # インストール時に生成されたハードウェア設定
./hardware-configuration.nix
];
# ブートローダの設定
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
boot.loader.efi.efiSysMountPoint = "/boot/efi";
# 使用する NixOS のバージョン
system.stateVersion = "22.05";
# タイムゾーン
time.timeZone = "Asia/Tokyo";
# ロケール等の設定
i18n.defaultLocale = "en_US.utf8";
i18n.extraLocaleSettings = {
LC_ADDRESS = "ja_JP.utf8";
LC_IDENTIFICATION = "ja_JP.utf8";
LC_MEASUREMENT = "ja_JP.utf8";
LC_MONETARY = "ja_JP.utf8";
LC_NAME = "ja_JP.utf8";
LC_NUMERIC = "ja_JP.utf8";
LC_PAPER = "ja_JP.utf8";
LC_TELEPHONE = "ja_JP.utf8";
LC_TIME = "ja_JP.utf8";
};
# キーマップの設定
console.keyMap = "dvorak";
# Nix パッケージマネージャで非フリーソフトウェアのインストールを有効化する
# e.g.) Google Chrome など
nixpkgs.config.allowUnfree = true;
# システム全体向けにインストールするパッケージ
environment.systemPackages = with pkgs; [
docker
docker-compose
gnupg
python3
zsh
];
# ユーザに zsh の使用を許可する
programs.zsh.enable = true;
# SSH サーバを有効化し,設定する
services.openssh.enable = true;
services.openssh.permitRootLogin = "no";
services.openssh.passwordAuthentication = false;
# Docker を有効化する
virtualisation.docker.enable = true;
# ユーザアカウントの追加
users.users.kino-ma = {
isNormalUser = true;
description = "Seiki Makino";
extraGroups = [ "networkmanager" "wheel" "docker" ];
# このユーザだけ利用可能なパッケージ
packages = with pkgs; [
htop
];
# ログインシェル
shell = pkgs.zsh;
# SSH 公開鍵の登録
openssh.authorizedKeys.keys = [
"ssh-ed25519 ..."
];
};
}
コメントを見ていただければ分かる通り,さまざまなシステム設定を宣言的に行うことができます.
- 使用するキーマップ
- インストールするパッケージ
- SSH サーバの有効化
- Docker の有効化
- ユーザアカウント
- 所属するグループ
- ログインシェル
- SSH 公開鍵
これ以外にも,非常にたくさんの設定を行うことができます.興味のある方や実際にセットアップを始めた方は,ぜひ マニュアル を参照してみてください [1].
configuration.nix
の設定は, nixos-rebuild switch
とコマンドを打つことでシステムに反映されます.
この configuration.nix
をコピーすることで,別のホストでも全く同じ環境を再現できます.
また,過去の設定にも簡単にロールバックすることができます.
この強みから,普段使いの OS としてはもちろん,サーバ用途としても活躍しやすいのではないかと思います.
簡単ですが、以上が Nix OS の紹介となります。雰囲気や嬉しさが伝わると嬉しいです。
Nix Flakes
次に, Nix 言語 で設定を記述するプロジェクト管理ツール Nix Flakes [2] の紹介をします.
この章の内容は,一部 NixOS Wiki にも書いてあります.
Nix Flakes は, Nix パッケージマネージャの一つの機能です.
Nix パッケージマネージャは NixOS にデフォルトで付属しているほか, macOS や Windows にも インストールすることができます.
Nix Flakes は,ソフトウェアのビルド,依存ツールの管理,開発者間での環境の統一,スクリプトの実行など,さまざまな機能を持っています.
これは,以下のようなさまざまなツールの機能をひとまとめにしたものだと捉えることができます.
- Make
- Docker
- pip, NPM などの各種パッケージマネージャ
- nodenv などの言語バージョン管理ツール
Nix Flakes によって管理されているプロジェクトのことを, Flake と呼びます.
自分のプロジェクトを Flake として管理したり,他人の Flake をインストールしたりすることができます.
また, configuration.nix
の代わりに Flake を記述し,システムの設定を行うこともできます.
dotfiles の代替として使用している人もいるようです.
Nix Flakes の有効化
Nix Flakes はまだ実験段階で,デフォルトでは使用できません.
以下のコマンドを打つことにより,実行したユーザに対して有効化できます.
mkdir -p ~/.config/nix
echo "experimental-features = nix-command flakes" >> ~/.config/nix/nix.conf
または, NixOS 上では configuration.nix
に以下の設定を追加すると使用できます.
{ pkgs, ... }: {
nix.settings.experimental-features = [ "nix-command" "flakes" ];
}
Nix Flakes を使い始める
プロジェクトを Flake として管理し始めるためには, Git 管理されたリポジトリの中で以下のコマンドを実行します.
nix flake init
すると,以下のような内容の flake.nix
ファイルが生成されます.
{
description = "A very basic flake";
outputs = { self, nixpkgs }: {
packages.x86_64-linux.hello = nixpkgs.legacyPackages.x86_64-linux.hello;
packages.x86_64-linux.default = self.packages.x86_64-linux.hello;
};
}
この flake.nix
が, Flake のさまざまな設定を含む Nix ファイルです.
flake.nix
は以下の要素を持つことができます.
-
description
: この Flake の説明文 -
inputs
: この Flake の依存パッケージ等- Git リポジトリ
- ローカルディレクトリ
- ほかの Flake
- など
-
outputs
:inputs
の内容を受け取り,このプロジェクトに関連するさまざまな出力を返すような関数- 出力の例:
- プロジェクトのビルド方法 (
nix build
で実行される) - プロジェクトに関連するスクリプト (
nix run
で実行される) - プロジェクトの開発用シェルにインストールするパッケージ (
nix develop
でシェルに入ることができる) - NixOS のシステム設定
- など
- プロジェクトのビルド方法 (
- 出力の例:
-
nixConfig
: このプロジェクト固有の Nix 設定
この flake.nix
を使用する nix
コマンドを実行すると, flake.lock
ファイルが生成されます.
flake.lock
ファイルは NPM の package-lock.json
と似た役割を持ち, inputs
に含まれる各種依存先のバージョンを固定しています.
ただし,リポジトリの git revision や SHA256 ハッシュが含まれており, package-lock.json
よりも厳密な固定と考えることができます.
実用的な例
以下が,実際に自分があるプロジェクトで使用している flake.nix
の一部です.
{
description = "";
# この Flake への入力です
inputs = {
# 公式リポジトリからパッケージをインストールします
nixpkgs = { url = "github:NixOS/nixpkgs/nixpkgs-unstable"; };
# Flake の作成を便利にするユーティリティ flake-utils を利用します
flake-utils = { url = "github:numtide/flake-utils"; };
};
# この Flake の出力です
outputs = { self, nixpkgs, flake-utils }:
# 本来 outputs は各システム(アーキテクチャ+OS)への出力を明示的に指定しなければなりませんが, flake-utils の機能を使って全システムを一度に指定します
flake-utils.lib.eachDefaultSystem (system:
let
inherit (nixpkgs.lib) optional;
pkgs = import nixpkgs { inherit system; };
nodejs = pkgs.nodejs;
yarn = pkgs.yarn;
pipenv = pkgs.pipenv;
in
{
# このプロジェクトの開発用シェルを出力します
devShell = pkgs.mkShell {
buildInputs = [
# `nix develop` で開発用シェルに入ると, Node.js,Yarn,pipenv を利用できます
nodejs
yarn
pipenv
python-ldap
];
};
});
}
このプロジェクトでは Node.js, Yarn, Pipenv を使って開発していたので,それぞれが開発用シェルで利用できるように設定しました [3].
また,今回は Docker を併用していたため設定しませんでしたが,ビルド方法を設定して nix build
コマンドでビルドすることもできます.
このように,開発用シェル環境として使うだけでも便利なのではないかと思います.
以上が Nix Flakes の紹介です.
まとめ
この記事では, Liunx ディストリビューションである NIxOS と,プロジェクト管理ツール Nix Flakes について紹介しました.
卒論で忙しいタイミングと被ってしまい,非常に簡単な説明しかできず残念です.
日本語の情報はまだ大変少ないため,また時間のある時にさらに詳しい紹介を行えたらと思います.
この記事をきっかけに興味を持ってくださる方がいると嬉しいです.
もしいたら,ぜひリアクションをください!
ここまで読んでいただいてありがとうございました.
Discussion