Open15

ArchLinuxからNixOSに環境を移行する+移行後のつまづいたポイント達

turttonturtton

追記

NixOSへの移行はここで完了していますが、引き続きNix環境でつまづいたポイントをここに書き溜めていく方針です。よってここはクローズされることはありません。
全体の記事化も検討しましたが、1つ1つの内容は独立しながらもゆるやかに繋がっているため、おそらくこのままスクラップであり続けると思います。


最近の更新でKDE Plasmaが5→6になった影響で様々なものが壊れた。X11環境特有っぽいバグも見られるのでストレスがマッハ(画面上にウィンドウレベルのアニメーションが入るとフレームレートが一時的にガタ落ちして作業にならない)
戻すのも面倒なので前から気になってたNixOSに移行して再現率100%の環境を作る

事前に見てた記事

まずはVM上で環境を作る
https://github.com/turtton/dotnix

Hidden comment
Hidden comment
Hidden comment
turttonturtton

IntelliJ製品の導入

この一見単純なことで盛大に沼った。ので解決までの道程を書く
とりあえず基本的なことはwikiの通りやれば良い
https://nixos.wiki/wiki/Jetbrains_Tools
一部pluginをbuildinで導入できるので入れられるやつは入れておくとお得。対応してるリストはこれ。現時点では少ないけど、copilotみたいな一部パッチが必要なものを自動でやってくれるのでうれしい。AndroidStudioはaddPluginできないっぽいのでそこだけ残念(普通にCopilot導入したら動いたのでヨシッ)

JetbrainsToolBoxも入れてみたけどまあ普通に動く。一応nix-ldの設定とnix-ld-rsも入れた。こいつのせいかは知らないけどlinuxのzenカーネルだと意味わからんもんをビルドしようとした挙句失敗するのでノーマルのカーネルかxanmodとかにしておくと良い

Failed to locate library: libGL.so

普段MinecraftのMOD開発をするのだが、IDEAからマイクラのクライアントが起動できないことに気付いた
同様の問題がdiscourseにもあったけど、解決方法は記載無し(最終的にはnix-ldも使えないことは無いけど微妙だった)
https://discourse.nixos.org/t/issues-with-opengl-in-minecraft-development-environments/37532/5

調査した結果、lwjglがLD_LIBRARY_PATH経由でlibGLを捜索するのが原因っぽい。ld.so経由してくれたらnix-ldが動作したのになんなんだよお前
とりあえずideaの起動時にLD_LIBRARY_PATHに必要な依存関係のパスを渡そうと色々やった
試行錯誤した順番で紹介(一番良かったやつは最後)

1. スクリプトでラップする

参考

idea = (pkgs.writeShellScriptBin "idea-ultimate" ''
  export LD_LIBRARY_PATH=$NIX_LD_LIBRARY_PATH
  exec ${patched-idea}/bin/idea-ultimate "$@"
  '');

とか
Githubで検索してヒットしたこれ

requiredLibPath = with pkgs; lib.makeLibraryPath [
    libGL
    udev
  ];
idea = pkgs.runCommand "intellij" {nativeBuildInputs = [pkgs.makeWrapper];} ''
  mkdir -p $out/bin
  makeWrapper ${patched-idea}/bin/idea-ultimate $out/bin/intellij --prefix LD_LIBRARY_PATH : ${requiredLibPath}
  '';

コンソールからしか起動できないので微妙

2. overrideAttrsでpostInstallを書き換える

意味なかった。謎

3. pkgs.symlinkJoinでラップ

これこれ
みて書いた。ちゃんとKRunnerから呼べたので満足
ファイル
https://github.com/turtton/dotnix/blob/04917ac23809681076f4a1a9f9cf5bf21fb02359/home-manager/gui/shared/idea.nix

これに辿り付くまでに5時間ぐらい持ってかれた。その代わりld.soとかnixについて深く知れたのとgithubの上にある検索バーが最強って分かったので良いことにする

turttonturtton

neovimを設定する

昔から使ってたこの設定達をnixに移植しつつ、もっと小さい環境を作ろうとした
https://github.com/turtton/dotfiles/tree/a5d67c0bfaf95f90af5cc6bedef363ef36a23e94/dot_config/nvim

ここ数年neovimだったりlunarvimだったりを使った感想として、自分にとってvimはgitのコミットメッセージをコマンドラインから書くときと、書き込みにsuper user権限が必要なファイルを弄る時だけ必要なツールなので、基本設定+skkぐらいに抑えた

ぶっちゃけhome-managerの設定が最強だったので特に言うことないけど、ソースコード見ないと気付かなかったことがちょくちょくあったので書く

programs.neovim.pluginsの書き方について

例では

with pkgs.vimPlugins; [
    yankring
     vim-nix
    { plugin = vim-startify;
      config = "let g:startify_change_to_vcs_root = 0";
    }
]

しか書かれてないけど、実はAttribute Setの時は便利なオプションが他にもある

  • type
    上の例でもあるconfigで記述している言語を指定できる。デフォルトはvimlだが、luaとかtealfennelが指定できる。使用例
  • optional
    trueにするとneovim内で:packaddしない限りロードされない設定になる。条件によっては有効化したくないプラグインがあればここに式をつっこむだけで良いので便利そう。自分は使う場面がなかった
  • runtime
    .config/neovim/内に実際に配置したい設定を記載できる。conifgの場合はinit.luaまたはそこからリンクされたinit.vimの中に記載されるので、例みたく
    { "ftplugin/c.vim".text = "setlocal omnifunc=v:lua.vim.lsp.omnifunc"; }
    
    って感じでneovimの機能を活かした設定ができる

それぞれの詳細は以下のオプションを参照
https://github.com/nix-community/home-manager/blob/2f0db7d418e781354d8a3c50e611e3b1cd413087/modules/programs/neovim.nix#L17

ここまで書いたけどtype以外は今回使わなかった。
とりあえずgithubから指定したプラグインはcommitのrevisionまで指定できたので、当分壊れることは無いだろうって思えるのが嬉しい。

超地味なTipsだけど、programs.neovim.extraLuaConfigの先頭に改行を入れておかないと

init.lua
vim.cmd [[source /nix/store/path-to-init.vim]]require'cmp'.setup {

みたいな感じで間に改行が入らないので注意。上で紹介したpluginsの設定でtype="lua"なものがあるときも同じことが起きるので、とりあえず\nを入れておくと安心かも
https://github.com/turtton/dotnix/blob/f15df01c9a2999e2b190fd8e89d8a1dc3aacd399/home-manager/cli/shared/nvim/default.nix#L15-L16

init.lua
vim.cmd [[source /nix/store/path-to-init.vim]]
#ここでちゃんと改行されるようになる
require'cmp'.setup {

https://github.com/turtton/dotnix/commit/f15df01c9a2999e2b190fd8e89d8a1dc3aacd399

turttonturtton

wallpaper-engine-kde-pluginの導入

今回の移行の動機であり破壊の原因でもあるKDEに自分が拘る原因の8割はこいつにある
Linux環境でありながらWallpaperEngineの壁紙がそのまま使える神プラグイン。これが入らないことにはお話にならない。
単なるPluginならKDEから入れて終わりだが、こいつは専用のlibが存在し、自分でビルドするしかない。ということでNixの仕組みを経由して構築してみる
文章としての情報はゼロに等しかったが、githubで検索したら割とヒットした。ありがとう先駆者

その中でも自分のやりたいことに近かったこれを参考に作成した
https://github.com/turtton/dotnix/commit/b5d7e9ae57273fe8db18fa78fc42ee4d52005eb7

無事にビルドできたものの、Pythonのwebsocketsライブラリが無いよって怒られた。
試行錯誤を続けた結果、home-manager側で設定してたpython312を消したら解決した。試行錯誤で3時間以上持ってかれたふざけんな
最終的にはこう
https://github.com/turtton/dotnix/blob/main/os/wm/plasma5.nix

一応関連スレッドにも投下しておいておいた
https://discourse.nixos.org/t/wallpaper-engine-on-nixos-wallpaper-engine-kde-plugin/19744/18?u=turtton

追記

上記の設定はまだ完璧じゃないことが後に分かった
どうやら手動でインストールしたプラグインとうまいこと噛み合って動作していたらしく。クリーンな環境で再度導入するとno_pyext_file_foundというエラーが出てpython3が無い扱いになった。
再度調査をしたところ、手動でインストールした際には存在していた~/.local/share/plasma/wallpapers/com.github.casout.wallpaperEngineKdeが消えていることに気付いた。そしてこの中のcontents/pyext.pyってファイルを読み込もうとして失敗したのだと思われる。
どうやらNixは/run/current-system/sw/share/plasma/wallpapers/com.github.casout.wallpaperEngineKdeを作成しており、これをKDEは認識できてないっぽい。良い方法が思い浮ばなかったのでとりあえずスクリプトでごり押すことにした
https://github.com/turtton/dotnix/commit/7c56589e9fce254e3e674f8470c9efcaa61cfd0c
上で貼ったdiscourseでもこの件について話してたけど、まあ悪くない手段なんじゃねって言われたのでこれでヨシッ

turttonturtton

nixpkgsの既存パッケージを書き換える

Steam内の表示で日本語が文字化けしていたので色々調べたら、使ってるNoto fontsが可変フォント(variable fonts )?ってやつだかららしい
https://github.com/NixOS/nixpkgs/issues/178121
これを修正するPRがあったんだけど、Steam以外ではバグらないってのでCloseされちゃってる
https://github.com/NixOS/nixpkgs/pull/205641

ってことでこの変更を自分の環境で適用する必要がありそう。
変更内容自体に関しては毎度毎度参考にさせていただいているdotfilesに丁度修正されたNoto fontのパッケージが書かれてたのでこれを参考に書く
https://github.com/asa1984/dotfiles/blob/e190adb157c4c7f14499ee6663e343f800593846/pkgs/default.nix
ついでにpkgsにはオーバーレイって機能があるっぽいのでこれで既存のnoto-fonts-cjk-sansとかを書き換えてみる
inputs.home-manager.lib.homeManagerConfigurationinputs.nixpkgs.lib.nixosSystemにはnixpkgs.overlaysって同じ名前のフィールドがあるらしく、そこに関数を渡してあげれば良いだけっぽい
https://nixos-and-flakes.thiscute.world/nixpkgs/overlays#overlays
ってことで差分はこんな感じ
https://github.com/turtton/dotnix/commit/b222ca22efce65e2e1c76f88e96455a765b3e631
多分ちゃんと適用されてると思う...んだけど、Steamの表記は直らなかった
fc-listから確認したけどちゃんと名前にVFが付いてないので成功はしてるはず

これ以上情報も無ければやれることも無いので放置。前からずっと英語設定で使ってたので自分の名前以外は読めるから良しとする。ちなみにwqy_zenheiを入れたりしても意味なかった

turttonturtton

Plasma6に挑戦

結論:ダメ

数日前にも試して、その時はWayland環境だとログインしてsddmから抜けたらsystemdのlogだけ出てplasma(kwin?)が起動しなかった。6にするならWaylandにしたいので一旦Plasma5で進めてたんだけどもう一度トライ
とりあえずwallpaper-engine-kde-pluginをqt6ブランチに変更してビルドしようとしたけど、Qt6が無いと言われて怒られ続けたので諦め。今回は先駆者も居ないっぽいので撤退
依存関係を参考にすべくAURを眺めながらやったんだけど、全部用意してもダメって言われたのでなんもわからん。もうちょい知見が溜まってから再チャレンジするとしよう(その前にHyprlandになってる可能性もある)

同様の理由でこっちも見送った(途中まで書いたので依存関係がどうにかなったらすぐ入れられるはず)
https://github.com/moodyhunter/applet-window-buttons6

turttonturtton

実機に導入する

ここまで丁寧に作り上げてきたnixファイル達を以てしてもイレギュラーは発生する
USBからのインストール作業を終えて準備しておいたファイルにhardware-configuration.nixだけ移動させて、いざ

sudo nixos-rebuild switch --flake .#maindesk

と意気揚々にコマンドを実行した矢先に問題が発生した。Nvidia のPRIME機能が有効だからIBusを指定しろだのなんだの...なんですかそれは?
がんばってスマホで調べたところ、どうやらラップトップ向けにそういう設定があるらしい
そんなのミリも触ってないので困惑していたら、どうやらこいつのせいだったみたい
https://github.com/turtton/dotnix/blob/5732bdbc9359c0f795aadca0655ca601c6364452/hosts/maindesk/nixos.nix#L21
わからん設定をわからんまま放り込むのはやめた方が良い(戒め
ちゃんとこれのソースコード見たら有効化されてました
https://github.com/NixOS/nixos-hardware/blob/master/common/gpu/nvidia/prime.nix
設定内容がぜんせんCommonじゃないというつっこみをしつつ、こいつの設定を消してついでにnvidiaの関連設定を行った。
https://github.com/turtton/dotnix/commit/051f513bd5c058380df9c9e2119af78263ce178d#diff-f1f0657b7ef8f043dba0b770578feef7ac201b1f30e4d0212f914711b7b73823
ほぼ環境を再現することができた(このあとアイコンとか直した
https://kameuo.turtton.net/notes/9qwd40unlf94ytgo

turttonturtton

セキュアブートを有効にする

Nixはどうやらlanzabooteってやつを使ってセキュアブートをやるのがメジャー(というかサポートされている唯一の方法?)らしい。実際今まで見てきたdotfileにもこいつがいた気がする。
とりあえずマニュアルの通りにやってみたが、マザボからSecureBootを有効にするとsystemd-bootが起動しなくなるという問題にぶつかり、まだまだ発展途上なこともあって同じような症状の報告や有力な情報は発見できなかった。そもそもドキュメントにあったSetup Modeとやらを自身のマザボの設定から見つけることができなかったので、自分で生成した鍵を使って署名するってことが想定されていない可能性がある。

PreLoaderを使う方法の開拓

そもそもセキュアブートをやりたい動機として、セキュリティ面での意識の高さなどはなく、単に普段デュアルブートしたWindowsで遊ぶゲームにひっついてるマルウェアのご機嫌を取るために毎回マザボの設定を切り替えるのが面倒なだけなので、ArchLinux時代お世話になったPreLoaderをNixでも使ってみようと思う。
とりあえず先駆者が居ないか探したのだが、おもしろいことに検索にはヒットせず。Githubでもまさかの0だった(執筆時に検索し直したら自分だけ出てきて草)。ただやることに関してはArchLinuxと変わらんはずので、ArchWikiと睨めっこしながらnix式での再現を目指した。このタイミングでAURのPKGBUILDを読んでみたが、これぐらいシンプルなものなら読めたしそのままnix式に落とし込めるようになった。途中複数のソースを含めよう[1]としたり、圧縮されてないファイルを処理するときのnix式の書き方[2][3]を模索して時間を溶かしたが、0からの構築に成功した。1週間前はNix言語なんもわからん状態だったことを考えると成長を感じれてうれしい。
https://github.com/turtton/dotnix/blob/e8eff0f768b390ee230aeb559143bcc4858920b9/os/core/secureboot/preloader.nix#L7-L24
あとはArchWikiの通りにフォールバックの設定までをNix式に落し込んで完了。実際にセキュアブート環境下でPreLoaderが動作してハッシュの登録までできるようになった。
唯一の問題として、普通にsudo nixos-rebuild switch(or boot) --falke ...したら以下のエラーが出て処理に失敗するようになった

Traceback (most recent call last):
  File "/nix/store/0ky2fq2qv0qbgnaqfmc3mc0pb5vcpdnn-systemd-boot/bin/systemd-boot-builder", line 394, in <module>
    main()
  File "/nix/store/0ky2fq2qv0qbgnaqfmc3mc0pb5vcpdnn-systemd-boot/bin/systemd-boot-builder", line 377, in main
    install_bootloader(args)
  File "/nix/store/0ky2fq2qv0qbgnaqfmc3mc0pb5vcpdnn-systemd-boot/bin/systemd-boot-builder", line 305, in install_bootloader
    raise Exception("could not find any previously installed systemd-boot")
Exception: could not find any previously installed systemd-boot

エラー内容的に前回のsystemd-bootの状態を探そうとして、改変されてるから失敗したって感じかな?ぶっちゃけ根本的な原因は分かってない。とりあえず問題の箇所はここだった
https://github.com/NixOS/nixpkgs/blob/3b48b3aaa9f53eefd61c334ece1a08b20f1a2e0c/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py#L304-L305
このチェック無視できるようにパッチが当てられたらいいのにって書こうとしたらやり方があったのでやってみる。
ってことで作成したパッチがこれ
https://github.com/turtton/nixpkgs/commit/c0f29cee5621026857062faad73ffbf74b70c0f4
これを作成するにあたってエラーの根本的な原因を調査したところ、どうやらbootctl statusで出力される情報からsystemd-bootのバージョンを抽出する正規表現が単一のefiファイルしかない時のみを想定されていたせいであった。
つまりは

          ESP: /boot (/dev/disk/by-partuuid/9b39b4c4-c48b-4ebf-bfea-a56b2395b7e0)
         File: └─/EFI/systemd/systemd-bootx64.efi (systemd-boot 255.2)

ってのが想定されていたところが、自分の環境では

         File: ├─/EFI/systemd/HashTool.efi
               ├─/EFI/systemd/PreLoader.efi
               ├─/EFI/systemd/systemd-bootx64.efi (systemd-boot 255.2)
               ├─/EFI/systemd/loader.efi (systemd-boot 255.2)
               └─/EFI/BOOT/BOOTx64.EFI

みたいな感じになっており、3番目と4番目にバージョンが記載されている。これのせいで精査が失敗していたみたい。
作成したパッチを自身に適用して従来のエラーが出ないことを確認。ってことでPreLoaderを使った完璧なセキュアブート環境が用意できた
https://github.com/turtton/dotnix/compare/e1031fc547e08fc9d5a3d7dd62be56d35dbc48ce...a40b27232011435a0b8e60baa8d0af169f97e3f0

今回作成したパッチはできるなら本流にPR送りたいけど、コメント的にあの正規表現は生成されたやつっぽいので、やるなら日を改めて大元の処理を直すところからやろうと思う。ってかなんならissue作るところからやるべきかも?なんて名前で出しゃええんや。英語なんもわからん
とりあえずissue投下した。伝わるといいな
https://github.com/NixOS/nixpkgs/issues/296563

脚注
  1. https://discourse.nixos.org/t/how-to-create-package-with-multiple-sources/9308/3 ↩︎

  2. https://stackoverflow.com/questions/57225745/how-to-disable-unpack-phase-to-prevent-error-do-not-know-how-to-unpack-source-a ↩︎

  3. https://discourse.nixos.org/t/how-to-install-github-released-binary/1328/5?u=turtton ↩︎

turttonturtton

rust-roverを動かす

適当なプロジェクト読み込んだら普通に怒られたので、こいつを動かすためのflake.nix作りをやった

試行錯誤の途中で見かけたプロジェクト達

ちなみに全部rust-roverにとっては無意味だった。いらない子だね

動作を理解する

そもそもの話として、rust-roverはrustupと密接に連携しており、こいつがあること前提な動き方をする。
ただ、今まで見てきた記事はNixの思想的にrustupを導入することをおすすめしない人ばっかりだったので自分もその気だった。が、こいつを動かすために必要なのはnixの思想ではなくrustupのエコシステムである。
ってことでまず自身の環境からrust-overlayを消してrustupを入れた
https://github.com/turtton/dotnix/commit/dd52502832c8cc0f492c2a44e8ed753c976eef32

これで8割は動いた。後はプロジェクトに応じて以下のような最小限のdevelop環境を構築すればいい

{
  description = "Rust-Nix";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
    utils.url = "github:numtide/flake-utils";
  };

  outputs = { nixpkgs, flake-utils, ... }: flake-utils.lib.eachDefaultSystem (system: 
  let
    pkgs = import nixpkgs {
      inherit system;
    };
   in with pkgs; rec {
    devShells.default = mkShell {
     nativeBuildInputs = [ pkg-config ];
     buildInputs = [ openssl ];
    };
  });
}

まあぶっちゃけこのレベルなら一々ディレクトリに移動してnix developしてrust-rover .ってコマンドからやるのが面倒くさいだけなのでopensslとpkg-configを実機に入れても良い気がする。Runnerから起動したいので自分は入れておくことにした入れたけどダメだったので上で書いた方法を使う必要があるかもしれない。不便なのでそのうちどうにかしたい

turttonturtton

direnvとの連携

上記の問題はrust-roverだけでなくWebStormでも発生した。corepack経由でpnpmを動かそうとしたところ、corepack enableでのリンク作成がNixによって阻まれ、その結果WebStormがpnpmを認識できなかった。
とりあえずNixでcorepackをどのように利用すれば良いかを調べたところ、このような記事を発見した
https://zenn.dev/eiel/articles/15103684351cb8
上の記事ではnix shellを用いていたが、とりあえず似た感じでflakeに落とし込んでみた

{
  description = "pnpm-Nix";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
    utils.url = "github:numtide/flake-utils";
  };

  outputs = { nixpkgs, flake-utils, ... }: flake-utils.lib.eachDefaultSystem (system:
  let
    pkgs = import nixpkgs {
      inherit system;
    };
    # https://zenn.dev/eiel/articles/15103684351cb8
    corepack = with pkgs; stdenv.mkDerivation {
      name = "corepack";
      buildInputs = [ pkgs.nodejs-slim ];
      phases = [ "installPhase" ];
        installPhase = ''
            mkdir -p $out/bin
            corepack enable --install-directory=$out/bin
        '';
    };
   in with pkgs; rec {
    devShells.default = mkShell {
      packages = [ corepack ];
    };
  });
}

これによってnix developした環境からwebstormを起動すればとりあえず認識してくれるようになった。
ただこれだとrust-roverの二の舞である。
ってことで解決策を探したところ、どうやらdirenvで解決できるらしいってことがわかった
https://www.reddit.com/r/NixOS/comments/z8uefy/comment/iyzgbkk/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button
このタイミングでnix-direnvってリポジトリを発見し、flakeとの連携テンプレートに出会えた
https://github.com/nix-community/nix-direnv/tree/master/templates/flake
同じように.envrcを設定し、コンソール上からdirenv allowを実行して動作を確認。
WebStormにはプラグインを導入したら、ちゃんとpnpmが認識されるようになった
https://plugins.jetbrains.com/plugin/15285-direnv-integration

turttonturtton

home-managerをnixosの設定と統合する

今まではsudo nixos-rebuild switchhome-manager switchを個別に実行していたが、わざわざ二回実行するのが手間なので統合する。

余談:これでnixosのロールバック対象に含まれるようになる...?確証は無いがこれまでの手法よりは可能性がありそう

とりあえず最小限の例はここに買いてある
https://nix-community.github.io/home-manager/index.xhtml#sec-flakes-nixos-module
home-managerのmoduleを追加する方法が公式には書かれていないが、以下のように書くことで追加できる
https://github.com/pjones/plasma-manager/blob/ef0c106a2104f841a54fe4b9ec60a79775e2fe1e/examples/systemFlake/flake.nix#L45-L45

最終的な差分はこんな感じに
https://github.com/turtton/dotnix/commit/d4428a2e13c7632c939ec182231a4b7f78c255f3

気付いた不便ポイント

home-managerの設定に渡せる追加の引数がユーザー別に指定できない

これのせいでマルチユーザーを定義することができない。後に困りそうだけど今のところ環境ごとに1ユーザーしか設定してないので良しとすることに

参考:
https://github.com/kaleocheng/nix-dots/

turttonturtton

教訓:usernameをミスると詰む

users.users.${username}をインストール時に設定したものから変えるとログインできるユーザーが無くなって詰むという話
ノートPCに導入しようとしたらこれに遭遇して再度メディアからのインストールをする羽目になった

焦りすぎてFIxになってる修正コミット
https://github.com/turtton/dotnix/commit/11255fdc9eb9b5646504fd5cb48e7876c30b0a03

おそらくパスワードのハッシュまで設定に盛り込んでおけば復旧できる可能性があると思うが、変わってしまった後からはどうしようもなくなるので詰む
ちなみにロールバックも意味ない。最初期のものまで戻ってもダメだった。メディアからchrootして直そうとしたけどエラーでて再構築ができなかった。謎

今思えばrootなら入れたかもしれない。まあ後の祭り