使用 Nix 管理及同步 dotfiles
迁移背景
我的开发平台是 macOS,以及家里 PVE 上开启的虚拟机,加上一个定期更换机器的 vps,平台只有 Linux 和 macOS,但是机器多,每次远程到 linux 上的时候,那只能用原生 vim,跟 macOS 上我配置的功能相去甚远,所以想着能不能使用 git 同步我的配置。
初始方案: shell 脚本直接操作
其实备份的 dotfiles 无非就是一些 shell、cli 工具配置,所以自然想到了使用 shelll 去管理这些 dotfiles,我的 shell 编程经验比较少,也不那么太喜欢 shell,所以我面临了几个问题:
- shell 经验不足,即使使用 gpt,写出来的东西也挺丑陋
- shell 有局限性,比如没法自动升级之类的,想要实现,受制于 1
总结来说,就是 shell 编程不熟悉,无法完成非常高深的同步需求,如果真按照需求写出来了,成本非常高。 所以一直以来,都是把 dotfile 作为存储仓库来使用,自动化的部分不多,有需要了拉下来然后手动执行命令配置。
Nix 拯救了我
前段时间在推上看到了这个Nix Darwin Kickstarter (opens in a new tab)仓库,了解到了 Nix,内心直呼这不就是我想要的么,于是开启了迁移踩坑之旅。
什么是 Nix?
还是上面 Kickstarter 仓库的作者,写了一本小册子 (opens in a new tab),用来帮助初学者入门,简单总结下,有兴趣可以看原链接
- Nix 是包管理器,使用 Nix 语言即可使用 Nix 包管理器
- Nix 语言是一门函数式语言
- NixOS 是使用 Nix 包管理器管理整个系统的发行版,可以管理任何的系统设置
- home-manager 是用来管里用户层级软件包的软件
- nix-darwin 可以用来管理 macOS 上的 brew 以及系统配置
简而言之,使用 nix 可以使用编程的方式定义自己系统里所需要的所有软件。 我没有使用 NixOS,我平时不会使用 Linux 的 GUI 界面,都是 ssh 过去,没必要徒增难度去强行使用 NixOS,所以我的 dotfils 没有关于这部分的内容
我的 dotfiles
我的 dotfiles 项目 (opens in a new tab)结构如下
flake.nix
: 项目入口,描述了基本的定义home-manager/
: home-manager 配置,描述了被 home-manager 所管理的一切软件和配置lib/
: Nix 工具函数machines/
: 每个机器的不同配置.overlays/
: overlay 文件夹,暂时只有 rust.config/
: 第三方软件配置文件夹.
上面出现了一个 overlay 和 home-manager
- overlay 是用来安装自定义软件的一个方式
- hm 是用来管理用户层级的软件以及配置的一个工具,我基本上所有的软件都在这里定义
如何安装软件和取舍配置
首先安装的软件分为三部分
- cli 软件,这部分软件几乎可以完全被 hm 管理
- macOS 上的 GUI 软件,比如 chrome,这些软件通过 brew 管理
- nvm 或者类 nvm 的动态版本管理软件,作为前端,nvm 必不可少,但是 nix 作为函数式管理的思路,又不适合 nvm,所以需要一些灵活性的 hack
第三方软件配置方面,实际上 hm 冗长的文档绝大部分都是配置各种软件的字段,但我不是非常想用
- 软件版本更新之后 hm 可能更新不及时
- 生成的配置无法随意更改,要想更改只能更改代码,会比较麻烦
所以最终的方案是
- 只使用 nix 安装软件
- 配置使用每个软件的官方配置方式,放到 config/文件夹里,通过脚本批量创建软连接
最终安装的软件
- 使用 nix-darwin 管理 brew,安装了 39 个 GUI 软件
- 使用 hm 管理将近五十个 cli 软件
- 使用 shell 管理 config 文件夹
最终包括我的 mac,一共 6 台机器都使用一样的命令行配置,效率提升
感想
Nix 是一个非常强大的工具,最近几年热度也持续攀升,但总的来说有以下缺点
- 非常难写,在我看来和 rust 已经基本一个难度层级,而且网上资料驳杂,从这个角度来说比 rust 还难。
- 报错不清晰,需要是不是在源代码里找线索
- 需要更多的 shell 知识,由于主要配置的是 cli,shell 新手想要使用 nix,那么可能是地狱级难度
最重要的优点就是一次使用,终身受益。一旦确定了基本架构并且完成项目,那么剩下的时间就是小修补,非常省时省力,不容易出问题。
总的来说还是非常推荐使用 Nix 作为 dotfiles 的管理工具,多花点时间,code like a pro!