资讯动态

openrig:声明式配置管理工具,一条命令搞定开发机环境

发布时间:2026/10/15 13:11:18 来源:尧图企业网站定制
我前天又一次启动了 openrig把一台新笔记本从刚拆封的状态变成了能直接写代码的开发 rig全程唯一做的事是运行一条命令然后等它结束。这个工具最初只是我自己零散的安装脚本仓库后来慢慢长成了现在这套可以描述整台机器的开源小框架。这篇内容就是 openrig 的设计思路以及我在真实环境里反复使用之后的经验记录适合那些受够了每次换电脑都要重装环境的人。1. 从手动装两天到一条命令装完openrig 想解决的问题先说清楚 openrig 到底在解决什么。大多数开发者维护自己电脑的方式其实是三套东西拼起来的一份躺在 GitHub 上的 dotfiles 仓库、几段不知道什么时候写的安装脚本、以及大量只存在于脑子里的手工操作。平时没出问题还好一旦遇到换电脑、电脑崩溃、或者要给第二台机器同步环境这三套东西就会各自为战。我第一次尝到教训是在一次临时出差中。公司给了我一台全新的工作机我原本预计半小时装完环境结果光是把 zsh、vim、终端字体、常用命令行工具逐个装好就花了将近一天。等所有软件就位才发现.ssh/config漏掉了某个调试工具装的是旧版本和本地表现不一致。这种状态在之后的几个月里不断以这台机器怎么和那台机器不一样的形式冒出来。手动操作最大的问题就在这里不可审计、不可复现、不可验证。openrig 的基本思路其实很朴素把一台电脑的最终状态用一份声明式文件描述出来然后由工具负责从当前状态收敛到目标状态。它不像配置管理工具那样面向几百台服务器也不像单纯的 dotfiles 管理器只管配置文件而是站在两者中间专门服务个人开发机和少数几台工作机。用我自己的话说它管的东西就是一台开发机该有的样子。这个取舍在项目早期非常重要。很多人一听配置管理下意识会想到一套庞大体系但 openrig 从一开始就限定范围只管一台机器上从操作系统到用户目录里的事。范围小了工具就可以做得很轻安装和上手都很快也不必为了支持复杂网络环境引入一堆额外概念。它适合的人是经常换机器、有多台电脑需要保持一致、需要给同事或同学快速交付一个可用开发环境的人。1.1 手动配置机器为什么不可靠手动配置看起来最直接实际上却最容易埋雷。一个典型的安装过程包括上网搜索安装命令、复制粘贴、等编译、改配置文件、重启终端、发现环境变量没生效、再去翻文档。这中间任何一步都没有留下这台机器此时是什么状态的记录。更隐蔽的问题是约等于。装某个软件的时候选了默认版本另一台机器上却装了最新版某次调试时给配置文件加了一行临时参数后来忘了删这行参数就一直躺在你的 shell 启动文件里。时间越长机器之间的差异越大最后你甚至说不清我平时用的那套环境到底是什么组成的。1.2 openrig 做了一个什么样的取舍openrig 选择描述最终状态而不是记录操作步骤。安装脚本记录的是过程声明式配置记录的是结果。这个区别在遇到环境漂移的时候非常明显脚本跑一遍如果中间报错你很难说清已经改了什么而声明式配置每次都从当前状态出发差的补上、多了的可以清理、多余的保持不动整个收敛过程是有规则的。代价是有的。声明式的方式要求你先想清楚要什么不能像手动那样装一步看一步。但对大多数成熟开发者来说自己电脑上需要什么其实是清楚的写清楚并不困难。1.3 安装 openrig 需要准备什么openrig 目前主要支持 macOS 和常见 Linux 发行版Windows 下建议配合 WSL 使用。安装它本身只需要一个可执行文件和一份配置不需要数据库也不需要常驻服务。唯一的前置要求是机器上有 Git因为配置文件默认从 Git 仓库拉取这也顺便解决了多台机器之间同步的问题。2. rigfile 的语法与模块设计整台电脑如何被描述核心配置文件叫rigfile.yaml放在你的配置仓库根目录。它的作用是把整台机器拆成几类可管理的东西系统设置、软件包、dotfiles、服务、以及一些需要在特定时机执行的 shell 命令。下面是一份我在主力机上实际在用的简化版本。project: devbox version: 2 system: hostname: work-720 timezone: Asia/Shanghai locale: en_US.UTF-8 packages: brew: present: - fish - neovim - git - jq - ripgrep absent: - vim apt: present: - build-essential - htop dotfiles: - source: dotfiles/.gitconfig target: ~/.gitconfig - source: dotfiles/.zshrc target: ~/.zshrc - source: dotfiles/init.fish target: ~/.config/fish/conf.d/init.fish shell: default: /usr/local/bin/fish services: ensure_running: - name: docker ensure_enabled: - name: sshd hooks: post_apply: - command: git config --global core.editor nvim2.1 一份最简单的 rigfile如果你第一次用一份只装了 Git 和 Neovim、再把.gitconfig和.zshrc放进去的配置就足够了。先跑通最小闭环再逐步加模块。千万别一开始就想着把所有细节都写进去否则第一天就会在配置语法上消耗大量耐心。project: quickstart version: 1 packages: brew: present: - git - neovim dotfiles: - source: dotfiles/.gitconfig target: ~/.gitconfig2.2 几类模块和它们各自的边界packages是最常用的模块。它不做版本管理只关心装没装。装了就不再动没装就装最新稳定版。如果你需要对某个软件锁版本可以在后面加version:字段openrig 会调用对应包管理器处理。absent列表则用来清理机器上不需要的软件这是手动维护时很少有人会做的事。dotfiles模块负责把配置文件放到正确位置。默认策略是符号链接这样你在仓库里改了配置目标机器会立即同步。如果目标位置已经存在文件openrig 会先对比内容一致就跳过不一致就备份成.bak-时间戳再创建链接。system模块里我一般只放 hostname、时区这类真正不希望漂移的设置。services模块管理服务的运行状态和开机自启它本质上是封装了systemctl和 macOS 的launchctl操作。hooks模块用来兜底那些不好抽象的场景例如某个软件的初始化命令所有 hook 都会在 plan 阶段显示出来不会悄悄执行。2.3 为什么不用纯 shell 脚本做这件事项目一开始确实是 shell 脚本但写到后面有几个问题绕不过去。第一是幂等安装脚本通常默认目标机器是干净的一旦重跑就报错或做重复操作第二是无法预览脚本执行前你基本不知道它会改什么第三是没有状态记录脚本跑完你拿不到一份这次到底改了什么的清单。openrig 把这些问题从机制上解决每个模块都实现了检测当前状态和执行变更两个动作plan 命令把所有变更列给你看apply 命令再真正动手每步结果写进本地状态文件。这个设计很像基础设施领域常说的收敛模型但放在个人电脑上其实一样有效。3. 在裸系统上把 openrig 跑起来完整流程与输出解读假设你刚拿到一台新电脑系统是干净的。使用 openrig 的完整流程可以分成三件事安装 openrig 本身、拉配置、执行 plan 和 apply。3.1 安装 openrig 的两种方式最简单的方式是用官方安装脚本curl -fsSL https://openrig.dev/install.sh | sh如果你对从网络拉脚本这件事比较谨慎也可以下载对应平台的二进制包解压后放到PATH里就行。安装完成后openrig version能正常输出版本号就说明本体没问题了。之后把配置文件仓库克隆到本地比如放在~/rigs目录然后告诉 openrig 使用哪个 rigfileopenrig init ~/rigs/devbox/ # 生成一份 rigfile 模板并关联本地状态目录 openrig plan3.2 plan 到底做了什么plan 阶段不会修改系统它逐模块扫描当前机器状态和 rigfile 里声明的目标状态比对。输出类似这样[plan] packages: 3 to install, 1 to remove [plan] dotfiles: .zshrc - will link (target exists, content differs, backup planned) [plan] services: docker will be started [plan] hooks: 1 command will run after apply这份清单就是整个操作的施工图。我自己的习惯是每次 plan 完都认真扫一眼尤其注意有没有自己预期之外的变更。执行前多花两分钟可以避免很多上手后才发现的问题。确认后运行openrig applyapply 会按顺序处理模块先系统设置、再包管理、然后是 dotfiles、服务最后是 hooks。每完成一项会打印状态标记[ok]表示已满足、[changed]表示做了变更、[failed]表示出错。全部完成后openrig 会把整次执行的变更写入.openrig/state.yaml方便事后回溯。3.3 幂等性到底是怎么做的openrig 宣称可以重复执行这不是靠运气而是每个模块都严格遵守同一套模式。拿 packages 举例它先调用包管理器查询某个包是否已安装已安装就直接跳过dotfiles 则先比较符号链接指向和文件内容services 先查状态再决定是否执行启动命令。所以同一份配置在一台机器上跑十遍结果是一样的第一遍做了所有变更后面九遍几乎都只是扫描和跳过。这个特性对日常维护很有价值——你不再需要担心我是不是多跑了某条初始化命令。需要临时改环境时可以直接改 rigfile 再执行一次 apply效果类似给系统做了一次定向对齐。4. 实战中踩过的坑和最终解决方式工具写了不等于好用真正让它变可靠的是反复踩坑和修补。下面这几个问题是我在实际使用中遇到的每个都值得单独说明。4.1 非交互 shell 导致的环境变量不生效第一次给 macOS 机器配置 Fish shell 时apply 跑完一切正常但打开终端却发现fish没有成为默认 shell$PATH也和我预期的不一致。排查后发现两个原因chsh -s在非交互式 shell 里不会刷新当前会话的缓存$PATH的设置在.zshrc里而 Fish 根本不会读它。现在的做法是shell 模块里显示声明默认 shell同时把环境变量统一放到~/.config/fish/conf.d/和~/.zshenv这种跨会话的地方而不是写进某个交互式配置里。这个原则对所有 shell 都适用启动时要用的东西放对位置交互时才用的东西才写在 rc 文件里。4.2 dotfiles 目标位置冲突有台机器上~/.gitconfig是我手工创建的内容带了一些本机特殊配置。第一次 apply 时 openrig 做了备份然后创建链接备份文件倒是生成了但我还是花了一点时间才找到。后来我在 dotfiles 模块里增加了conflict_strategy: backup选项并规定所有机器的 dotfiles 仓库保持单一来源本地特殊配置一律用git config --global的追加方式放到~/.gitconfig.local。这样既保留了单机差异又不会污染公共配置。4.3 包管理器的有版本号但内容不对包管理器只保证某个软件装了不保证它装的是你想要的版本。有次我配置里的ripgrep在旧系统源里是 11.x公司服务器上解析出来的却是 13.x。问题不严重但两台机器软件版本不一致正是最初想解决的问题。所以 packages 模块增加了一个可选字段version:。声明了版本号的包apply 时会用包管理器查询当前版本不一致就升级或降级。没有特别要求的话我还是建议让包管理器保持最新版但工作里涉及工具链一致性的场景这个字段能省很多事。4.4 需要 sudo 权限的操作卡在交互输入上安装系统级包、修改 hostname、控制服务这些操作大多需要 sudo。交互式运行没问题但不交互执行时整条流程就会卡在密码输入上。我最终在 apply 命令里增加了--sudo模式它会提前一次提示输入密码只在需要时使用不会缓存凭证流程结束时立刻清空。这个细节改造完之后整个 apply 过程才算真正能无人值守跑完。5. openrig 和 Ansible、Chezmoi 的关系边界在哪里每次听到配置管理这个词很多人第一反应都是 Ansible一提到 dotfiles又会想起 Chezmoi、GNU Stow 这些工具。openrig 不是要替代它们而是站在一个不同层级上。用一句话概括Ansible 管服务器群Chezmoi 管配置文件openrig 管个人开发机整机状态。工具主要场景学习成本状态管理典型用户Ansible批量服务器配置高面向远程主机依赖 inventory运维工程师Chezmoi管理 dotfiles 多处同步中仅配置文件不涉及包和服务进阶开发者GNU Stow符号链接管理 dotfiles低无状态仅做链接熟悉 Unix 的用户openrig个人开发机整机装配低有状态覆盖包/配置/服务多机器开发者Ansible 的优势在于批量、并行、面向无状态的远程服务器但个人电脑的场景其实不太一样机器有桌面环境、有用户会话、有各种 GUI 软件很多状态 Ansible 并不理解。Chezmoi 在处理 dotfiles 这一件事上做得非常细比如模板化和多机器差异这是 openrig 不会去覆盖的功能。openrig 保留了这个能力圈dotfiles 就是简单链接或复制不做模板渲染。如果你已经用 Chezmoi 管好了配置文件也不一定非要迁移到 openrig。可以让 openrig 只负责 packages 和服务dotfiles 部分继续沿用 Chezmoi。项目设计上允许在 rigfile 里把dotfiles模块整个禁用两边互不干扰。6. 用了两个月之后日志、回滚和一些个人体会openrig 整个设计里我最满意的是状态文件和日志。以前手动装环境的记忆全靠脑内事后想不起来那天为什么装了那个包。现在每个变更都有迹可循rigfile 是目标状态.openrig/state.yaml是当前状态apply.log是变更历史。有一次我发现自己机器上多了个不明服务查日志发现是两周前一个测试用的 rigfile 改的顺手就清理掉了。仓库管理上我的建议是把整个 rigs 目录做成一个 Git 仓库rigfile.yaml和dotfiles/放在一起。这样一来任何一次对环境的修改都成了一次 commit提交信息就是今天我装了 X、删了 Y机器的变化历史变得和代码仓库一样清晰。你也可以给仓库打 tag比如stable、dev不同机器可以锁定在不同版本上。另外一个小技巧把 openrig 的仓库提交到 GitHub 后新机器只需要一条命令克隆外加openrig apply就能恢复 90% 的开发环境。剩下 10% 是各类 GUI 应用的登录态和授权信息这部分我目前还是手动处理。真要自动化可以后续加一个打开这些应用的登录页的 hook但隐私和安全性我还没想好怎么平衡。openrig 现在还在持续演进下一个想做的方向是多机器之间的配置差异管理。比如工作机器和个人机器的 dotfiles 共享但某些系统设置不同。这个问题在设计层面还没完全想清楚可能会借鉴一些同类工具的思路。不过就目前的使用体验来说从手动装两天到一条命令装完这个转变已经足够让我觉得当初把这个工具认真做完是值得的。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑