はじめに
初投稿です。
業界のひとではありませんのでイケてる情報をお探しの方はタブクローズ推奨です。
還暦過ぎのじーさんの記事ですので懐古ネタきしょっの方も同様です。
父が気まぐれで買ってきたBASICのサブセットが走るカシオの関数電卓にはじまり1、プログラミング三昧だった少年時代を過ごしたあと諸事情で全く関連のない分野に進み生業としています。本業での必要から最後にアプリケーション2をかいてから14年くらいたちますがその間は多忙でほとんど時間が割けず。最近本業が暇になりつつありまた遊んでみたくなったという次第です。
何度か流行りのNixOSでの環境構築を試みては失敗してきました。記憶力のよくない(さらに悪化傾向にある)せいで何度も同じことを調べ直すことが多いので記録を残しておきたいと考えました。
技術者の方や専門の学生の方の情報交換の場であるQiitaに素人が投稿するのはいかがなものか、とも思ったのですが、当たり前ですがたぶんだれも読まないわけで、それなら別に気にすることもないかと自分用に記事にしていくことにしました。
というわけでこの記事の正しさにはなんの保証もありませんが、先の事情のごとく成果を求められるわけでなく比較的時間もあるので、実際に作業しながらこつこつ進めていきます。理解できないことをコピペだけで進めていかない、という基本方針です。もし「NixOSわからん」と諦めていた私くらいの知識の方が読んでくださっていたら安心してください、私もわかりません😇。一緒にやりましょう。またもし詳しい方がご覧になられていて間違いに気づかれましたらご教授いただければ幸いです。
目標
コンソールのみの最小構成から始めて、ストレスなくコードがかけるNixOSデスクトップ環境を構築する。
対象ハード構成
ThinkPad X1 Carbon 6th Gen ... 7年選手となります
(Model 20KHCTO1WW)
- CPU: Intel i7-8650U
- GPU: Intel UHD Graphics 620
- Memory: 16GiB
- Disk: SSD NVMe 1T
軌道にのったらデスクトップ機でWindows 11とのデュアルブートの構成も行う予定です。
下準備
Bootable USB drive作成
USBメモリにVentoryをインストールする
空いたUSBメモリにVentoryをインストールします(Ventory化します)。Ventory化したドライブは通常のドライブのように読み書きできるのですが、ここにブータブルISOイメージをコピーするだけで起動ディスクとして使用できるようになります。複数のイメージを置いておけばマルチブートできますので各種ディストロのお試しが1本のメモリでできます。空いた領域は通常のドライブとして使えるので無駄になりません。
NixOS公式サイトからISOイメージをダウンロードしVentoryディスクにコピーする
現在、gnomeのライブ環境からGUIでデスクトップ環境を選んでインストールできるGraphical ISO imageと、コンソールから最小限構成のみインストールできるMinimal ISO imageが提供されています。ここでは後者で始めます。
記事作成時のバージョンは25.11でした。
Ventoryディスクで起動しNixOSをインストールする
公式ドキュメントに則って進めていきます。
対象ハードは元はWindows 10がプリインストールされたモデルでしたが、内蔵ディスクは全消ししてNixOS専用機とします。もともとUEFI起動ですがセキュアブートはBIOSからオフとしておきます。
ネットワークにつなぐ
Ventoryディスクから起動するとコンソール画面となりnixosという名のホストにユーザーnixosでログインした状態となります。インストールの継続にはネットワーク接続が必要ですが外付けEthernetアダプタを持ってないのでwifiを有効化します。NetworkManagerが使えます。
$ nmtui
内蔵ディスクにパーティションを切ってフォーマットする
続いてパーティショニングです。lsblkで内蔵SSDの名前を確認します。nvme0n1です。
フォーマットの種類を選びます。「NixOSでは細かいファイルがたくさん作成されやすくシンボリックリンクも大量に作成されるためext4ではinodeの枯渇が起きる場合がある」という記事を拝見したのでルートパーティションはbtrfsにします。NixOSではデフォルトで/bootをEFIシステムパーティションとして使いますので分けてfatにします。スワップも一応作成します。
次にサイズですが、「NixOSではシステムのロールバックを可能とする分、古いカーネルを残しておくことになり容量の消費が大きいので推奨1G」という記事を見かけました。zenなどの改造カーネルを試してみたくなるかもしれないので少し大きめの1.5Gにします。
fdiskしか使ったことがなかったのですが、公式マニュアルのサンプルにそってpartedを初めて使ってみました。
$ sudo -i
# parted /dev/nvme0n1 -- mklabel gpt
# parted /dev/nvme0n1 -- mkpart root btrfs 1.5G -16G
# parted /dev/nvme0n1 -- mkpart swap linux-swap -16G 100%
# parted /dev/nmve0n1 -- mkpart ESP fat32 1MB 1.5G
# parted /dev/bmve0n1 -- set 3 esp on
これでパーティションは以下のようになります。
# lsblk
(略)
nvme0n1 259.0 0 953.9G 0 disk
├nvme0n1p2 259.1 0 14.9G 0 part
├nvme0n1p1 259.2 0 937.6G 0 part
└nvme0n1p3 259.3 0 1.4G 0 part
続いてフォーマットします。
ラベルはたぶんつけなくても大丈夫ですが、/dev/disk/by-label/LABELとパスがかけるようになるのでシェルの補完が使えて後で少し楽ができます。
# mkfs.btrfs -L nixos /dev/nvme0n1p1
# mkswap -L swap /dev/nvme0n1p2
# mkfs.fat -F 32 -n boot /dev/nvme0n1p3
パーティションをマウントしデフォルトの設定ファイルを生成する
インストール先の/を/mntに、/bootを/mnt/bootにマウントします。
# mount /dev/disk/by-label/nixos /mnt
# mkdir -p /mnt/boot
# mount -o umask=077 /dev/disk/by-label/boot /mnt/boot
# swapon /dev/disk/by-label/swap
デフォルトのシステム設定ファイルを生成します。NixOSではこれに基づいて宣言的にシステムが構成されます3。
# nixos-generate-config --root /mnt
主な設定ファイルであるconfiguration.nixと自動判定されたハードウェアの設定ファイルであるhardware-configuration.nixとが/mnt/etc/nixos/以下に作成されます。後者は前者にインポートされるようになっています。後者だけ生成するコマンドオプションもあるようなのでハードウェア構成の変化に対応しやすくしていると思われます。
hardware-configuration.nixを確認してみます。コメントは外しました。
{ config, lib, pkgs, modulesPath, ... }:
{
imports =
[ (modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [ "xhci_pci" "nvme" "usb_storage" "sd_mod" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "/dev/disk/by-uuid/7533bf93-a03c-4f69-a82b-8f1e70912e43";
fsType = "btrfs";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/371B-9842";
fsType = "vfat";
options = [ "fmask=0077" "dmask=0077" ];
};
swapDevices =
[ { device = "/dev/disk/by-uuid/45a0c073-5ab7-423b-a94c-b62e1981910f"; }
];
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}
インポートされている(modulesPath + "/installer/scan/not-detected.nix")の内容を確認してみます。
$ find /mnt -name "not-detected.nix"|xargs cat
# Enables non-free firmware on devices not recognized by `nixos-generate-config`.
{ lib, ... }:
{
hardware.enableRedistributableFirmware = lib.mkDefault true;
}
となっていました。non-freeのファームウェアを有効とするかどうかの設定でした。
次のboot.initrd.availableKernelModulesは起動時にルートをマウントするまでに必要となりえる(従ってRAMディスク上にある必要のある)カーネルモジュールでオンデマンドに読み込まれます。読み込みを強制したいものはboot.initrd.kernelModulesに置くようです。ケースが想像できませんが、ググると「LVMを使ったシステムでデバイスマッパーモジュール(dm_mod)が自動でロードされない」という記事があったのでLUKSなど使いたい時に必要なのかもしれないです。
boot.kernelModulesはブートプロセスの第2ステージで必要となるモジュールです。いわゆるブートローダーがカーネルを起動するステージです。仮想化機能が設定されていました。使っている意識は全然ないのですがもはや必須の機能なんでしょうか、しらんけど。
あとはファイルシステムの構成とデフォルトのプラットフォーム、unfreeのCPUマイクロコードアップデートを行うかどうかの設定です。
設定ファイルに最低限の編集を加える
続いて、configuration.nixを編集してシステム設定をちょっとだけ変更します。
このファイルの中身はNix言語における関数となっており、決まった要素を持ったattribute setを受け取り、決まった様式のattribute setを返します。こうした構造をmoduleと呼んでいます。
nix.devによると、
- module is a function that takes an attribute set and returns an attribute set.
- It may declare options, telling which attributes are allowed in the final outcome.
- It may define values, for options declared by itself or other modules.
- When evaluated by the module system, it produces an attribute set based on the declarations and definitions.
とありますが、システムビルドの設定で登場するmoduleであれば、 (nixpkgs.lib.nixosSystemで評価された際に)パッケージ群やライブラリ、オプション定義など含むアトリビュートセットを受け取り、自ら宣言するオプションや他モジュールのオプションを定義する(ことで機能を調整するような)アトリビュートセットを生成する 、といった感じでしょうか。
まずは最低限の機能として、flakesの有効化、タイムゾーンの設定、一般ユーザーの追加を行うのと、ある程度デスクトップ環境が整うまでコンソールだけで作業を続けるのは辛いので母艦から作業できるようsshdも有効にしておきます。
(略)
nix.settings.experimental-features = [ "nix-command" "flakes" ];
time.timeZone = "Asia/Tokyo";
users.users.naogami = {
isNormalUser = true;
extraGroups = [ "wheel" ];
};
services.openssh.enable = true;
(略)
システムをビルドする
いよいよインストール開始です。
# nixos-install
これで先の設定に基づいてシステムがビルドされます。ビルドといってもキャッシュされたバイナリがダウンロードされるので割とはやく終了します、が、最初に書くべきでしたが作業の前に電源に接続されていることを確認しましょう。フォーマットやダウンロードなど電力を結構使う作業が続きましたがバッテリーが尽きると何の警告もなく突然落ち4て壊れたファイルが残ります。
インストールが成功すると最後にrootのパスワードを尋ねられて終了です。
再起動してwifiを設定し、sshでログインできることを確認する
内蔵ディスクから再起動するとそっけないsystemd-bootの画面で今ビルドしたシステムを(選択肢は現在ひとつですが)選択しログインします。先の設定で一般ユーザnaogamiのパスワード設定を忘れていたので一旦rootでログインして手動で設定してからログインします。
# passwd naogami
ちなみに初回ログイン時用のパスワードを設定ファイルで設定するなら、
users.users.naogami.initialPassword = "foo";
のようにしておけば、新しくユーザーnaogamiが作成されたときのみ初期パスワードfooが設定されます。naogamiとしての初回ログイン後にパスワードを変更できますのでrootでのログインが不要となります。またシステムの再ビルドを行なっても既にnaogamiはありますから設定済のパスワードがfooで上書きされてしまうこともありません。
恒久的なパスワードも宣言的に設定できるみたいですが、secretsを保存する仕組みをきちんと理解して構成しないといけません。敷居が高いです。agenixとかsops-nixといったツールがあるようですが後の課題としておきます。
インストール時に入力したwifi設定は引き継がれないのでnmtuiで再度設定し直します。またまた忘れ物ですがnaogamiユーザーをNetworkManagerのグループに入れてなかったのでsudoが必要です。
以降はsshで母艦から作業をして楽をしたいと思いますので、IPアドレスを確認します。
$ ip addr
母艦からログインできることを確認して一段落です。
-
カシオ PB-100、富士通 Micro-8、シャープ MZ-2000、NEC PC-9801F、Apple Macintosh SE、Apple Macintosh Quadra 660AV、BeBox Dual603e-133、以降自作PC、とお世話になりました。 ↩
-
薬物動態コンパートメントモデルを用いて投薬コンテキストから薬剤血中/効果部位濃度を算出するアプリをdebianマシン上にQt、C++を用いて作成しました。
リアルタイムの超音波断層画像を探索子先にARで表示し穿刺針との位置関係やコリジョンを視認できるアプリをblackmagic社のvideo capture cardを2枚さしたdebianマシン上にARToolkitとOpenCV、Qt、C++を用いて構成しました。 ↩ -
Gentooのインストールでは
chrootしてからの手作業で失敗してやり直し、のループが辛かった思ひ出があります。 ↩ -
落ちました ... 再度立ち上げてマウントしなおしましたがnixos-installが失敗するので/nix以下にあった壊れているであろうファイルを削除したところ継続できました。 ↩