NixOS を使い始めたときに設定をしたときのメモ。前半は VM に入れた NixOS で作業している。後半からは実機にインストールして作業する。自分用のメモを仕立て直したものなので読みにくいかも。
NixOS の使用感を知りたい人は一番下までスクロールすると書いてある。
#参考にするもの
公式のドキュメントに良いチュートリアルを見つけられなかったので、こちらの日本語記事を参考にする:https://zenn.dev/asa1984/articles/nixos-is-the-best
#ISO イメージをダウンロードする
公式サイトから GNOME の ISO イメージをダウンロードする:https://nixos.org/download/
#vim と gnome-terminal を入れる
GNOME で立ち上げると XTerm は入っているが gnome-terminal は入っていない。Vim も入っていないので入れる。NixOS の設定は /etc/nixos/configuration.nix
にあるので、これを書き換える。
environment.systemPackages = with pkgs; [
vim
pkgs.gnome.gnome-terminal
]
みたいにする。その後
sudo nixos-rebuild switch
すると入る。
#Nix command と flakes を有効化する
nix
というコマンドがあって、nix-HOGEHOGE
というコマンドを統一的なインターフェースで扱えるようになっているらしい。現時点では実験的な機能でデフォルトでは入っていないらしいので、これを入れる:https://nixos.wiki/wiki/Nix_command
あと Flake とかいう、パッケージをいい感じに使えるようになる機能も実験的な機能ということになっているので、これも入れる:https://nixos.wiki/wiki/Flakes
日本語記事では以下のようにしていれている:
nix = {
settings = {
experimental-features = ["nix-command" "flakes"];
}
}
が、以下のようにしてもよさそう:
nix.settings.experimental-features = ["nix-command" "flakes"];
#Flake を作る
自分の環境の設定は Flake とかいうのを作って管理するらしい。~/.dotfiles
に Git repo を作り、/etc/nixos
配下のファイルを全部コピーしてくる。追加で flake.nix
も作る。
flake.nix
の書き方はここに説明がある:https://nixos.wiki/wiki/Flakes#Flake_schema
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
};
outputs = inputs: {
nixosConfigurations = {
myNixOS = inputs.nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
./configuration.nix
];
};
};
};
}
inputs
が attribute set で、outputs はこれ(に拡張が入ったもの)を受け取って attribute set を返す関数。どういう attribute set を返せばよいかは schema に書いてある。ここでは nixosConfigurations
を返す。これは nixos-rebuild switch --flake .#<hostname>
したときに使われる。
outputs
中では inputs
が引数として渡されているので、これを参照できる。
nixpkgs.lib.nixosSystem
には NixOS のシステムを立ち上げるために必要なパッケージが入っているらしい。https://www.reddit.com/r/NixOS/comments/13oat7j/comment/jl6aka8/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button
#configuration.nix を書き換える
ドキュメント:
- https://nixos.org/manual/nixos/stable/#ch-configuration
- https://nixos.org/manual/nixos/stable/options
##users.*
ユーザの設定。https://nixos.org/manual/nixos/stable/#sec-user-management
mutableUsers = false
にしたい。するとパスワードを configuration.nix で設定する必要がある。mkpasswd
コマンドに打ち込んで得た結果を users.users.anqou.hashedPassword
に突っ込む。
##programs.*
Appendix A のドキュメントを見ながら必要そうなものを入れるのがよさそう。とりあえずは日本語記事に書いてあったものを入れる。
##IME の設定
https://nixos.org/manual/nixos/unstable/#module-services-input-methods
stable と unstable で設定方法が異なる。たぶん unstable を使っているので以下のように書く:
i18n.inputMethod = {
enable = true;
type = "fcitx5";
fcitx5.addons = with pkgs; [ fcitx5-mozc ];
};
Nix の with pkgs; [ fcitx5-mozc ]
は [ pkgs.fcitx5-mozc ]
と等価らしい。https://nix.dev/tutorials/nix-language.html#with
##JP キーボードの設定
IME の設定を有効にするために再起動したところ、キーボード設定が us になっている。configuration.nix には services.xserver.xkb.layout = "jp"
と書いてあるのに。
というか services.xserver.enable = true
なのに Wayland が立ち上がっている。なんてこったい。
https://discourse.nixos.org/t/enabling-x11-still-results-in-wayland/25362/2 によると ↑ は X を使えるようにするだけで、実際にどちらを使うかは GDM の歯車次第らしい。
Hyprland を使う都合上 Wayland で立ち上がってほしいのは事実なので、wayland の設定をする。
と思ったのだが、Wayland だと統一的な設定方法が用意されていなくて、それぞれの WM で設定する必要がありそう。GNOME は単に GUI の設定アプリから設定しろという話らしい。
と思ったのだが、設定アプリから設定したものは再起動すると初期化されてしまうっぽい。こういうのは dconf で設定する必要がありそう。home-manager とかいうやつを使ってもできるし、単に programs.dconf
でも設定できそう。https://wiki.nixos.org/wiki/GNOME#dconf_settings
まず dconf watch /
を実行してから GNOME の設定画面をいじると、以下のような表示が出る:
/org/gnome/desktop/input-sources/sources
[('xkb', 'jp')]
のでこれをもとに configuration.nix をいじる。
dconf の式を Nix の式として書く必要がある。https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-gvariant が公式のドキュメント。https://github.com/nix-community/dconf2nix なども使えそう。今回は https://discourse.nixos.org/t/dconf-org-gnome-desktop-input-sources-sources-gets-reverted-upon-login/39263 を参考にした。
dconf = {
enable = true;
profiles.user.databases = [
{
lockAll = true;
settings = {
"org/gnome/desktop/input-sources" = {
sources = [(lib.gvariant.mkTuple ["xkb" "jp"])];
};
};
}
];
};
##フォントの設定
日本語記事の通りにする。fonts.fontDir.enable = true;
は Flatpak が正しく動くために必要らしい:https://nixos.wiki/wiki/Fonts
##ZSH のコマンド履歴が再起動で消えないようにする
ZSH の設定をする。shellInit
を使えば好きな .zshrc
を作れるので、ここに bindkey '^R' history-incremental-search-backward
と書いておく。
##NVIDIA driver などのハードウェアの設定
https://nixos.wiki/wiki/Nvidia とかを見ながら設定するのがよいが、実は https://github.com/NixOS/nixos-hardware を使えば必要な設定を勝手にやってくれる説がある。導入だけして、必要なものを後から入れることにするのがよさそう。
##/nix/store を最適化する・GC を有効化する
設定は普通にできる。手動で GC を動かす場合は nix-store --gc
を打つ。
##Git repo が dirty でもビルドさせる
Git repo を作った状態で commit せずに nixos-rebuild switch
しようとすると error: path '...' does not exist
とか言われて死んでしまう。
git add . && git commit -m wip
したら大丈夫だった。
あるいは sudo nixos-rebuild switch --flake path:.#anise
すればよかった。
##Rootless Docker を入れる
virtualisation.docker.*
をいい感じに設定する:https://wiki.nixos.org/wiki/Docker
#home-manager を使う
user environment を扱うためのシステムらしい。
ドキュメント:
- https://nix-community.github.io/home-manager/
- https://nix-community.github.io/home-manager/options.xhtml
manual に書いてあるインストール方法と日本語解説記事のインストール方法が派手に違う(homeConfigurations
が無い)が、とりあえず manual 側にそろえる。
user の権限で nixpkg をインストールできて便利という話っぽいが、真に便利なのはたぶん programs.*
で、rofi などがインストールできる。あと programs.zsh.*
とかもいろいろある。微妙に configuration.nix とは名前が違うのでだるい。
##configuration.nix との重複
configuration.nix と home-manager の双方で設定できる項目がいくつかあり、お互いに排他だったり相補的だったり、どっちかが動かなかったりするのでややこしい。例えば:
-
programs.firefox.enable
はどちらに書いても Firefox はインストールされるが、home-manager 側に書くと desktop session file を作ってくれないので configuration.nix に書くのがよさそう。 -
programs.zsh.enable
は configuration.nix に書かないとusers.users.anqou.shell
が設定できなくて詰むし、home-manager 側にも書かないと autocd とかが使えなくて不便なので両方に書く必要がありそう。 -
configuration.nix の
programs.dconf.*
と等価なことを home-manager のdconf.*
でもできそうだが、上でやったキーボード設定は home-manager では動かなかった。前者しか効果がなさそう。 - Hyperland も両方に設定があり、両方有効にするのがよさそうな雰囲気が出ている。https://wiki.hyprland.org/Nix/
#Nix の Wiki
なんか知らんけど二つある:
歴史的経緯らしい:https://nixos.wiki/wiki/NixOS_Wiki:History
#ホームディレクトリ配下のフォルダ名を英語にする
いつもの
LANG=C xdg-user-dirs-gtk-update
#Tilix の設定を宣言的に管理する
以下のようにするとショートカットを設定できる。
"com/gexperts/Tilix/keybindings" = {
app-new-session = "F2";
session-switch-to-terminal-down = "<Shift>Down";
session-switch-to-terminal-left = "<Shift>Left";
session-switch-to-terminal-right = "<Shift>Right";
session-switch-to-terminal-up = "<Shift>Up";
win-switch-to-previous-session = "F3";
win-switch-to-next-session = "F4";
session-add-down = "<Shift>F2";
session-add-right = "<Primary>F2";
terminal-copy = "<Primary><Alt>c";
terminal-paste = "<Primary><Alt>v";
};
#Thunderbird のプロファイルを宣言的に設定しない
home-manager を使うと thunderbird のプロファイルを宣言的に設定できる:
programs = {
thunderbird = {
enable = true;
profiles = {
main = {
isDefault = true;
};
};
};
};
accounts.email.accounts = {
"[email protected]" = {
primary = true;
realName = "Ushitora Anqou";
thunderbird.enable = true;
address = "[email protected]";
userName = "[email protected]";
flavor = "gmail.com";
};
};
が、結局 Thunderbird を起動すると GMail のパスワード設定を求められるので不便。結局データは ~/.thunderbird
に入るのでこれをコピー&ペーストすればいい。ということで上のやつは使わない。home-manager で programs.thunderbird.enable = true
すると programs.thunderbird.profiles
も設定しないと怒られるので、configuration.nix で programs.thunderbird.enable = true
する。
#homeConfigurations
がなくてもいいのか
homeConfigurations
を使って設定する解説記事ばかりの中、マニュアルには書いてなかったので使っていなかったが、今のところ普通に動いている。どうも standalone setup で home-manager switch
するときに使う設定項目っぽい。
https://apribase.net/2024/07/14/home-manager-module/ とかが参考になりそう?
#Cica
nixpkgs に Cica はないが、Ricty の nixpkg の記述を参考に以下のようにすればインストールできた。意外と Nixpkg は簡単に作れる。
fonts = {
packages = with pkgs; [
# ...
# Cica
# cf. https://github.com/NixOS/nixpkgs/blob/nixos-24.05/pkgs/data/fonts/ricty/default.nix
(stdenv.mkDerivation rec {
pname = "cica";
version = "5.0.3";
src = fetchurl {
url = "https://github.com/miiton/Cica/releases/download/v${version}/Cica_v${version}.zip";
sha256 = "cbd1bcf1f3fd1ddbffe444369c76e42529add8538b25aeb75ab682d398b0506f";
};
nativeBuildInputs = [ unzip ];
unpackPhase = "unzip $src";
installPhase = "install -m644 --target $out/share/fonts/truetype/cica -D Cica-*.ttf";
})
];
#実機に NixOS をいれる
##GRUB で正しく起動する
入れるのはすぐだったが、その後 GRUB で起動させるまでが大変だった。どうやら boot に失敗していたようで、なにを apply しても再起動すると巻き戻ってしまう状態だった。以下のように設定してうまく行った。まず configuration.nix
:
# Bootloader.
boot.loader = {
grub = {
enable = true;
device = "nodev";
useOSProber = true;
efiSupport = true;
};
efi = {
canTouchEfiVariables = true;
efiSysMountPoint = "/boot/efi";
};
};
続いて hardware-configuration.nix
:
fileSystems."/boot/efi" =
{ device = "...";
fsType = "vfat";
options = [ "fmask=0077" "dmask=0077" ];
};
以上の設定は https://nixos.wiki/wiki/Bootloader#Keeping_kernels/initrd_on_the_main_partition に書いてあった。正直この説明を読んでも、これを適用すべきなのかどうかはさっぱりわからなかったが、やったら動いた。
##/omion にマウントして必要なファイルを ~/ に配置する
システムディスクとは異なる btrfs のディスクを /omion
というパスにマウントする。まず hardoware-configuration.nix
を書き換えて /omion
にディスクをマウントする。
fileSystems."/omion" =
{ device = "/dev/disk/by-uuid/...";
fsType = "btrfs";
options = [ "subvol=omion" ];
};
続いて /omion
配下のディレクトリをホームディレクトリ配下へシンボリックリンクを張る。 普通に絶対パスを書くとエラーになるので mkOutOfStoreSymlink を使う:https://github.com/nix-community/home-manager/pull/1211
file = {
".hoge" = {
target = ".hoge";
source = config.lib.file.mkOutOfStoreSymlink /omion/hoge;
};
};
##クリップボードを有効化する
wl-clipboard を入れる。
##formatter を有効化する
https://nix.dev/manual/nix/2.17/command-ref/new-cli/nix3-fmt を見ながら以下を設定した:
# flake.nix
{
outputs = { nixpkgs, self }: {
formatter.x86_64-linux = nixpkgs.legacyPackages.x86_64-linux.alejandra;
};
}
nix fmt
でフォーマットできる。
##GDM の auto suspend を無効化する
デフォルト設定では GDM の auto suspend が有効化されているため、WoL で起動して SSH で接続していると、いきなり SSH が切れる(1 敗)。
無効化する:
services.xserver.displayManager.gdm = {
enable = true;
autoSuspend = false;
};
#現在動いているもの
現在使われているファイル群は /usr/share
とかを探しに行っても存在しないが、以下にある:/run/current-system/sw/
home-manager で入れたものは以下にある:/etc/profiles/per-user/anqou/
実態はシンボリックリンクになっている。
#書き捨てのシェルスクリプト
/usr/bin/bash
とかが無いので shebang が普通には書けない。https://zenn.dev/natsukium/scraps/d260e091cb8fdc とかを参考に、以下のように書くと動く:
#!/usr/bin/env nix-shell
#! nix-shell -i bash --pure
#! nix-shell -p bash
## その他に必要なものがあったら↑に書く。
# ここに Bash スクリプト
#ローカルでカスタムのパッケージをビルド
unstable にもまだ入っていない Hyprland の最新版を使いたかったので、手元でビルドする。まず nixpkgs からソースを探す。https://search.nixos.org/packages から探して “Source” からリンクを飛ぶと見つかる。Hyprland の場合は https://github.com/NixOS/nixpkgs/blob/nixos-unstable/pkgs/by-name/hy/hyprland/package.nix にある。これをローカルにコピーする。
続いて version
の値を最新版に合わせ、fetchFromGitHub
の中身を修正する。再現性を担保するために SHA256 ハッシュを計算する必要があるが、これには nix-prefetch-git
コマンドが使える。以下のように使う:
nix-prefetch-git --rev v0.46.2 https://github.com/hyprwm/Hyprland
続いてこの package.nix
を configuration.nix
から使うように設定する。これには pkgs.callPackage
を使う。Hyprland の場合 stdenv
をいい感じに設定する必要があることが nixpkgs の all-packages.nix
を見るとわかるので、これを考慮して以下のようにする:
hyprland = {
# ...
package = pkgs.callPackage ./hyprland/package.nix {
stdenv = gcc14Stdenv;
};
# ...
};
1 ヶ月半くらい NixOS を使った感想
configuration.nix
経由で様々なソフトウェアを宣言的に管理できるのがかなり体験として良い。普通の(Ubuntu や Arch Linux などの)distro だと apt
とか pacman
とかを使ってソフトウェアをインストールし、Wiki を見ながら /etc/
配下の設定ファイルをいい感じにいじって、とかする必要があるところ、NixOS だと configuration.nix
で hoge.enable = true
みたいにすればインストールや設定ファイルの配置が行われ、設定を変更する際も
hoge.settings.foo = "bar"
みたいに予め用意された「つまみ」を configuration.nix
から変更すれば済む。どういう設定のツマミがあるかも https://search.nixos.org/options や https://home-manager-options.extranix.com を見れば一覧で表示されるため分かりやすい。インターネット上の NixOS の情報量は Arch Wiki の情報量の多さと比べると少ないが、このオプションの一覧表示のおかげであまり気にならない。
一方で ad hoc かつ一時的にシステムの設定ファイルを書き換えることは残念ながらやりにくい。実際に遭遇した例でいうと、自動的に Minikube を起動して minikube ip
を叩いて出てきた IP アドレスを自動的に /etc/hosts
に設定するスクリプトは /etc/hosts
が NixOS によって read only に設定されてしまったため動かなくなった。仕方がないので IP アドレスを設定するところだけマニュアルで configuration.nix
を書き換えるフローに変更した。また Hyprland や Neovim の設定ファイルなども Nix の式として組み込むことができるようになっているが、これをやると Hyprland・Neovim の設定を挙動を見ながらちょっとずつ書き換えていこうにも、書き換えるたびに nixos-rebuild
を打つ必要があり面倒である。仕方ないのでこれらの設定ファイルを Nix に寄せるのは諦めた。
その他、シェルスクリプトがそのまま動かなかったり、aqua や opam といった他のパッケージマネージャと相性が悪かったりと細かい不具合は色々あるが、都度 NixOS 向けに書き換えていけばいいのであまり大きな問題にはなっていない。特に OCaml に関しては opam2nix という素晴らしいツールがあるので、これを使って脱 opam を始めている。最近自分が管理している OCaml のコードに flake.nix
ファイルが commit されつつあるのはそういう理由である。
Nix の文法や意味論は、慣れるまで少し大変(特に list と attribute set のセパレータの区別とか)だが、そこまで難しかったり奇妙だったりするようには見えない。ただしこれは自分が OCaml などの関数型プログラミング言語のパラダイムに慣れているからかもしれない。
nixpkgs は主要な distro の中で最多のパッケージを誇ると様々なところで喧伝されているように、必要なソフトウェアやその他のものはおおよそ揃うように思える。揃わない場合でも、 Nix を使って手元でソフトウェアをビルドすることは容易にできる。 Arch Linux を使っていた頃は PKGBUILD ファイルを一度も手で書いたことはなかったのだが、 NixOS では Nix を使わないとソフトウェアのビルドが面倒そうなので、自然と Nix のファイルを書いて手元でビルドするようになった。一般的な Autotools や CMake を使うビルドのほか、cargo や Go のビルドを簡単に行うためのフレームワークが Nix 側から提供されているので、見た目ほど難しくはなさそう。ただし nixpkgs に収容されているパッケージの中にはどのようにビルドされているのかが Nix のファイルを読んでもわからないものが多数あるので、このあたりはまだ修練が必要そう。
という感じで、色々細かい問題はあるものの、概ね問題なく NixOS を使えている。しばらくはこの環境をメインで使っていくつもり。