怠惰なHomebrewユーザーでもNixを使いたい!!
はじめに
最近巷で話題のNix。耳にする頻度がだんだん増えてきました。
何やらNixを使うとHomebrewとは違って宣言的にパッケージやmacOSの設定を管理できるらしいじゃないですか。
奥が深いらしいNixですが様々な記事を参考にしつつ怠惰な自分でもNixを使って楽にパッケージやOSの設定を管理できたので書き残しておきます。
宣言的に管理したいというモチベーションだけでNixを使用しているため本来の思想や使用用途から外れたことをしているかもしれません。ご容赦くださいmm
自分は怠惰なのでNixとは何か、Nixの使い方についての詳細は省きます!!
👆が分かっていなくても楽に管理できるのが目的なので!!
この記事を見てNixが面白いと思った方は自分でさらに奥深くへ進んでみてください。
そして自分に色々教えてください。
対象読者
- Homebrewを使っている人
- Nixについてなんとなくしか知らない人
- なんでもいいから楽にパッケージやmacOS設定を宣言的管理したい人
- dotfilesの概念を理解している人
要約
最終的なディレクトリ構成は👇のようになりました。
~/dotfiles
├─ nix
│ ├─ flake.nix # メインファイル
│ ├─ flake.lock
│ ├─ pkgs.nix # Nixpkgsに存在するCLI管理
│ └─ nix-darwin
│ ├─ config.nix # nix-darwinの管轄ファイル
│ ├─ homebrew.nix # GUI、Nixpkgsに存在しないCLI、フォント管理
│ └─ system.nix # macOSの設定管理
└─ ... # 他のdotfiles設定ファイル
各ファイルの内容は👇のアコーディオン内を参照してください。
flake.nix
{
description = "My Dotfiles.";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
nix-darwin = {
url = "github:LnL7/nix-darwin";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs =
{
self,
nixpkgs,
nix-darwin,
}:
let
system = "aarch64-darwin";
pkgsConfig = import ./pkgs.nix { inherit nixpkgs system; };
pkgs = pkgsConfig.pkgs;
in
{
packages.${system}.お好きなパッケージ名 = pkgs.buildEnv {
name = "お好きなパッケージ名";
paths = pkgsConfig.myPackages;
};
apps.${system}.update = {
type = "app";
program = toString (
pkgs.writeShellScript "update-script" ''
set -e
echo "Updating flake..."
nix flake update
echo "Updating profile..."
nix profile upgrade nix
echo "Updating nix-darwin..."
nix run nix-darwin -- switch --flake .#お好きなホスト構成名
echo "Update complete!"
''
);
};
darwinConfigurations.お好きなホスト構成名 = nix-darwin.lib.darwinSystem {
system = system;
modules = [ ./nix-darwin/config.nix ];
};
};
}
pkgs.nix
{ nixpkgs, system }:
let
pkgs = import nixpkgs {
inherit system;
config.allowUnfreePredicate =
pkg:
builtins.elem (nixpkgs.lib.getName pkg) [
"claude-code"
];
};
in
{
inherit pkgs;
myPackages = with pkgs; [
### CLI Applications
nil
nixfmt-rfc-style
fzf
bat
ripgrep
eza
fish
gh
git
just
claude-code
terminal-notifier
gemini-cli
jankyborders
mise
kubectl
];
}
nix-darwin/config.nix
{ pkgs, ... }:
{
imports = [
./system.nix
./homebrew.nix
];
}
nix-darwin/homebrew.nix
{ pkgs, ... }:
{
homebrew = {
enable = true;
onActivation = {
autoUpdate = true;
cleanup = "uninstall";
};
caskArgs = {
appdir = "~/Applications";
};
brews = [
### CLI Applications not available in nixpkgs
"fisher"
];
taps = [
"nikitabobko/tap"
];
casks = [
### GUI Applications
"wezterm"
"1password"
"1password-cli"
"aerospace"
"cursor"
"firefox"
"obsidian"
"raycast"
"stats"
"shottr"
"notchnook"
"jordanbaird-ice"
"kap"
"keycastr"
"zed"
"arc"
### Fonts
"font-google-sans-code"
"font-jetbrains-mono-nerd-font"
];
};
}
nix-darwin/system.nix
{ pkgs, ... }:
{
nix = {
optimise.automatic = true;
settings = {
experimental-features = "nix-command flakes";
max-jobs = 8;
};
};
system = {
stateVersion = 6;
primaryUser = "Macのユーザー名";
keyboard = {
enableKeyMapping = true;
# CapsLockをControlにマッピング
remapCapsLockToControl = true;
};
defaults = {
CustomUserPreferences = {
"com.apple.desktopservices" = {
DSDontWriteNetworkStores = true;
};
};
WindowManager = {
# デスクトップ上のアイテムを非表示にする
StandardHideDesktopIcons = true;
};
controlcenter = {
# メニューバーにAirDropを表示しない
AirDrop = false;
# メニューバーにバッテリー残量を表示しない(Statsで表示しているため)
BatteryShowPercentage = false;
# メニューバーにBluetoothを表示する
Bluetooth = true;
};
dock = {
# アプリケーションスイッチャーを全てのディスプレイに表示する
appswitcher-all-displays = true;
# Dockの自動非表示を有効にする
autohide = true;
# Mission ControlのExposeでアプリケーションをグループ化する
expose-group-apps = true;
# Dockのホバー時の拡大サイズ
largesize = 48;
# Dockのホバー時の拡大を有効にする
magnification = true;
# Dockの位置を左側に設定する
orientation = "left";
# 最近使用したアプリケーションをDockに表示しない
show-recents = false;
# 開いているアプリケーションのみをDockに表示する
static-only = true;
# Dock内のアイコンサイズ
tilesize = 32;
# ホットコーナー(左下)にLaunchpadを設定する
wvous-bl-corner = 11;
# ホットコーナー(右下)にApplication Windowsを設定する
wvous-br-corner = 3;
# ホットコーナー(左上)に通知センターを設定する
wvous-tl-corner = 12;
# ホットコーナー(右上)にMission Controlを設定する
wvous-tr-corner = 2;
};
finder = {
# 拡張子を常に表示する
AppleShowAllExtensions = true;
# 隠しファイルを常に表示する
AppleShowAllFiles = true;
# Finderアイコンをデスクトップに表示しない
CreateDesktop = false;
# 拡張子を変更するときに警告を表示しない
FXEnableExtensionChangeWarning = false;
# リストビューをデフォルトにする
FXPreferredViewStyle = "Nlsv";
# CD, DVDなどをデスクトップに表示しない
ShowRemovableMediaOnDesktop = false;
# Finderの下部にステータスバーを表示する
ShowStatusBar = true;
# 完全パスを表示する
_FXShowPosixPathInTitle = true;
};
magicmouse = {
# 左右クリックを有効にする
MouseButtonMode = "TwoButton";
};
menuExtraClock = {
# メニューバーの時計を24時間表示にする
Show24Hour = true;
# メニューバーに余裕がある場合は日付を表示する
ShowDate = 0;
# 日付を表示する
ShowDayOfMonth = true;
# 曜日を表示する
ShowDayOfWeek = true;
# 秒は表示しない
ShowSeconds = false;
};
spaces = {
# ディスプレイごとに異なるスペースを使用する
spans-displays = false;
};
universalaccess = {
# カーソルのサイズ
mouseDriverCursorSize = 2.0;
};
};
};
}
中身を見てみる
さて、それぞれのファイルがどんな役割を持っているか、実際に見ていきましょう。
flake.nix
これがNixプロジェクトのエントリーポイントです。最初は複雑に見えますが、基本的には「何を使うか(inputs)」と「何を作るか(outputs)」を定義しているだけです。
まず、自分のCLIツール群をまとめてインストールできるようにする部分です
packages.${system}.お好きなパッケージ名 = pkgs.buildEnv {
name = "お好きなパッケージ名";
paths = pkgsConfig.myPackages;
};
初回は以下のコマンド一発で全部インストールします。
nix profile install .#お好きなパッケージ名
次に、更新作業を自動化する部分
apps.${system}.update = {
type = "app";
program = toString (
pkgs.writeShellScript "update-script" ''
# 各種アップデート処理が書かれている
''
);
};
これでnix run .#update
を実行するだけで、flakeの更新からnix-darwinの適用まで全部やってくれます。
基本的にはどの設定に関しても変更を加えた場合は上記コマンドを実行するだけでOKです。
このコマンドに関しては👇の記事を参考にさせていただきました🙇♂️
最後に、nix-darwinとの連携部分です。
nix-darwinについては公式ドキュメントを参照してください。
macOSのあれこれを宣言的に設定できるプロジェクトです。
darwinConfigurations.お好きなホスト構成名 = nix-darwin.lib.darwinSystem {
system = system;
modules = [ ./nix-darwin/config.nix ];
};
pkgs.nix
ここでNixpkgsからインストールするCLIツールを定義します。
Nixpkgsに存在しないパッケージ以外はここで管理します。本来であればNixpkgs以外からでもインストールできるのですが怠惰なのでHomebrewに一任してます。
claude-codeのような非フリーソフトウェアを使いたい場合は、こんな感じで許可してあげる必要があります。
config.allowUnfreePredicate =
pkg:
builtins.elem (nixpkgs.lib.getName pkg) [
"claude-code"
];
myPackages = with pkgs; [
### CLI Applications
nil
nixfmt-rfc-style
fzf
bat
ripgrep
# どんどん追加していく
];
with pkgs;
を使うことで、いちいちpkgs.
を書かなくて済むのが地味に嬉しいです。
使いたいツールがNixpkgsにあるかどうかは👇で検索できます。
nix-darwin/config.nix
nix-darwinの設定をテーマごとに管理できます。
現時点ではhomebrew管理、macOS設定管理だけです。
imports = [
./system.nix
./homebrew.nix
];
nix-darwin/homebrew.nix
GUIアプリケーションやNixpkgsにないものはここでHomebrewを使って管理します。最初は「結局Homebrew使うんかい!」と思いましたが、宣言的に管理できればなんでも良いのです。
自分はいつも brew search
で検索してから入れてます。
自分はこんな感じで使い分けてます
- GUIアプリ → casks(WezTermとか1Passwordとか)
- Nixpkgsにないツール → brews(fisherくらいしか使ってないけど)
- フォント → casks
nix-darwin/system.nix
nix-darwinを使用するとシステム環境設定でポチポチやる作業が全部コードで管理できます。
設定可能な項目は👇の通りです。
実際の運用
初回セットアップ
- Nixをインストール
- dotfilesリポジトリをclone
-
nix profile install .#お好きなパッケージ名
,nix run .#update
を実行 - 終わり!
非常に簡単でした。
日々のアップデート
自分はnix run .#update
を定期的に実行するだけです。これだけで
- flakeのロックファイルが更新される
- Nixのプロファイルがアップグレードされる
- nix-darwinの設定が適用される
- Homebrewのパッケージも更新される
全部自動でやってくれるので本当に楽です。
パッケージの追加
新しいツールを使いたくなったら
-
pkgs.nix
,homebrew.nix
に追加する
- CLIの場合
- nixpkgsを検索し存在すれば
pkgs.nix
に、なければhomebrew.nix
に追加する
- nixpkgsを検索し存在すれば
- GUIの場合
-
homebrew.nix
に追加する
-
-
nix run .#update
で適用
これだけです。
最後に
怠惰な自分でも宣言的にパッケージやmacOSの設定を管理することができました。
Nixに関してまだまだ知識が浅いので、もっと理解度を高めていきたいと思っています。
参考まで、自分のdotfiles貼っておきます👇
ここまでお付き合いいただきありがとうございました!!
参考文献
Discussion