在 macOS 中使用 Nix 作为包管理器

大概是比 Homebrew 更好用的包管理方案

为什么不用 Brew

目前在 macOS 上的主流包管理方案还是 Homebrew,但是这玩意我觉得是一点都不好用:

  1. 真的很慢:安装新包通常来说是比较低频的操作,但是 brew 会自作主张给你在安装前检查自己的更新;就算跳过这一步,和其他包管理器相比,从头安装一个包所需要的时间差异也非常大,我是不太能理解这么一件简单的事儿为什么 brew 需要花那么久;
  2. "污染"系统文件:众所周知,brew 会把东西全部一股脑的装到 /usr/local/bin 中,如果有一些包想作恶会很轻松的混入系统默认 PATH 中,brew 社区运作的模式也无法保证所有包都是安全的,何况还有可能遇到供应链攻击;
  3. 晦涩难懂:Homebrew 用了大量的啤酒生产术语:Formula, Keg, Tap, Cellar, Bottle, Cask, ...对于我这种滴酒不沾的人来说理解门槛确实有点高,得去好好学习一下才知道这些都是啥。

总之 Brew 并不是一个让我用着舒服的包管理器。但是迫于生计需要在 macOS 上搬砖来养活自己,不能说走就走跑去用 Linux 写代码,于是我就把目光转向了 Nix。

Nix 和 NixOS

大概一年前我在苦于无法便捷地管理 10+ 台服务器时发现了 NixOS,有很多文章都详细介绍了 NixOS 的特点,让我心动不已:

  1. /etc/nixos 为中心,通过配置文件来控制整个系统上安装的软件和他们的配置;
  2. 可重复构建,对于相同的配置文件,构建出来的操作系统也是一致的*;
  3. NixOS 使用的包管理器的配置语言 Nix 图灵完备,配置得当我可以在一个 git 仓库中维护我所有服务器的配置,可以最大化共享基础配置,同时记录所有历史版本方便回滚和调试。
  4. Nix 是函数式的!非常有意思不是吗

* 当然和大部份包管理器一样,如果没有锁其实也并不能保证这一点

在后来的一段时间里我逐步用 NixOS 替换了我大部分服务器上的 Debian。期间我注意到 NixOS 的下载页面中,Nix (the package manager) 是有 macOS 版本的:

于是就计划好了,之后一定要把 brew 从我的系统中彻底抹掉。

替换契机

公司有一个政策:购入三年的 MacBook 产品可以申请到期更换,如果想要甚至可以选择将这台打工电脑回购。满三年之后我自然是立即和 IT 发起了到期更换流程,这台 Intel MacBook Pro 虽然配置了 i7 + 32G,但是用起来依然是卡到爆炸,写代码随时处在崩溃边缘 (:з」∠)

申请当天 IT 就通知我可以来领电脑了。换来的新电脑还是 16 英寸的 MacBook,配备了 M2 处理器和 32G 的内存,整体上非常符合我的期待。至于软件,我不打算从旧的 Intel Mac 上迁移数据,毕竟跨了架构,总感觉会不靠谱。于是这次我就没有安装 brew,准备小试一下不在 NixOS 中使用 Nix。

安装 Nix

就和上面官网截图中介绍的一样,Nix 的安装也是直接用 curl 下载脚本执行来完成的。

less 复制代码
sh <(curl -L https://nixos.org/nix/install)

不过和大部份"一键脚本"还不太一样,Nix 会在安装过程中详细的输出了自己需要干什么,特别是用到 sudo 的时候:

安装完成之后,我们就可以在终端使用 nix 命令了:

nix 和 brew 比起来有一个很好的地方,就是他的安装的文件都是放在一个 APFS 容器中,如果想要删除 Nix 很方便:删掉容器就好了。

到此为止我们就已经安装完成了 nix 这个包管理器,但是距离像 NixOS 一样用一个 configuration.nix 管理大部份软件还有点区别。

安装 nix-darwin

nix-darwin 把 NixOS 的软件管理模式复刻到了 macOS 上,我们可以用 nix 很方便的安装 nix-darwin:

bash 复制代码
nix-build https://github.com/LnL7/nix-darwin/archive/master.tar.gz -A installer
./result/bin/darwin-installer

安装完成之后,我们就可以在 ~/.nixpkgs 中发现这个 darwin-configuration.nix 了:

ini 复制代码
{ config, pkgs, ... }:

{
  environment.systemPackages = [
    pkgs.vim
  ];

  services.nix-daemon.enable = true;
  programs.zsh.enable = true;  # default shell on catalina
  system.stateVersion = 4;
}

因为我是一个臭写 HTML 的,所以需要安装 node,同时我更习惯使用 GNU 的 coreutils 而不是 BSD 的,所以我将这个配置调整至如下:

ini 复制代码
{ config, pkgs, lib, ... }:

{
  nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [
    "unrar"
  ];

  environment.systemPackages = with pkgs; [
    vim ffmpeg-full coreutils gnugrep gnused gawk htop mtr
    smartmontools neofetch rsync p7zip hugo ncdu
    ipmitool iperf3 wireguard-tools jq p7zip unrar
  ];

  services.nix-daemon.enable = true;
  programs.zsh.enable = true;
  system.stateVersion = 4;
}

之后只需要执行 darwin-rebuild switch 即可让 darwin-nix 完成软件的安装和配置(我这里出于使用习惯,没有使用配置的能力)。完成之后所有的软件就都在 PATH 中了:

看日志不难注意到 /Applications/Nix Apps 这个目录的存在,实际上不只是命令行软件,GUI 软件也可以通过 Nix 安装,比如这个叫 kitty 的终端模拟器

相关推荐
Yz987625 分钟前
Hive安装-内嵌模式
大数据·linux·数据仓库·hive·hadoop·hdfs·bigdata
SmallBambooCode2 小时前
【人工智能】阿里云PAI平台DSW实例一键安装Python脚本
linux·人工智能·python·阿里云·debian·脚本·模型训练
纯小白是我2 小时前
CentOS 7系统中更改YUM源为阿里云的镜像源
linux·阿里云·centos
嵌入式Linux,2 小时前
BUG: scheduling while atomic
linux·运维·服务器·bug
小兔子酱#2 小时前
【Linux 29】传输层协议 - UDP
linux·运维·服务器·网络·网络协议·udp
CYRUS_STUDIO2 小时前
Android下的系统调用 (syscall),内联汇编syscall
android·linux·汇编语言
想不到好名字了()2 小时前
负载均衡式在线oj项目开发文档2(个人项目)
linux·网络·c++
General_G2 小时前
FastDDS服务发现之EDP的收发
linux·中间件·服务发现·fastdds
LuckyTHP2 小时前
linux分析利刃之sar命令详解
linux·运维·服务器
浙江赛思电子科技有限公司2 小时前
自动驾驶为什么需要时间同步?高精度时间同步如何实现?
linux·科技·计算机网络·硬件架构·硬件工程·能源·信号处理