NixOSとHyprlandで最強のLinuxデスクトップ環境を作る
このスクラップの更新を忘れていた。数ヶ月前にHypalandの環境が完成した。以下のディレクトリに設定一式がある。
Hyprland WikiのNixのセクションに従ってNixOS moduleとしてHyprlandを導入した。ただし、hyprland.conf
の設定はhome-managerのモジュールから行っている。前はhome-managerのhome.file
を使ってhyprland.conf
テキストを配置していたが、今回はwayland.windowManager.hyprland
を使って全てNix言語で書いた。カラースキーマをNix言語で管理しているのでこっちを使っている。
マルチディスプレイ時のHyprlandのワークスペースの挙動がキモかったので、hyprsomeというワークスペースをAwesome-likeにするツールを導入した。
また、hypr-helper
というヘルパーツールをRustで自分で実装した。次の機能を持つ。
- ウィンドウが1つだけのときはフルスクリーン化
- Hyprlandのmovefocusをマルチディスプレイ用にいい感じにした
- フルスクリーン時: モニターフォーカスの切り替え
- 非フルスクリーン時: ウィンドウフォーカスの切り替え
hyprland-rs
というHyprlandとIPC通信するクレートを使っている(hyprsomeでも使われている)。Rustの型のおかげで、Hyprlandの勝手さえ分かっていればクレートのドキュメントを読まずともなんとなく使えるので便利。シェルスクリプトとかいう狂気の代物を書かなくて済んだ。
今のところIMEは問題ない。しかし、フルHDとWQHDの2つのディスプレイの内、WQHDの方が一日に数回不具合を起こす。画面全体の内、左上からフルHDサイズの領域までは問題ないが、その外側の画面更新が止まる。そういう時はウィンドウを作成&削除してやると正常な状態に戻る。そこまで大きな問題ではないが、うざい。
目的
- 関数型LinuxディストリビューションNixOSとWaylandコンポジターHyprlandを主軸にLinuxデスクトップ環境を作る
- 過程で得た知見、ぶつかった問題とその対処など、なんでもメモしていく
- NixOSはいいぞ
- Hyprlandカッコいいぞ
NixOS
- 関数型Linuxディストリビューション
- 再現可能、宣言的、信頼性を謳っている
- Nixという関数型パッケージマネージャをシステムのベースにしている
- Nix言語によってシステム設定を記述する
Hyprland
- モダンなタイル型Waylandコンポジター
- デフォルト設定がぬるぬる動いて既にカッコいい
- ウィンドウアニメーション、ブラー、透過などを自前で搭載している
- ダイナミックタイリングというものを採用しており、ウィンドウレイアウトが柔軟
- 設定はhyprland.confに独自の設定記法で記述
dotfiles
- 今回作っていくdotfilesはこちら!
- 結構な頻度で大改修が入るので注意
NixOS modules
- NixOSの特徴的機能
- システム設定を宣言的に記述する仕組み
- 場所は
/etc/nixos/configuration.nix
設定の例
{ pkgs, ... }: {
# ハードウェア
# デバイスに合わせてインストール時に自動生成される
# ドライバやファイルシステムについて記述している
imports = [ ./hardware-configuration.nix ];
# ブートローダー
boot.loader = {
systemd-boot.enable = true;
efi.canTouchEfiVariables = true;
efiSysMountPoint = "/boot/efi";
};
# カーネル
boot.kernelPackages = pkgs.linuxPackages_latest;
# タイムゾーン
time.timeZone = "Asia/Tokyo";
# ロケール
i18n.defaultLocale = "ja_JP.UTF-8";
# ネットワーク有効化
networking.networkmanager.enable = true;
# サウンド
sound.enable = true;
hardware.pulseaudio.enable = true;
# ユーザー(user1は名前の例)
users.users.user1 = {
isNormalUser = true;
shell = pkgs.zsh;
extraGroups = [ "networkmanager" "wheel" "audio" "video" ];
};
# システムに導入するパッケージ
environment = {
shells = [ pkgs.zsh ];
systemPackages = with pkgs; [
zsh
git
neovim
];
};
# サービス
services = {
openssh.enable = true;
};
# デスクトップ環境
services.xserver = {
enable = true;
displayManager.gdm.enable = true;
desktopManager.gnome.enable = true;
};
# フォント
fonts.fonts = with pkgs; [
noto-fonts
];
#~~~その他必要な設定~~~#
# ...
}
設定可能なオプションの検索
Generations
-
sudo nixos-rebuild
で変更が反映された新しい世代が生成される -
reboot
するとブートローダーに新しい項目が追加されている - この仕組みにより、万が一設定の変更によって致命的な不具合が発生してもロールバックできる
Summary
- あらゆるシステム設定を1つのコードで宣言的に記述可能
-
sudo nixos-rebuild
後、reboot
して設定を反映 - 世代機能によりいつでもシステムをロールバック可能
home-manager
- 一言で言えばユーザー環境版NixOS modules
- ユーザー環境にインストールするパッケージとdotfilesを管理する
- インストールしたいパッケージを宣言的に記述できる
-
.config/
に用意するような設定ファイル群をまとめて記述できる - コマンド一発環境構築ができる
- NixOS以外のLinuxディストリビューションやMacにも導入可能
使い方
新たにパッケージインストールしたり、アプリケーションの設定を変更したりしたい時は以下をその都度行う。少々面倒だがメリットに十分見合うコスト。
-
.config/nixpkgs/home.nix
に設定を記述 -
home-manager switch
コマンドで設定ファイルを評価 - home-managerが自動的にパッケージをインストール、シンボリックリンクで各アプリケーションの設定ファイルを配置
設定例
{ pkgs, ... }: {
# 基本設定
home = {
username = "user1";
homeDirectory = "/home/user1";
stateVersion = "22.11";
};
programs.home-manager.enable = true;
# インストールするパッケージ
home.packages = with pkgs; [
bat
exa
neofetch
];
# home-manager対応のソフトウェアはprogramsからインストール・設定可能
programs.zsh = {
enable = true;
enableCompletion = true;
enableAutosuggestions = true;
shellAliases = {
ls = "exa --icons";
};
initExtra = builtins.readFile ./config.zsh; # Nix言語以外で記述した設定ファイルも読み込める
};
}
home-managerの設定検索
NixOS modulesとの違い
NixOS modules | home-manager | |
---|---|---|
ターゲット | システム | ユーザー環境 |
パッケージのインストール先 | システム全体 | ユーザー環境 |
root操作 | 可能 | 不可能 |
対応OS | NixOS | Linux, Mac |
Summary
- 宣言的dotfiles管理ツール
Nix
- 中核的存在
- 関数型パッケージマネージャ
- Linux, Macに導入可能
- パッケージを非常に厳密に区別する
- 依存関係問題が非常に起きにくい
- NixOSはシステム全体をNixで構築している(後述)
- インストール可能なパッケージはnixpkgsというリポジトリで管理されている(パッケージの検索)
他のパッケージマネージャと何が違うのか?
一般的なインストール→実行までの流れ
- ソースコードをリポジトリからダウンロード
- ローカルでビルド
- 生成された実行ファイルを所定の位置(
bin/
など)に配置 - シェルが
$PATH
からそれらを読み取り、コマンドとして使えるようになる
Nixの流れ
- ダウンロード
- パッケージの依存関係、ソースコード、コンパイラのフラグなどをインプットにとってハッシュ値を算出
- ビルド
-
/nix/store/
に算出したハッシュ名のディレクトリを作り、生成された実行ファイルを配置
5.~/.nix-profile/bin/
に実行ファイルとのシンボリックリンクを張る - シンボリックリンクはハッシュ値ではなく普通のコマンド名なため、一般と同様のコマンドとして使えるようになる
または
- ダウンロード
- ハッシュ算出
- クラウドのキャッシュにハッシュ値を照会し、キャッシュが存在する場合はビルド済みバイナリをそのままダウンロード
Nixの根幹はシンプルで、要はハッシュ計算をしているに過ぎない。ビルド時にハッシュを算出し、生成物を/nix/store/
でハッシュ値により一意に管理する、という機能をベースに様々な機能が付加されたソフトウェアが"Nix"である。
世代機能
インストール時、/nix/var/nix/profiles/per-user/{ユーザー名}/
下に"profile"から始まる名前のシンボリックリンクが生成される。これは一般的なホームディレクトリに存在するbin/
やetc/
などを含んだディレクトリで、インストール毎に新しく生成される。"profile"が現在の~/.nix-profile
、"profile-{バージョン}-link"が過去のprofileとなっており、"profile"を切り替えることで簡単にユーザー環境をロールバックできる。
イミュータブル
Nixにおいてパッケージのアップデートを行おうとした場合、バージョンが異なればハッシュ値も変わるので、新旧が互いに全く別のパッケージとして扱われる。これは上書きが発生しないことを意味する。関数型言語は変数(メモリ上のデータ)が不変なのに対し、Nixはファイル(ストレージ上のデータ)が不変になる。
また、Nixではアンインストールを実行してもシンボリックリンクが消えるだけで、/nix/store/
下の実体ファイルは削除されない。なので特別にnix-collect-garbage
コマンドを実行しなければならない。これは使用されていない/nix/store/
下のファイルのみを削除する。
NixOSやhome-managerとの関連性
NixOS modulesはシステムの設定を自動的に生成し、必要な位置に生成されたファイルへのシンボリックリンクを張っている。nixos rebuild
を実行するたびに/nix/var/nix/profiles/
に"sytem"から始まる名前のシンボリックリンクが配置することで、Nixの世代機能を使えるようにしている。
home-managerは、本来なら手動でNixのインストールコマンドを打ったり、.config/
に設定ファイルを置いたりしなければならないところを、Nix言語で宣言的に記述・自動構築できるようにした、Nixをよりユーザー環境構築のために扱いやすくしたラッパー的存在である。
追記(2024/01/28)
現在のHyprlandを試してみたところ,特に不具合もなく結構いい感じなので,スクラップを再オープンしてもう一度頑張ってみる.
Hyprlandは素晴らしいWMだったが、やはりWayland由来の不具合が多く実用に耐えなかったので結局XMonadにした。
私が使っていたHyprlandの設定は、dotfilesのarchive-hyprlandブランチに置いている。
私が過去に使っていたHyprlandの設定は,dotfilesのarchive-hyprlandブランチに置いている.(追記2024/01/28)
また、NixとNixOSについては以下の記事にまとめた。