1 2# Modular Services {#modular-services} 3 4Status: in development. This functionality is new in NixOS 25.11, and significant changes should be expected. We'd love to hear your feedback in <https://github.com/NixOS/nixpkgs/pull/372170> 5 6Traditionally, NixOS services were defined using sets of options *in* modules, not *as* modules. This made them non-modular, resulting in problems with composability, reuse, and portability. 7 8A configuration management framework is an application of `evalModules` with the `class` and `specialArgs` input attribute set to particular values. 9NixOS is such a configuration management framework, and so are [Home Manager](https://github.com/nix-community/home-manager) and [`nix-darwin`](https://github.com/lnl7/nix-darwin). 10 11The service management component of a configuration management framework is the set of module options that connects Nix expressions with the underlying service (or process) manager. 12For NixOS this is the module wrapping [`systemd`](https://systemd.io/), on `nix-darwin` this is the module wrapping [`launchd`](https://en.wikipedia.org/wiki/Launchd). 13 14A *modular service* is a [module] that defines values for a core set of options declared in the service management component of a configuration management framework, including which program to run. 15Since it's a module, it can be composed with other modules via `imports` to extend its functionality. 16 17NixOS provides two options into which such modules can be plugged: 18 19- `system.services.<name>` 20- an option for user services (TBD) 21 22Crucially, these options have the type [`attrsOf`] [`submodule`]. 23The name of the service is the attribute name corresponding to `attrsOf`. 24<!-- ^ This is how composition is *always* provided, instead of a difficult thing (but this is reference docs, not a changelog) --> 25The `submodule` is pre-loaded with two modules: 26- a generic module that is intended to be portable 27- a module with systemd-specific options, whose values or defaults derive from the generic module's option values. 28 29So note that the default value of `system.services.<name>` is not a complete service. It requires that the user provide a value, and this is typically done by importing a module. For example: 30 31<!-- Not using typical example syntax, because reading this is *not* optional, and should it should not be folded closed. --> 32```nix 33{ 34 system.services.my-service-instance = { 35 imports = [ pkgs.some-application.services.some-service-module ]; 36 foo.settings = { 37 # ... 38 }; 39 }; 40} 41``` 42 43## Portability {#modular-service-portability} 44 45It is possible to write service modules that are portable. This is done by either avoiding the `systemd` option tree, or by defining process-manager-specific definitions in an optional way: 46 47```nix 48{ 49 config, 50 options, 51 lib, 52 ... 53}: 54{ 55 _class = "service"; 56 config = { 57 process.argv = [ (lib.getExe config.foo.program) ]; 58 } 59 // lib.optionalAttrs (options ? systemd) { 60 # ... systemd-specific definitions ... 61 }; 62} 63``` 64 65This way, the module can be loaded into a configuration manager that does not use systemd, and the `systemd` definitions will be ignored. 66Similarly, other configuration managers can declare their own options for services to customize. 67 68## Composition and Ownership {#modular-service-composition} 69 70Compared to traditional services, modular services are inherently more composable, by virtue of being modules and receiving a user-provided name when imported. 71However, composition can not end there, because services need to be able to interact with each other. 72This can be achieved in two ways: 731. Users can link services together by providing the necessary NixOS configuration. 742. Services can be compositions of other services. 75 76These aren't mutually exclusive. In fact, it is a good practice when developing services to first write them as individual services, and then compose them into a higher-level composition. Each of these services is a valid modular service, including their composition. 77 78## Migration {#modular-service-migration} 79 80Many services could be migrated to the modular service system, but even when the modular service system is mature, it is not necessary to migrate all services. 81For instance, many system-wide services are a mandatory part of a desktop system, and it doesn't make sense to have multiple instances of them. 82Moving their logic into separate Nix files may still be beneficial for the efficient evaluation of configurations that don't use those services, but that is a rather minor benefit, unless modular services potentially become the standard way to define services. 83 84<!-- TODO example of a single-instance service --> 85 86## Writing and Reviewing a Modular Service {#modular-service-review} 87 88A typical service module consists of the following: 89 90For more details, refer to the contributor documentation in [`nixos/README-modular-services.md`](https://github.com/NixOS/nixpkgs/blob/master/nixos/README-modular-services.md). 91 92## Portable Service Options {#modular-service-options-portable} 93 94```{=include=} options 95id-prefix: service-opt- 96list-id: service-options 97source: @PORTABLE_SERVICE_OPTIONS@ 98``` 99 100## Systemd-specific Service Options {#modular-service-options-systemd} 101 102```{=include=} options 103id-prefix: systemd-service-opt- 104list-id: systemd-service-options 105source: @SYSTEMD_SERVICE_OPTIONS@ 106``` 107 108[module]: https://nixos.org/manual/nixpkgs/stable/index.html#module-system 109<!-- TODO: more anchors --> 110[`attrsOf`]: #sec-option-types-composed 111[`submodule`]: #sec-option-types-submodule