LinuxとかOSSのこととか

Linux (主にNixOS) や OSS に関する取り組みを記述するブログ。

st (simple terminal), Touchpad で スクロールができるようにする

NixOS での話ですが、他でも使えると思います。

最近は、Terminal に st を使っています。rxvt-unicode から乗り換えました。乗り換えた理由は、rxvt-unicode が True Color に対応していなかった、そんな理由だったと思います。

NixOSでの st のインストール方法

NixOS で st を使えるようにするには、/etc/nixos/configuration.nix でパッケージを宣言するだけですが、カスタマイズを色々することになるので、最終的にはこんな感じになります。

  environment.systemPackages = with pkgs; [
# *snip*
    (st.overrideAttrs (oldAttrs: rec {
      patches = [
        ./st-patch/st-scrollback-0.8.5.diff
        ./st-patch/st-scrollback-reflow-0.8.5.diff
      ];
      configFile = writeText "config.def.h" (builtins.readFile ./config.def.h);
      postPatch = "${oldAttrs.postPatch}\n cp ${configFile} config.def.h";
    }))
# *snip*
  ];

フォントやカラーテーマ等は config.def.h で設定します。config.def.h の元本はここから取ってきました。 パッチは、色々機能を拡張できる機能で、それらはここで確認できます。

これらは、どちらもローカルにファイルを保存して取り込むだけでなく、URLから取り込む方法もあり詳細は wiki にあります。私は、ハッシュ値の計算が面倒だったのと、リモートのソースは勝手に変更される可能性があるので、全てローカルに保存して使いました。

そんなことより重要なのは、config.def.h が反映されるのはパッチを当てた後になることです。パッチには config.def.h の diff もあるのですが、それらの diff は 自分の用意した config.def.h で上書きされます。なのでパッチを読んで、config.def.h の設定を自分の config.def.h に適切に拾い上げていく必要があります。

本題

せっかくインストールした st ですが、画面をスクロールさせることができませんでした。タッチパッドを下から上に動かすと、^Y が端末に入力され、上から下に動かすと^E が入力されるだけでした。悲しい。

解決策は、FAQ によると、3つあるようです。この記事では最後のを試しました。2つ目は scroll をどうやって NixOS で取り込み管理していくか、すぐには分からなかったため、試さなかったです。

## How do I scroll back up?
  * Using a terminal multiplexer.
    * `st -e tmux` using C-b [
    * `st -e screen` using C-a ESC
  * Using the excellent tool of [scroll](https://git.suckless.org/scroll/).
  * Using the scrollback [patch](https://st.suckless.org/patches/scrollback/).

やったこと

上記の configuration.nix の通り、スクロール機能を追加するために2つのパッチを追加しました。また、スクロール機能をキーバインドするため、config.def.hを以下のように編集しました。Button4がタッチパッドを下から上にスクロールさせることに相当し、Button5がタッチパッドを上から下にスクロールさせることに相当します。それらに今回追加した kscrollup, kscrolldown を設定しました。これにより、タッチパッドを動かしても画面がスクロールされない問題が解決しました。

diff --git a/config.def.h b/config.def.h
index f8546d0..4dd4821 100644
--- a/config.def.h
+++ b/config.def.h
@@ -163,9 +163,9 @@ static MouseShortcut mshortcuts[] = {
        /* mask                 button   function        argument       release */
        { XK_ANY_MOD,           Button2, selpaste,       {.i = 0},      1 },
        { ShiftMask,            Button4, ttysend,        {.s = "\033[5;2~"} },
-       { XK_ANY_MOD,           Button4, ttysend,        {.s = "\031"} },
        { ShiftMask,            Button5, ttysend,        {.s = "\033[6;2~"} },
-       { XK_ANY_MOD,           Button5, ttysend,        {.s = "\005"} },
+       { XK_ANY_MOD,           Button4, kscrollup,      {.i = -1} },
+       { XK_ANY_MOD,           Button5, kscrolldown,    {.i = -1} },
 };

NixOS で Vim プラグイン deoplete.nvim を使えるようにする

TL;DR

  deoplete.nvim のインストールには, vim の Python3 サポートだけではなく, pynvim も必要です. そのため, 以下のように configuration.nix を追記してビルドしました.

environment.systemPackages = with pkgs; [
  ...
  (vim_configurable.override { python = python39.withPackages (ps: with ps; [ pynvim ]); }) 
  ...
];

しかし, pynvim を vim から見つけられず, エラーになってしまいました.

[vim-hug-neovim-rpc] requires one of `:pythonx import [pynvim|neovim]` command to work 

この問題を解決するために, python3 のパッケージも追加でインストールし, deoplete.nvim を使えるようにしました.

environment.systemPackages = with pkgs; [
 ...
 (python39.withPackages (ps: with ps; [ pynvim ]))
 (vim_configurable.override { python = python39; }) 
 ...
];

説明すること

  • NixOS での Vim のインストール方法
  • Python3 サポートされた Vim のインストール方法
  • deoplete.nvim を入れた際のエラーとその解消方法

NixOSでのVimのインストール方法

システムに vim をインストールしたい場合は, /etc/nixos/configuration.nix を編集して, nixos-rebuild でビルドしてシステム設定を切り替えます. 一方, ユーザーの場合は nix-env 等でインストールします. 本記事では, 便宜的にシステムにインストールする場合の話に限定します.

vim インストールは他のパッケージと同様に, 以下のように environment.systemPackages にパッケージ名を追加すればできます. 自分のインストールしたいパッケージがあるかを調べたい場合は, ここで調べると良いです. vim パッケージは他にも vimHugeX, vim_configurable といくつか種類がありますが, 設定をいじることができる vim_configurable がおすすめです. また, vimHugeX は vim_configurable のエイリアスです.

environment.systemPackages = with pkgs; [
  vim_configurable
];

Python3サポートされたVimのインストール方法

NixOS WikiのVimの記事を参考に, 以下のように記述します.

environment.systemPackages = with pkgs; [
  ...
  (vim_configurable.override { python = python3; })
  ...
];

インストールできたかの確認は以下の方法で確認できます.

  • vim --version を入力して, +python3 が表示される
  • vim を起動して :echo has("python3") を実行し, 1 が返る

deoplete.nvim を入れた際のエラーとその解消方法

deoplete.nvim は入力補完用のプラグインです. deoplete.nvim のインストールには, vim の python3 サポートと pynvim が必要になります. そこで, NixOS WikiのPythonの記事を参考に, 以下のように記述しました.

with pkgs;
let
  packages = python-packages: with python-packages; [
    pynvim
  ]; 
  python-with-my-packages = python3.withPackages my-python-packages;
in 

...

environment.systemPackages = with pkgs; [
 ...
 (vim_configurable.override { python = python-with-my-packages; }) 
 ...
];

そして, 以下のプラグインをインストールしました. 下2つは deoplete.nvim を使うのに必要なプラグインです. ちなみに, プラグインのインストール方法は省略します. 私は vim-plug を使用しました.

これで無事 deoplete.nvim が使えるようになっていれば御の字ですが, 実際は, 以下のエラーメッセージがでてしまいました.

[vim-hug-neovim-rpc] requires one of `:pythonx import [pynvim|neovim]` command to work...

調べたところ, 上記でインストールした pynvim は, /nix/store 直下にパッケージとしてインストールされている一方, pythonサードパーティライブラリが保存される site-packages にはインストールされていないようでした.

このエラーを解決するために色々と格闘した結果, 以下のように追加で python もインストールすることで解消されました.

environment.systemPackages = with pkgs; [
 ...
 (python39.withPackages (ps: with ps; [ pynvim ]))
 (vim_configurable.override { python = python39; }) 
 ...
];

以下で vimpython は, 新しくインストールされた python パッケージをみることが確認できました.

vim上で :pythonx import sys; print(sys.path)
[
 '/nix/store/qmaczi731dgiip22am4js0b0k574z6wl-python3-3.9.2-env/lib/python39.zip',
 '/nix/store/qmaczi731dgiip22am4js0b0k574z6wl-python3-3.9.2-env/lib/python3.9', 
 '/nix/store/qmaczi731dgiip22am4js0b0k574z6wl-python3-3.9.2-env/lib/python3.9/lib-dynload',
 '/nix/store/qmaczi731dgiip22am4js0b0k574z6wl-python3-3.9.2-env/lib/python3.9/site-packages', 
 '_vim_path_'
]

端末上で readlink `which python`
/nix/store/qmaczi731dgiip22am4js0b0k574z6wl-python3-3.9.2-env/bin/python

NixOS上で、Linux From Scratch を構築した

はじめに

Linux From Scratch(以下 LFS)は, 自前の Linux システムを構築するプロジェクトです. このプロジェクトでは, 必要なパッケージを 1 つ 1 つ, ソースコードからビルドし, Linux システムを構成します. 本記事は, NixOS 上で LFS を構築し, 一般的なディストリビューションと違った点を紹介する記事です.

次のように構築していきました. はじめに, ハードディスクイメージを作成し, パーティションファイルシステムの作成します. 次に, ソースコードをダウンロードし, LFS システムの内外でビルド, インストールを行い, 段階的にシステムを構築していきます. 最後に, QEMUを用いて, LFS を起動します. 最終結果は, 下の図です. 起動時は GRUB を使用せず, UEFI Shell から Linux 本体を実行しています.

f:id:ykonomi:20210515081758p:plain
最終画面

ドキュメントは, 有志の日本語訳を使用しました. 英語のドキュメントだと途中でやめてしまう可能性があるためです. また, この記事を作成するにあたり, LFS は合計 3 回構築しています. はじめは, コマンドをタイプして入力していたのですが, 2 回目以降はスクリプトにしています. 作成したスクリプト群は, 以下にまとめています. 以下では, このリポジトリを単にリポジトリとして言及することがあります.

github.com

構築するLFSのバージョンとホスト情報

  • LFS Version: 10.1-systemd
  • NixOS Version : 20.09
  • CPU モデル名: AMD Ryzen 7 3700U

インストールしたパッケージ

LFS の構築にあたって, インストールしたパッケージを紹介します. LFS のドキュメントには, 一般ユーザーで作業する部分があります. 本記事では, 作業のしやすさを考慮して, インストールするパッケージを分けました.

システムにインストールしたパッケージは以下です. configuration.nix に記述し, ビルドしました.

  environment.systemPackages = with pkgs; [
    ...
    parted 
    wget
    file
    bison
  ];

また, qemu と OVMF ファームウェアを使うため, 以下のオプションを追加しました.

virtualisation.libvirtd.enable = true;
virtualisation.libvirtd.qemuOvmf = true;

一般ユーザーにインストールしたパッケージは以下です. NixOS では一般ユーザーが使うパッケージは nix-env コマンドを使い, インストールします.

[lfs@nixos:/root]$ nix-env --query
binutils-2.31.1
gnum4-1.4.18
gnumake-4.3
python3-3.9.2

記事の構成

LFS のドキュメントでは, 3 部構成で LFS の構築手順を説明していますが, 本記事では以下の 5 部構成で説明します.

  • part1: ディスクの作成, ソースダウンロード, ユーザー lfs の作成
  • part2: ユーザー lfs による一時ツールの作成
  • part3: chroot 環境の準備と chroot 環境での一時ツールの追加ビルド
  • part4: chroot 環境での LFS システム構築
  • part5: Linux カーネルビルドと起動

一時ツールとは, LFS システムを構築するための一時的なツールです. 例えば, GCC(the GNU Compiler Collection)です. LFS システムには(C で書かれた)カーネルをビルドするため, GCC が必要ですが, その GCC 自体をビルドする GCC が必要になります. この例のように, LFS システムを構築するために必要なツールを先に作成します.

各パートごとの作業の詳細は省きます. ドキュメントの二番煎じになってしまうためです. 記事のメインは, 様々な理由でドキュメントの手順通りにいかなかった内容です. 特に, part2 ではホスト環境のツールを使うため, NixOS 特有の作業があります.

ちなみに, 作業マシンでビルドにかかった時間は以下です. ビルドは, ソースファイルの解凍, インストール時間も含まれます. また, part4 ではビルド物のテストが手順に含まれていたので, そちらの時間も載せています. なお, リポジトリの sbu.txt には詳細な測定結果があります.

part 時間(分)
2 36
3 8
4 build 56
4 check 149
5 7

part1の特記事項

ディスクの作成

ホストのストレージにハードディスクイメージを作成しました. 手持ちに物理的なメディアがなく, 購入するのも億劫であったためです. ディスクの容量ははじめ, 20G で作成したのですが, 途中で足らなくなり 60G で作り直しました.

qemu-img create -f raw lfs.img 60G

パーティションUEFI 対応のもので, parted を用いて作成しました. コマンドはNixOS Manualを参考にしています. また, ファイルシステムを作成する際は, ループバックデバイスを使用しています.

parted lfs.img -- mklabel gpt
parted lfs.img -- mkpart primary 512MiB -8GiB
parted lfs.img -- mkpart primary linux-swap -8GiB 100%
parted lfs.img -- mkpart ESP fat32 1MiB 512MiB
parted lfs.img -- set 3 esp on

losetup -P /dev/loop0 lfs.img 
mkfs.ext4 -L lfs /dev/loop0p1
mkswap -L swap /dev/loop0p2
mkfs.fat -F 32 -n boot /dev/loop0p3

一時ツールの作成用のインストールディレクトリの作成

LFS のドキュメントでは, ダウンロードファイルを sources ディレクトリに保存する方針です. しかし, LFS システムを構築するための一時ツールの構築と LFS システム構築を同じディレクトリで行うことで, ビルド作業に混乱がありました. そのため, 一時ツールのソースは tools-sources, LFS システムのソースは sources に保存しました. 具体的なソースリストは, リポジトリの part1/tools-list にあります.

作業用ユーザー lfs の作成

configuration.nix に以下を追加してビルドします. 作業中にパスワードを入力する煩わしさがあるため, パスワードは設定しないことにしました.

users.groups.lfs = {}; # group: lfs
users.users.lfs = {
  isNormalUser = true;
  home = "/home/lfs";
  extraGroups = [ "wheel" "lfs" ];
};

ユーザーに配布する .bashrc は以下です. 追加行は 9 行と 10 行です. NixOS は一般的なディストリビューションとは違い, /bin, /usr/bin に, ls 等の身近なシェルコマンドがありません. 実際に確かめてみると /bin には sh, /usr/bin に env しかないことがわかります. また, NixOS はパッケージを全て /nix/store 以下の Nix Store で管理しているため, 仮にコマンドがあったとしても, それらは全て, Nix Store へのシンボリックリンクになっています. このため, ls 等のコマンドを lfs ユーザーでも使えるようにするため, 9 行目と 10 行目を追加しています. 9 行目は, configuration.nix 経由でインストールした実行ファイルがあるパスで, 10 行目は, nix-env で lfs ユーザーにインストールした実行ファイルがあるパスです. 注意点は, 一時ツールは tools 以下に保存されるため, そちらを優先して探すようにパスを追加してます.

cat > ~/.bashrc << "EOF"
set +h
umask 022
LFS=/mnt/lfs
LC_ALL=POSIX
LFS_TGT=$(uname -m)-lfs-linux-gnu
PATH=/usr/bin
if [ ! -L /bin ]; then PATH=/bin:$PATH; fi
PATH=/run/current-system/sw/bin:$PATH
PATH=$HOME/.nix-profile/bin:$PATH
PATH=$LFS/tools/bin:$PATH
CONFIG_SITE=$LFS/usr/share/config.site/run/current-system/sw/bin
export LFS LC_ALL LFS_TGT PATH CONFIG_SITE
EOF

part2の特記事項

version_check.sh の修正

LFS のドキュメントには, ホストシステム要件としてスクリプトが用意されています. それを実行することで, 必要なパッケージがホストにインストールされているかを確認できます. NixOS の特徴的な仕組みから, スクリプトを修正する必要がありました. それらを次で紹介します.

Shebangsの変更

NixOS には /bin/bash はないため, /bin/sh か /usr/bin/env bash で Shebangs を設定します. 以下は env の例です.

#! /usr/bin/env bash

シンボリックリンクの作成

一部のコマンドは, 特定のパスにあることが重要になります. そのため, 以下のように, それらのコマンドのシンボリックリンクを作成しました. env は元々あったものです. また, ホストシステム要件にはなかったのですが, file パッケージが必要になったため追加しています.

[root@nixos:~/lfs-in-nixos]# ls -l /usr/bin/
total 4
lrwxrwxrwx 1 root root 30 Mar 19 11:16 awk -> /run/current-system/sw/bin/awk
lrwxrwxrwx 1 root root 66 May 21 02:59 env -> /nix/store/vr96j3cxj75xsczl8pzrgsv1k57hcxyp-coreutils-8.31/bin/env
lrwxrwxrwx 1 root root 31 May  9 19:24 file -> /run/current-system/sw/bin/file
lrwxrwxrwx 1 root root 32 Mar 19 11:16 yacc -> /run/current-system/sw/bin/bison

nix-shell 上でgcc, g++ を実行する

NixOS の GCC パッケージは更に特殊で, nix-env でインストールした GCC では, コンパイルに失敗します. これは, /usr/include, /usr/lib がなく, crt1.o 等のファイルがないためです. そのため, NixOS では, gcc や g++は nix-shell による環境で実行する必要があります. これに合わせて, version_check.sh の GCC に関する部分を以下のように書き換えました. -p がパッケージの指定, --run が非インタラクティブモードでの指定されたコマンドの実行を意味します.

nix-shell -p gcc --run "gcc --version | head -n1"
nix-shell -p gcc --run "g++ --version | head -n1"

echo 'int main(){}' > dummy.c && nix-shell -p gcc --run "g++ -o dummy dummy.c"
if [ -x dummy ]
  then echo "g++ compilation OK";
  else echo "g++ compilation faield"; fi
rm -f dummy.c dummy

SBU値と並列ビルド数

LFS では, 各パッケージのビルド時間とインストール時間の合計を見積もるため, 最初のパッケージである Binutils のビルド時間とインストール時間の合計を標準ビルド単位(Standard Build Unit; SBU)として使います. 以下は, MAKEFLAGS の値に対する SBU です. ホストシステムの論理プロセッサ数は 8 であるため, 本番では -j8 を指定します.

フラグ 時間(xmys)
-j1 2m43.576s
-j2 1m37.105s
-j4 1m3.539s
-j8 0m58.666s
-j10 1m0.586s

コンパイルエラー解消のため, コンパイルオプションの追加

一時ツールの中には, デフォルトの gcc をそのまま使うとコンパイルエラーになってしまうパッケージがあります. それは BinutilsGCC です. これは, セキュリティ強化のための設定ですが, このままだとビルドできません. そのため, -Wformat -Wformat-security -Werror=format-security をコンパイル時に追加する必要があります. NixOS では, 以下のファイルを作成し, nix-shell で指定することで, それらのフラグを追加できます. hardeningDisable にある"format"がそのためのオプションです. なお, その他の設定はこちらにあります.

cat > gcc_with_options.nix << "EOF"
  with import <nixpkgs> {};
  pkgs.mkShell {
  buildInputs = with pkgs; [ gcc ];
  hardeningDisable = [ "format" ];
}
nix-shell gcc_with_option.nix --run "./configure --hoge && make && make install"

ネイティブコンパイラとクロスコンパイラの両方を必要とするパッケージをビルドする

例えば, ncurses です. パッケージ gcc を指定した nix-shell 環境では, 環境変数 CC や CXX に gcc, g++ が設定されます. これにより, ./configure で gccx86_64-lfs-linux-gnu-gcc の代わりにクロスコンパイラに設定されてしまいます. そのため, CC や CXX を unset しています. また, nix-shell ではパッケージの gcc への PATH が先頭に追加されていました. そのため, PATH の先頭に一時ツールが先に見つかるように新たに PATH を追加してます.

cat > gcc.nix << "EOF"
  with import <nixpkgs> {};
  pkgs.mkShell {
  buildInputs = with pkgs; [ gcc ];
  shellHook = '' 
    export PATH="$LFS/tools/bin:$PATH"
    unset CC
    unset CXX
  '';
}
EOF

part3, part4の特記事項

特記事項はないです. ここからは, Chroot 環境での作業であり, NixOS のパッケージにはアクセスしないため, 他のディストリビューションと同様の構築になります.

part5の特記事項

カーネルの設定

make defconfig による設定のままですが, UEFI 上で起動するため, EFI stub support にチェックが入っていることを確認しました.

QEMUによる実行

起動のため, 以下のコマンドを実行しました. UEFI ファームウェアを使うため OVMF.fd を /nix/store 以下からコピーしました.

qemu-system-x86_64 -bios OVMF.fd -hda lfs.img

起動後 30 秒程度待つと, UEFI Shell が起動します. FS0: でディスクをマウントし, 以下のコマンドを実行すると, Linux が起動します. その後コンソール画面に移行するので, パスワードを入力すれば, 記事冒頭の図の画面になります.

vmlinuz_5.10.17-lfs-10.1-systemd root=/dev/sda1

おわりに

NixOS での LFS を構築したときの違った点を紹介しました. NixOS では, パッケージは全て Nix Store で管理されるため, いくつかの点でやり方を変える必要がありました. NixOS での作業にずいぶん慣れた気がします. 次にやることですが, part5 は駆け足でやってしまったので, そのあたりの理解を深めるために GRUB の設定をしたいです. また, Beyond Linux From Scratchと呼ばれる LFS 構築後のプロジェクトがあります. それは, NixOS とは関係ないですが, せっかく最小限の Linux が手に入ったので, Linux の理解を深めるため, 手を付けたいです.

NixOSマシンを自分好みにカスタマイズする

はじめに

前回の記事では ThinkPad に NixOS をインストールしました。 今回の記事では、このマシンを自分好みにカスタマイズします。 NixOS でシステムの構成するには、設定ファイル configuration.nix を編集し、ビルドコマンドを実行します。 本記事では、マシンのカスタマイズに何をしたかとそのために configuration.nix をどのように編集したかを書いていきます。 また、この記事はカスタマイズした NixOS マシン上で書いており、文章の推敲にはtextlintを使用しています。

タイムゾーンの設定

time.timeZone = "Asia/Tokyo"

GUIの環境の導入

services.xserver.enable = true; で, X11 を使えるようにします。 また, ウィンドウマネージャとして i3 を使用します。 他に、以下の設定を加えています。

  • Control(Left)と Caps Lock キーを入れ替える設定
  • トラックパッドを使用できるようにする設定
  • トラックパッドのスクロールを上にスワイプすると下にスクロールする設定

最終的に、以下のコードになります。

services.xserver = {
  enable = true;
  windowManager.i3.enable = true;
  xkbOptions = "ctrl:swapcaps";
  libinput.enable = true;
  libinput.naturalScrolling = true;
};

サウンドを使えるようにする

あまり使ってませんが、一応。

sound.enable = true;
hardware.pulseaudio.enable = true;

Wi-Fi の設定

無線 LAN を使えるようにするための Wi-Fi の設定のコードは以下です。 ハッシュされた PSK は wpa_passphrase コマンドで生成しました。 ちなみに、平文の場合は networking.wireless.networks.<ESSID>.psk を使います。 また、DHCP で IP アドレスをサーバから自動で取得できるようにしました。

networking.wireless.enable = true;
networking.wireless.networks = {
  <ESSID> = {
    pskRaw = "<ハッシュされたPSK>";
  };
}
networking.useDHCP = false; # is deprecated, therefore explicitly set to false here.
networking.interfaces.<インタフェース名>.useDHCP = true;

日本語入力の設定

インプットメソッドに fcitx を使います。また、日本語入力の変換に mozc を使いました。 ビルド後(後述)、再起動すると fcitx が自動で立ち上がります。 fcitx-configtool で「Keyboard - English(US)」「Mozc」を設定し、Ctrl+Space で切り替えるようにしました。

i18n.inputMethod = {
  enabled = "fcitx";
  fcitx.engines = with pkgs.fcitx-engines; [ mozc ];
};

システムに様々なソフトウェアをインストールする

使いたいパッケージを記述します。 Vim はパッケージから取得すると、クリップボードのサポートがないものを取得します。 この Vim は、システムのクリップボードを共有しないため、不便です。 そのため、vimHugeX を指定しています。

environment.systemPackages = with pkgs; [
  vimHugeX
  w3m
  git
  chromium
  rxvt_unicode
];

日常ユーザーの作成

ビルド後、root アカウントからpasswdでパスワードを後から設定しました。

users.users.ykonomi = {
  isNormalUser = true;
  home = "/home/ykonomi";
  extraGroups = [ "wheel" ];
};

システム構成のビルド

作成した configuration.nix を元に、以下のコマンドより、システム構成をビルドし切り替えます。 システム構成が大きく変わりのもあり、正しく変更されたかの確認のため、再起動もしてます。 ちなみに、システム構成のビルドだけを試しに行う場合は nixos-rebuild buildを実行します。 また、システム構成を切り替えるがデフォルトのシステム構成にしない場合は nixos-rebuild testを実行します。

nixos-rebuild switch
reboot

最後に

以上により、NixOS マシンのシステム設定しました。 一度にすべての設定をしたわけではないため、再現性に乏しいです。 特に、日本語入力は、はじめは Mozc が起動しなかったため、一時期 Anthy を使用していました。1 設定を configuration.nix 1ファイルでできることで、自分がどのようにシステム設定したかをひと目でわかるのがいいと感じています。 他の利点は、ビルドしたシステム設定間を切り替えることができる点です。 トライアンドエラーでお世話になりました。


  1. xterm を urxvt に変えたあたり、うまくいくように。 一方、xterm に戻しても Mozc が使用できたので真相は闇の中です。その際、いろいろいじりすぎたのであまり参考にはならないと思います。

ThinkPad E595 に NixOS をインストールする

はじめに

前々回から二年も開いたので、またOSインストールの話からします。OSインストール芸人ではないです。 経緯は、突如新しいPCを買いたくなったため購入し、せっかくなのでLinuxマシンにしようと思ったのが経緯です。 購入したPCは、ThinkPad E595で、私にとって初のRyzen CPU搭載マシンになります。 主なカタログスペックは以下です。

  • ディスプレイ: 15.6型FHD液晶 (1920x1080) IPS、光沢なし、250nit
  • CPU: AMD Ryzen 7 3700U (2.3GHz, 4MB)
  • メモリ: 16GB DDR4 2400 SoDIMM
  • SSD: 512GB (M.2 2280, PCIe-NVMe)
  • キーボード: US配列

作業内容

以前 (NixOS を始める 起動編 - LinuxとかOSSのこととか) と同様に NixOS Manual に則って作業しましたが、 UEFI対応マシンであるためコマンドは前回と違い、GPTを作成するものになりました。 また、ネットワーク接続はLANケーブルを使用しています。

途中過程の画像は以下です。 1枚目はUSB Bootのための設定画面です。OS Optimized Default を disabled し、 Load Setup Defaults を実行しています。(BIOS (Boot Menu) でUSBディスクから起動する - Windows 8, Windows 10 - ideapad/Lenovo ノートブック - Lenovo Support UY を参考にしました)

2枚目はUSBのインストーラーの起動画面です。

f:id:ykonomi:20201110063913j:plain f:id:ykonomi:20201110063920j:plain

ハマりどころ

パーティションを作成し、フォーマットする対象のデバイスは /dev/nvme0n1 です。 マニュアル通りに /dev/sda を指定すると、インストールUSBがフォーマットされることになります。 (2回やらかす)

これから

日常ユーザーアカウントの作成、ウィンドウマネージャーのインストール、日本語入力ができるようにしたいです。

また、書きます。

前回の記事から二年経ち、モチベも戻りつつあるため、ブログを再開しようと思う。 丸二年 Linuxに関する活動らしい活動はしてこなかったけど、一応 LPIC1, 2, 3(303) を取得した ので、その合格体験記はかけるかなと思う。(某所で発表したし... スライドはある。) NixOSのマシンは、この二年でただ YouTube をみるための娯楽マシンと化してしまったため、 もっと真面目に向き合いたいと思う。というのも、前回の記事が、Google検索で1ページに ひっかかるようになってしまい申し訳ない気持ちがあるためである。(Nix Expressions の話も なく、 NixOS 特有のパッケージ管理の仕組みも説明せず、どのOSにもあてはまるような話を... すいません)今後の記事の方針は、OSS、特にLinuxを中心にある程度まとまった内容を書けたら と思う。頑張ります。

NixOS を始める 起動編

はじめに

この記事は Linux Advent Calendar 2018の4日目の記事です。この記事は前回の記事の続きですが、ちょうど Advent Calendar の時期なので、ついでに載せることにしました。

ykonomi.hatenablog.com

NixOSは、純粋関数型 Linux Distribution であり、Nix パッケージマネージャを利用して作られるOSです。Nix は関数型由来の様々な独自機能を持っています。この記事ではそのことをほとんど紹介できていませんが、興味を持った方はぜひ初めてみてください。

この記事は、実際に NixOS をインストールするまでの記録です。具体的には、インストールメディアの作成、パーテーションの作成、設定ファイルの作成、インストールと起動を行います。当初の目的は、この記事自体を NixOS 上で執筆することでしたが、日本語入力がうまくできなかったため仕方なく諦めました。そのため、ゴールはGUI上でログイン画面が表示されるまでとしました。

また、ここで行った手続き、入力したコマンドは全てNixOS manualを参照しています。

インストール用のUSBメモリの作成、起動

マニュアルによると、インストールするメディアはCD, DVD, USBメモリから選択することができました。しかし、手持ちにUSBメモリしかなかったため、USBメモリを選択しました。

f:id:ykonomi:20181122075114j:plain
インストール用のUSBとインストール先のSSDSSDは友人からただでもらう。

USBメモリへの書き込み時に入力したコマンドは以下です。作業はMacOS上で行いました。2行目のdisk2は1行目のdiskutil listによって判明した識別子であり、PCに刺したUSBメモリを指します。nix.iso は公式で入手してリネームしたものです。

$ diskutil list
$ diskutil unmountDisk disk2
$ sudo dd bs=1m if=nix.iso of=/dev/rdisk2

この作業は特別問題なくできたのですが、ログに以下の表示がでるだけだったので、本当に書き込みが成功したか不安でした。

541065216 bytes transferred in 56.234190 secs (9621641 bytes/sec)

次に、作成したUSBメモリが優先的に起動できるよう、BIOSの設定を行いUSBを先に起動できるようにしました。以下がその時の画像です。

f:id:ykonomi:20181203073352j:plain
インストールメディア起動画面。一番上以外が謎のまま。

画像を撮り忘れたのですが、インストールメディア起動後CUIが起動します。以降のコマンドはそのCUI上で実行しています。ちなみに、デフォルトのキーレイアウトはUS配列です。

パーティションの分割、フォーマット、そして、インストール

インストール先のメディアとして、上の図にある SSD(容量は256GB)を使用しました。マニュアルによると、NixOS のシステムをブートする方法として、BIOSとUDFIがあります。しかし、自分が所持するマザーボードが10年ものであり、UDFIに対応していなかったため、(というか、UDFIをその時に初めて知りました。)BIOSで起動せざるを得ませんでした。次の機会にはUDFIを試したいです。パーティションの作成で入力したのが以下のコマンドです。BIOSでは、パーティションテーブルとしてMBR (Master Boot Record) を用います。コマンドの1行目がこのパーティションテーブルを作成するコマンドです。2行目ではルートパーティション(/から始まる)を作成し、3行目ではスワップパーティションを作成しています。

# parted /dev/sda -- mklabel msdos
# parted /dev/sda -- mkpart primary 1MiB -8GiB
# parted /dev/sda -- mkpart primary linux-swap -8GiB 100%

次にフォーマットです。以下のコマンドを入力しました。マニュアル通りです。

# mkfs.ext4 -L nixos /dev/sda1
# mkswap -L swap /dev/sda2

最後に、インストールです。以下のコマンドを入力しました。マニュアルとの相違点はnanoではなくvimを使った点です。単純にnanoが使えないためvimにしました。

# swapon /dev/sda2
# mount /dev/disk/by-label/nixos /mnt
# nixos-generate-config --root /mnt
# vim /mnt/etc/nixos/configuration.nix
# nixos-install

configuration.nix はNixOSの全体のシステムを設定するファイルです。configuration.nix に、使用するパッケージを記述します。nixos-install コマンドを実行することで、configuration.nix に記述されたパッケージがビルドされインストールされます。configuration.nix の最初コードは、以下のように記述しました。

{ config, pkgs, ... }: {
  imports = [
    # Include the results of the hardware scan.
    ./hardware-configuration.nix
  ];

  boot.loader.grub.device = "/dev/sda"; 
};

nixos-install 後の結果が以下の図です。

f:id:ykonomi:20181203073454j:plain
nixos-install 成功後のコンソール画面

マニュアルでは、この後、reboot することでNixOSを立ち上げることができる、と記述されていました。しかし、私の環境の都合で再起動後、インストールメディアの方が先に立ち上がってしまったトラブルがありました。本来立ち上がるべきなのは、インストール先のメディアであるため、BIOSの設定から起動優先順位を変更しインストール先のメディアを先に起動できるようにしました。

起動後、GRUBのブートメニューが立ち上がります。成功したみたいです。

f:id:ykonomi:20181203073518j:plain
GNU GRUB2 の画面

一般ユーザーの作成

この記事の趣旨としてはおまけになります。rootユーザーのみでは常用OSとしては不安なため、一般ユーザーを追加しました。mutableUserは、デフォルトはtrueですが、falseすると、users.users 最初に設定したパスワードが起動時のパスワードになり、パスワードを変更しても再起動すれば元に戻るなど、面白い挙動になります。

  users.mutableUsers = true; #default
  users.users.ykonomi = {
    isNormalUser = true;
    home = "/home/ykonomi";
    description = "";
    extraGroups = ["wheel" "networkmanager"];
  };
  

X Window System (X11) の導入

GUIが欲しいため、X Window Systemを導入しました。以下をconfiguration.nixに追加しました。当然ですが搭載するグラボによって指定するデバイスドライバも変わります。また、freeではないソフトウェアを設定ファイルに記述するためにnixpkgs.config.allowUnfree = true; を記述する必要があるなど、ad hoc な対応が要求されました。

  nixpkgs.config.allowUnfree = true;
  services.xserver = {
      enable = true;
      videoDrivers = [ "nvidia" ];
      desktopManager.gnome3.enable = true;
      layout = "us";  # default
  };  

ユーザー設定とX Window Systemの設定をconfiguration.nix に追加して、再ビルドしたものが以下の図です。無事ログイン画面を表示させることができました。

f:id:ykonomi:20181203073433j:plain
ログイン画面。歪みがひどい。

まとめ・感想

マニュアルを読み、以前から気になっていたNixOSをインストールしました。 作業を少しずつ進めるたびに一つずつレベルアップしていく感じがしてよかったです。 次は日本語入力対応とNixOpsというものがあるらしいので試してみたいです。