Nixops on Vultr

Published 2018-10-23


Summary🔗

Requirements:

Introduction🔗

NixOS is a Linux distribution based on the functional package manager Nix. It benefits from the full potential of Nix and allows to statically describe your OS and its packages, configuring services and rolling back to previous configurations. Nixops is a tool that allows to describe, configure and manage a set of NixOS machines using the nix language. Nixops benefits from nix and NixOS properties and extends it to a network management.

This post describe how to start using nixops on a virtual machine. I choose vultr as cloud provider because it proposes to boot a VM with an ISO. And NixOS is one of the ISO available, which facilitate the installation. Most of this post should, however, be compatible with other cloud provider.

At the end of this article, one have a running virtual machine with NixOS installed and configured by nixops. The virtual machine can be deployed and configured with nixops. The final installation is the article is directly taken from the official documentation. At the end you should have unleashed the power of nix{,os,ops}, and be able to configure and deploy your own nixops instance to fit your needs

Deploy a Virtual Machine and Install NixOS🔗

The first step, straightforward, is to create an account on Vultr, and to run your first VM instance. Note that the this post uses a VM of a minimum of 1GB of memory, and I had issues to do the installation with less than 1GB of ram.

Once the VM is running, we can just access to the running instance in order to install NixOS. Vultr proposes from its dashboard to access to the instance with a web console. For my part I found it more convenient to change --- temporarily --- the root password and access to the machine with ssh. you may also need to run the ssh server on the VM: systemctl start sshd.

In this post, I will not describe how to install NixOS. The official manual of NixOS is complete and I could not add any additional useful information. In addition the documentation of Vultr also describes the full procedure.

When the installation is finished, I recommend to create a snapshot of your installation. It will allow to restore NixOS and prevent from reiterate the whole installation in case of failure.

Nix🔗

Now that we a running virtual machine with a NixOS installation, we can start working with nix. Nix is very easy to install, to install it on your local computer: curl https://nixOS.org/nix/install | sh. Don't forget to read the end of the installation, you may have to source a file ;)

Then using the fresh installation, we can directly install Nixops: nix-env -iA nixpkgs.nixops

Nixops is a tool that allows you to statically describe the services running on a machine, or a set of machine, and connect them together. The strong point of using Nixops is that we can benefits from all the good properties of the Nix package manager and NixOS.

Using Nixops is simple, start by creating a file called configuration-vultr.nix, and add the following content.


int main() {}

{
  network.description = "Web server";

  webserver =
    { config, pkgs, ... }:
    {
      imports = [ # Include the results of the hardware scan.
        ./hardware-configuration.nix
      ];

      services.httpd.enable = true;
      services.httpd.adminAddr = "alice@example.org";
      services.httpd.documentRoot = "${pkgs.valgrind.doc}/share/doc/valgrind/html";
      networking.firewall.allowedTCPPorts = [ 80 ];
    };
}

This is example is directly taken from the official Nixops documentation. It defines a machines that enable the httpd service to serve the content of the valgrind documentation. If you are familiar with nix, you can notice that documentRoot is pointing on a derivation. The derivation will be built and translated to the path of the output doc of the derivation on the store. This example remains simple as it only deploy a service. However we can already see that we can reference nix packages in the source code of the network, which is a powerful feature.

The next file nixops will require to deploy your virtual machine is the hardware definition of the VM. The easiest way to obtain this file is to take it directly from the VM. Normally, if you already installed nixOS, you had to use the command nixOS-generate-config --root /mnt, which generate two files. The first one is the /etc/nixOS/configuration.nix, which is not required because nixops will overwrite it with our previous file. The second file, however is the file /etc/nixOS/hardware-configuration.nix, which describe the device that contains your installation. We can download it, and put it next to the previous one. Now, your folder should have the following files:

$cd nixops-kodama/
ls -l

configuration.nix
hardware-configuration.nix

At this point, the machine is configured to run a http service, however we need to tell to NixOS where to find our virtual machine. We just need to add the following line to the file configuration.nix.

deployement.targetHost = "1.2.3.4";

The next modification we need to apply, is to enable the ssh server on our configuration. Otherwise, the virtual machine will be inaccessible after the first deployment. Luckily, we are using Nix, nothing is more simple than adding a new service. Adding the following line will do the trick:

services.openssh.enable = "yes";

At this point, the configuration file should look like:

{
  network.description = "Web server";

  webserver =
    { config, pkgs, ... }:
    {
      imports = [ # Include the results of the hardware scan.
        ./hardware-configuration.nix
      ];

      deployement.targetHost = "1.2.3.4";
      services.openssh.enable = "yes";

      services.httpd.enable = true;
      services.httpd.adminAddr = "alice@example.org";
      services.httpd.documentRoot = "${pkgs.valgrind.doc}/share/doc/valgrind/html";
      networking.firewall.allowedTCPPorts = [ 80 ];
    };
}

Now, that we configured our server, we can start to create a Nixops state. We need to run the command:

nixops create /path/to/configuration.nix -d vmv

This command will create the new state for our vm, but it will not trigger the installation yet. Note that the argument -d vmv creates an alias for your state.

We can directly check if Nixops created our instance state.

$nixops list
+-------------+--------+-----------------+------------+------------+
| UUID        | Name   | Description     | # Machines |    Type    |
+-------------+--------+-----------------+------------+------------+
| 7d7f8859-d8 | vmv    | Web server      |          1 |    none    |
+-------------+--------+-----------------+------------+------------+

Finally, to deploy the instance we need to run the command:

nixops deploy -d vmv

Running Out of Space🔗

It seems that the version of nixops delivered by the channel 18.09, has memory management issues with machines with a small amount of memory. In my case, for a VM with 1024M of memory I had trouble deploying the virtual machine with nixops. The error was:

vps.......> error: out of memory
vps.......> error: unexpected end-of-file

A simple workaround is to create a swapfile for your virtual machine. The following article describe this procedures: linux-add-a-swap-file-howto. One can access to the virtaul machine for creating and activating the swap file..

And you are ready to go: nixops deploy -d vmv.

However note that if you restart the machine, the swap file will not be activated. To make it activated, one can add the following lines to your hardware-configuration.nix.

swapDevices =
  [ { device = "/swapfile1"; size = 1024; }
];

Tada, you should be able to access to the valgrind documentation, at the address http://1.2.3.4/.

Refs🔗