如何在 Nixos 中添加自定义服务
How to add custom services in Nixos
使用 nixops
可以轻松配置如下服务:
{
network.description = "Web server";
webserver = { config, pkgs, ... }:
{
services.mysql = {
enable = true;
package = pkgs.mysql51;
};
但我想延长 services
。例如,使用 override
就像下面 pkgs
所做的那样:
let
myfoo = callPackage ...
in
pkgs = pkgs.override {
overrides = self: super: {
myfoo-core = myfoo;
};
}
问题
如何为 services
做到这一点?
添加服务需要您先为您的服务编写服务定义。即,声明服务选项并提供实现的 nix 文件。
假设我们的服务名为 foo
,然后我们为其编写服务定义并将其保存为文件 foo.nix
:
{ config, lib, pkgs, ... }:
with lib; # use the functions from lib, such as mkIf
let
# the values of the options set for the service by the user of the service
foocfg = config.services.foo;
in {
##### interface. here we define the options that users of our service can specify
options = {
# the options for our service will be located under services.foo
services.foo = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Whether to enable foo.
'';
};
barOption = {
type = types.str;
default = "qux";
description = ''
The bar option for foo.
'';
};
};
};
##### implementation
config = mkIf foocfg.enable { # only apply the following settings if enabled
# here all options that can be specified in configuration.nix may be used
# configure systemd services
# add system users
# write config files, just as an example here:
environment.etc."foo-bar" = {
text = foocfg.bar; # we can use values of options for this service here
};
};
例如,对于 Hydra,可以在此处找到此文件:https://github.com/NixOS/hydra/blob/dd32033657fc7d6a755c2feae1714148ee43fc7e/hydra-module.nix。
写完服务定义后,我们可以像这样使用它作为我们的主要配置:
{
network.description = "Web server";
webserver = { config, pkgs, ... }: {
imports = [ ./foo.nix ]; # import our service
services.mysql = {
enable = true;
package = pkgs.mysql51;
};
services.foo = {
enable = true;
bar = "hello nixos modules!";
};
};
}
免责声明:这里可能有一些错别字,我没有测试过。
根据 aszlig 的说法,我们可以这样做:
configuration.nix
{ config, lib, ... }:
{
disabledModules = [ "services/monitoring/nagios.nix" ];
options.services.nagios.enable = lib.mkOption {
# Make sure that this option type conflicts with the one in
# the original NixOS module for illustration purposes.
type = lib.types.str;
default = "of course";
description = "Really enable nagios?";
};
config = lib.mkIf (config.services.nagios.enable == "of course") {
systemd.services.nagios = {
description = "my own shiny nagios service...";
};
};
}
评价一下
$ nix-instantiate --eval '<nixpkgs/nixos>' --arg configuration ./test-disable.nix -A config.systemd.services.nagios.description
"my own shiny nagios service..."

与没有 disabledModules 的对比:
$ nix-instantiate --eval '<nixpkgs/nixos>' --arg configuration ./test-disable.nix -A config.systemd.services.nagios.description
error: The option `services.nagios.enable' in `/home/aszlig/test-disable.nix' is already declared in `/nix/var/nix/profiles/per-user/root/channels/vuizvui/nixpkgs/nixos/modules/services/monitoring/nagios.nix'.
(use '--show-trace' to show detailed location information)
使用 nixops
可以轻松配置如下服务:
{
network.description = "Web server";
webserver = { config, pkgs, ... }:
{
services.mysql = {
enable = true;
package = pkgs.mysql51;
};
但我想延长 services
。例如,使用 override
就像下面 pkgs
所做的那样:
let
myfoo = callPackage ...
in
pkgs = pkgs.override {
overrides = self: super: {
myfoo-core = myfoo;
};
}
问题
如何为 services
做到这一点?
添加服务需要您先为您的服务编写服务定义。即,声明服务选项并提供实现的 nix 文件。
假设我们的服务名为 foo
,然后我们为其编写服务定义并将其保存为文件 foo.nix
:
{ config, lib, pkgs, ... }:
with lib; # use the functions from lib, such as mkIf
let
# the values of the options set for the service by the user of the service
foocfg = config.services.foo;
in {
##### interface. here we define the options that users of our service can specify
options = {
# the options for our service will be located under services.foo
services.foo = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Whether to enable foo.
'';
};
barOption = {
type = types.str;
default = "qux";
description = ''
The bar option for foo.
'';
};
};
};
##### implementation
config = mkIf foocfg.enable { # only apply the following settings if enabled
# here all options that can be specified in configuration.nix may be used
# configure systemd services
# add system users
# write config files, just as an example here:
environment.etc."foo-bar" = {
text = foocfg.bar; # we can use values of options for this service here
};
};
例如,对于 Hydra,可以在此处找到此文件:https://github.com/NixOS/hydra/blob/dd32033657fc7d6a755c2feae1714148ee43fc7e/hydra-module.nix。
写完服务定义后,我们可以像这样使用它作为我们的主要配置:
{
network.description = "Web server";
webserver = { config, pkgs, ... }: {
imports = [ ./foo.nix ]; # import our service
services.mysql = {
enable = true;
package = pkgs.mysql51;
};
services.foo = {
enable = true;
bar = "hello nixos modules!";
};
};
}
免责声明:这里可能有一些错别字,我没有测试过。
根据 aszlig 的说法,我们可以这样做:
configuration.nix
{ config, lib, ... }:
{
disabledModules = [ "services/monitoring/nagios.nix" ];
options.services.nagios.enable = lib.mkOption {
# Make sure that this option type conflicts with the one in
# the original NixOS module for illustration purposes.
type = lib.types.str;
default = "of course";
description = "Really enable nagios?";
};
config = lib.mkIf (config.services.nagios.enable == "of course") {
systemd.services.nagios = {
description = "my own shiny nagios service...";
};
};
}
评价一下
$ nix-instantiate --eval '<nixpkgs/nixos>' --arg configuration ./test-disable.nix -A config.systemd.services.nagios.description
"my own shiny nagios service..."

与没有 disabledModules 的对比:
$ nix-instantiate --eval '<nixpkgs/nixos>' --arg configuration ./test-disable.nix -A config.systemd.services.nagios.description
error: The option `services.nagios.enable' in `/home/aszlig/test-disable.nix' is already declared in `/nix/var/nix/profiles/per-user/root/channels/vuizvui/nixpkgs/nixos/modules/services/monitoring/nagios.nix'.
(use '--show-trace' to show detailed location information)