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.