尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

编写与审查 NixOS 模块化服务(Modular Services):从设计原理到提交规范

发布时间:2026/9/23 22:37:10

资讯中心
01
ARTICLE

编写与审查 NixOS 模块化服务(Modular Services):从设计原理到提交规范

编写与审查 NixOS 模块化服务(Modular Services):从设计原理到提交规范
包管理器操作系统【免费下载链接】nixpkgsNix Packages collection NixOS项目地址https://gitcode.com/GitHub_Trending/ni/nixpkgs点击查看免费下载NixOS 模块化服务Modular Services是 NixOS 25.11 引入的一项仍在开发中的新功能它把传统服务选项集合重构为真正可组合、可移植的服务模块可通过system.services.name接入任意配置管理系统。本文基于 nixos/README-modular-services.md 的贡献者规范结合 nixpkgs 仓库内 lib/services、nixos/modules/system/service 的源码实现与 ghostunnel 等真实范例系统讲解如何编写、审查并提交一个合格的模块化服务读完你将掌握_class service、optionalAttrs (options ? systemd)可移植写法、finalAttrs.finalPackage包默认值覆盖等核心要点。模块化服务是什么传统 NixOS 服务是在模块内部用一组选项options定义的例如services.foo.enable、services.foo.port而模块化服务本身就是一个模块它为服务管理组件service manager声明的核心选项包括运行哪个程序提供取值。由于它是一个模块可以通过imports与其他模块组合以扩展功能。相关背景与正式定义见手册章节 nixos/doc/manual/development/modular-services.md。NixOS 提供两个接入点system.services.name把模块化服务作为 systemd 服务配置面向用户服务的选项TBD尚未落地。这两个选项的类型是attrsOf submodule服务名即attrsOf对应的属性名。该submodule预置了两个模块一个可移植的通用模块lib/services/service.nix一个systemd 专属模块nixos/modules/system/service/systemd/service.nix其取值/默认值从通用模块的选项值推导而来。因此system.services.name的默认值不是一个完整服务必须由用户提供取值——通常通过导入某个包导出的服务模块{ system.services.my-service-instance { imports [ pkgs.some-application.services.some-service-module ]; foo.settings { # ... }; }; }与 NixOS 模块的关系模块化服务不是NixOS 模块的替代品但未来可能成为替代品用模块化服务来实现一个 NixOS 模块是被期待的使用场景但这会让该 NixOS 模块暴露在尚不能为广泛使用模块所接受的不确定性之下。从源码结构看这一双重身份在实现上已明确分层可移植层位于 lib/services不依赖 NixOSsystemd 绑定层位于 nixos/modules/system/service/systemdNixOS 的system.services选项则在 system.nix 中声明并通过lib.services.configure将两层拼接。维护职责Maintainership如果你贡献一个模块化服务必须把自己标记为该模块化服务的维护者模块化服务的维护者不必与该 NixOS 模块的维护者相同如果你不是该 NixOS 模块的维护者应主动申请加入其meta.maintainers团队以便参与评审和讨论——大多数讨论同样影响模块化服务NixOS 模块维护者对模块化服务没有义务最多在发现模块化服务损坏时通知你。meta.maintainers之所以是硬性要求是因为服务基础模块在 lib/services/service.nix 中通过imports引入了通用维护者模块 modules/generic/meta-maintainers.nix。最低标准Minimum Standard模块化服务必须满足附带一个 NixOS VM 测试实际运行该模块化服务具有meta.maintainers模块属性列出模块化服务的维护者。两者缺一不可任何不满足标准的 PR 都不应被合并。审查清单评审一个模块化服务时应逐项检查详见下文说明- [ ] Has a NixOS VM test - [ ] Has a meta.maintainers attribute - [ ] Systemd-specific definitions are behind optionalAttrs (options ? systemd) to promote portability. - [ ] _class service - [ ] Modular services provided through passthru.services must override the default of the package option using finalAttrs.finalPackage - [ ] Is the modular services infrastructure sufficient for this service? If one or more features are not covered, comment in https://github.com/NixOS/nixpkgs/issues/428084 - [ ] Has been added to nixos/modules/misc/documentation/modular-services.nixNixOS VM 测试测试必须小而聚焦启动 VM → 启用服务 → 断言一个基本请求成功。测试通常放在nixos/tests/下并由包的passthru.tests引用。仓库中 nixos/tests/modular-service-etc/python-http-server.nix 是一个轻量示例——一个基于 Python 内置http.server的模块化服务模块定义了自己的package、port默认 8000、directory选项并通过process.argv组装命令行、通过configData暴露 webroot 目录。它演示了模块化服务测试所需的全部要素_class service、自定义选项树、process.argv与configData的组合。systemd 集成层的测试可参考 nixos/modules/system/service/systemd/test.nix其中覆盖了system.services.foo、system.services.bar以及systemd.mainExecStart的参数转义/变量替换argv-with-subst、argv-escaped、argv-extended等场景。_class service声明_class声明参见 模块系统 class 参数确保当模块被意外导入到非模块化服务配置例如普通 NixOS 配置时会给出清晰明确的错误而不是产生难以理解的求值失败。将其作为模块的第一个属性提供# Non-module dependencies (importApply) { writeScript, runtimeShell }: # Service module { lib, config, ... }: { _class service; options { # ... }; config { # ... }; }_class service同时出现在可移植基础模块 lib/services/service.nix、systemd 绑定模块 nixos/modules/system/service/systemd/service.nix 以及 NixOS 宿主模块其_class nixos见 system.nix中——宿主与服务的 class 不同正是为了防止把服务模块误当 NixOS 模块导入。覆盖包默认值finalAttrs.finalPackage通过passthru.services提供模块化服务时必须用finalAttrs.finalPackage覆盖 package 选项的默认值参见 mkDerivation 递归属性。原因某些包本身就是由 override 定义的例如somePackage.override { ... }如果服务模块内部自己解析pkgs就会启动错误的包——甚至根本无法构建。示例package.nix{ stdenv, nixosTests, # ... }: stdenv.mkDerivation (finalAttrs: { pname example; # ... passthru { services { default { imports [ (lib.modules.importApply ./service.nix { inherit pkgs; }) ]; example.package finalAttrs.finalPackage; # ... }; }; }; })如果做不到这一点或者该模块不表示单一包则应考虑只按文件路径直接暴露模块化服务。仓库中的完整范例ghostunnel真实范例见 ghostunnel 的 package.nix 与 service.nixpassthru.services.default { imports [ (lib.modules.importApply ./service.nix { }) ]; ghostunnel.package finalAttrs.finalPackage; };其服务模块 service.nix 展示了完整的最佳实践组合_class service作为第一个属性独立的选项树ghostunnel.*listen、target、keystore、cert、key、cacert、allowAll、allowCN等package选项无默认值defaultText The ghostunnel package that provided this module.在config中通过assertions校验至少设置一个访问控制标志通过process.argv组装基础命令行getExe cfg.package、--listen、--target等systemd 专属定义全部包在lib.optionalAttrs (options ? systemd) (...)中用systemd.mainExecStart、systemd.service补充凭据注入LoadCredential、${CREDENTIALS_DIRECTORY}等能力。可移植性optionalAttrs (options ? systemd)可移植写法是编写模块化服务的核心技巧要么完全避开systemd选项树要么把进程管理器专属定义写成可选形式{ config, options, lib, ... }: { _class service; config { process.argv [ (lib.getExe config.foo.program) ]; } // lib.optionalAttrs (options ? systemd) { # ... systemd-specific definitions ... }; }这样该模块可以被加载到不使用 systemd 的配置管理器中此时options ? systemd为 falsesystemd 定义被忽略而其他配置管理器也可以为自己的服务声明专属选项。设计上systemd选项树的取值/默认值从通用选项值推导见 service.nix 中systemd.mainExecStart、systemd.services的声明从而保持通用层可移植、专属层可选的分层。设计原理为什么服务模块拿不到pkgs可移植基础模块刻意不把pkgs作为模块参数暴露给服务模块见 nixos/modules/system/service/README.md 的设计决策记录派生包与构建函数通过**词法闭包lexical closure**提供。收益有三依赖显式化服务声明自己需要什么而非隐式依赖某个pkgs无干扰服务模块可在不同上下文复用无需假设特定的pkgs实例意外的 pkgs 版本不再是故障模式更清晰实现路径更少依赖来源来自模块而非 OS 或服务管理器没有歧义。因此服务模块应把包依赖声明为选项而非pkgs默认值{ # Bad: uses pkgs module argument foo.package mkOption { default pkgs.python3; # ... }; }{ # Good: caller provides the package foo.package mkOption { type types.package; description Python package to use; defaultText lib.literalMD The package that provided this module.; }; }而passthru.services可以利用包的词法作用域提供完整模块使模块真正自包含详见 README.md 中的package.nix/service.nix双文件示例以及 ghostunnel 的落地实现。深入可移植服务基础与 systemd 集成可移植层lib/serviceslib/services/service.nix 是可移植服务基础模块定义process.argv原始命令行不做 shell 转义、flags、services子服务、configData等通用选项并自导入meta-maintainers与 assertions 模块。lib/services/config-data.nix 与 lib/services/config-data-item.nix 定义configData一种服务管理器无关的配置数据接口每个条目自动获得由服务管理器实现设置的path属性路径跨 generation 不变只有内容变化。lib/services/lib.nix 提供lib.services.configure宿主系统接入入口以及getWarnings/getAssertions递归收集服务与子服务的警告/断言。systemd 集成层system.nix 把每个服务的configData映射为environment.etc条目落在/etc/system-services/前缀下并把systemd.services/systemd.sockets单元定义虹吸到系统配置中单元名以抽象服务名为前缀。config-data-path.nix 递归计算服务与子服务的唯一路径如/etc/system-services/webserver/与/etc/system-services/webserver-api/其本身_class service对模块系统而言是完全普通的模块。service.nix 提供 systemd 专属选项systemd.mainExecStart默认是process.argv的转义版本显式设置后才启用%n、%i、${VAR}等替换、systemd.mainExecReload、systemd.services、systemd.sockets以及systemd.lib.escapeSystemdExecArgs参数转义函数把%→%%、$→$$防止 systemd 的 specifier/变量替换。注册文档通过passthru.services提供的模块化服务还需加入 nixos/modules/misc/documentation/modular-services.nix以便渲染进 NixOS 手册。该文件以fakeSubmoduledocumentation.nixos.extraModules的方式为pkgs.autopush-rs.services.autoconnect、pkgs.ghostunnel.services.default、pkgs.git-pages.services.default、pkgs.ktls-utils.services.default、pkgs.php.services.default、pkgs.snid.services.default、pkgs.trailbase.services.default等服务生成文档占位当前是原生服务文档落地前的中间方案。组合与迁移组合Composition相比传统服务模块化服务天然更可组合——它本身就是模块导入时获得用户提供的名字。组合有两种方式可叠加使用用户提供必要的 NixOS 配置把多个服务链接起来服务可以是其他服务的组合体通过可移植层的services选项声明子服务见 service.nix。良好实践先把服务写成独立服务再组合成更高级的组合每个独立服务包括组合体都是合法的模块化服务。迁移Migration即使模块化服务成熟后也不必迁移所有服务。许多系统级服务是桌面系统不可或缺的单实例服务多实例化没有意义将其逻辑拆到独立 Nix 文件仅在不使用这些服务的配置求值效率上有较小收益除非模块化服务未来成为定义服务的标准方式。状态与现状截至写作时模块化服务是 NixOS 中的新功能NixOS 25.11 引入处于开发中重大变更可期。RFC 163 的中间结论是应尝试基于模块的可移植服务方案但这尚未成为广泛认同的解决方案——评审与使用时应保持这一认知并为基础设施缺口在 issue 428084 中反馈。本文涉及的关键实现路径均可直接在仓库中查阅lib/services可移植层、nixos/modules/system/servicesystemd/NixOS 集成、nixos/modules/misc/documentation/modular-services.nix文档注册与 pkgs/by-name/gh/ghostunnel完整范例。赞分享包管理器操作系统【免费下载链接】nixpkgsNix Packages collection NixOS项目地址https://gitcode.com/GitHub_Trending/ni/nixpkgs点击查看免费下载相关推荐NixOS 模块化服务Modular Services实战指南以模块为单位声明可组合、可移植的服务NixOS 模块化服务Modular Services实战指南以模块为单位声明可组合、可移植的服务 模块化服务Modular Services是 Ni包管理器操作系统NixOS 模块编写指南从选项声明到 Systemd 服务集成Writing NixOS ModulesNixOS 模块编写指南从选项声明到 Systemd 服务集成Writing NixOS Modules NixOS 通过模块化modular系统实现包管理器操作系统Upsonic 仓库提交规范commit.md实战指南从编写规范提交信息到严守审批红线Upsonic 仓库提交规范commit.md实战指南从编写规范提交信息到严守审批红线 本文以 Upsonic 仓库的 提交规则文档 https://li人工智能大模型AI AgentAgent 框架自主智能体工具调用RAGAgent 记忆Agent 编排创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。