The nixops defaults module

By Simon Lackerbauer | Thu, 08 Nov 2018

Avoiding code repetition in a nixops deployment

As with most configuration management tools, there are some options in nixops that need to be defined for virtually any machine in a deployment. These global options tend to be abstracted in a common base profile that is simply included at the top of a node configuration.

This base profile can be used for including default packages, services or machine configuration usually needed on all machines—like networking debug tools and admin users with access to the whole network.

Nixops, however, provides an easy way to include a default module for all machines of a network at the top level of the deployment configuration. This rather less well-known attribute is simply and effectively called defaults.

The defaults attribute in action

This little example shows a fully functional nixops configuration including a defaults module:

 1# defaults-test.nix:
 2{
 3  network.description = "nixops DEFAULTS test network";
 4
 5  defaults = { pkgs, ... }: {
 6    environment.systemPackages = with pkgs; [ iotop strace tcpdump ];
 7    programs.mtr.enable = true;
 8  };
 9
10  webserver = { ... }: {
11    deployment.targetEnv = "libvirtd";
12    services.nginx = {
13      enable = true;
14      virtualHosts.localhost.locations."/" = {
15        proxyPass = "https://nixos.org";
16      };
17    };
18  };
19
20  database = { pkgs, ... }: {
21    deployment.targetEnv = "libvirtd";
22    services.mysql = {
23      enable = true;
24      package = pkgs.mariadb;
25     };
26  };
27}

To test, just create the deployment and see mtr in action:

$ nixops create defaults-test.nix -d defaults-test
$ nixops deploy -d defaults-test
$ nixops ssh -d defaults-test webserver
[root@webserver:~]# mtr --report -c 4 database
Start: 2018-11-08T15:02:15+0000
HOST: webserver                   Loss%   Snt   Last   Avg  Best  Wrst StDev
  1.|-- database                   0.0%     4    1.2   1.0   0.4   1.2   0.4

As can be surmised from the above configuration example, the defaults attribute’s value is a simple nixops module that will be automatically included in all machine configurations, just like an imports = [ base/profile.nix ]; in each respective node file would include the module given in base/profile.nix.

Instead of specifying it inline, you can—since the module system is used here—import a module at this point.

1{
2  default = { ... }: { imports = [ ./base/profile.nix ]; };
3}

To make it even shorter you can also use the built-in import function here:

1{
2  defaults = import ./base/profile.nix;
3}

This feature is fully documented in the nixops manual.

Do you have a question about Nix?

Just ask us! We would love to talk to you!

Check out our crew