NixOS: Enabling LXD digital machines utilizing Flakes

Nixpkgs is an ever-increasing assortment of software program packages for Nix and NixOS. Even with greater than 80,000 packages, you simply run in a scenario the place there’s a performance that’s not but applied.

Earlier this yr, we wrote a tutorial on easy methods to implement your personal package deal in NixOS. The implementation of the package deal within the system was tedious and required retaining observe of the package deal you wished to implement.

Let’s dive right into a sensible instance: LXD is a container and digital machine supervisor. It endorses digital machines natively since LXD 4.0. Nevertheless, operating on NixOS breaks the function, and we’ve got to search out workarounds to make use of it. To permit LXD to start out digital machines on NixOS, we’d like a repair, and we wish it to be each reproducible and moveable.

To take action, we’re utilizing the lxd-agent function which successfully repair the aforementionned subject. It was launched by astridyu, a contributor to nixpkgs. It has not but been applied within the Grasp department of nixpkgs and is, as of 19/04/2022, a pull request.

Our aim is to combine the pull request to our nixpkgs to have the ability to begin digital machines. For this, we are going to use Flakes. It’s an experimental function of the Nix package deal supervisor that enables reproducibility within the deployment of dependencies. We use it to assemble completely different nixpkgs collectively. It’s a trait referred to as composability.

If the pull request has been merged, this tutorial turns into irrelevant. To get the performance, replace your Nix or NixOS to the present model of the grasp department.


Step 1 – Putting in ZFS

ZFS is a filesystem that we use to generate storage swimming pools in LXD. It’s the solely filesystem supported by this methodology, for now.

ZFS have to be put in on the NixOS machine previous to the set up of LXD. To take action, go to your configuration.nix file situated in /and many others/nixos/ and add the next strains to your configuration.

boot =         
  initrd.supportedFilesystems = [ "zfs" ];        
  supportedFilesystems = [ "zfs" ];         
  zfs.requestEncryptionCredentials = true;  


  kernelParams= [ "nohibernate" ];

providers.zfs =    
  autoScrub.allow = true;                  
  autoSnapshot.allow = true;               

Within the file, the networking.hostId property have to be set. It’s a bit tough as a result of it solely accepts 32bit ID that you just generate on the terminal with head -c 8 /and many others/machine-id.

With this ID, go to your configuration file and set it.

networking = 
  hostId = "";

Now, rebuild the swap drive. That is achieved by doing sudo nixos-rebuild swap.

If the construct fails as a result of you have already got LXD put in, confer with this part of the article.

Step 2 – Putting in Flakes

To put in Flakes, merely put, in configuration.nix:

nix = 
  package deal = pkgs.nixFlakes; 
  extraOptions = ''experimental-features = nix-command flakes'';

You should rebuild your swap drive once more.

Getting began with Flakes

We’ll draw on the ability of Flakes to patch our system by combining completely different variations of nixpkgs. The variations we are going to use are:

You possibly can observe the pull request with its quantity: #166858.

Then, we are going to proceed to override the LXD package deal from the nixpkgs grasp department model with astridyu’s nixpkgs lxd-vms department model to get the lxd-agent function utilized onto LXD.

To make use of Flakes, it’s required to create a flake.nix file in /and many others/nixos. That is finished by doing sudo nano /and many others/nixos/flake.nix.

On this file, we describe which nixpkgs repository we need to add to our configuration, and easy methods to merge them.

Be aware: Confirm that your hostname, is outlined below the networking.hostName discipline in your configuration. It’s required.

  description = "NixOS Configuration of LXD";

  inputs = 
    nixpkgs.url = "nixpkgs/grasp";

    nixpkgs-lxdvm = 
      url = "github:astridyu/nixpkgs/lxd-vms";

  outputs =  self, nixpkgs, nixpkgs-lxdvm :
      system = "x86_64-linux";
      overlay-lxdvm = ultimate: prev: 
         lxdvm = import nixpkgs-lxdvm 
           inherit system;
           config.allowUnfree = true;
      nixosConfigurations."" = nixpkgs.lib.nixosSystem 
        inherit system;
        modules = [
          ( config, pkgs, ... :  nixpkgs.overlays = [ overlay-lxdvm ]; )

Putting in LXD

We should modify our configuration.nix to allow LXD virtualization.

boot.kernelModules = ["vhost_vsock"];

virtualisation = 
  lxd = 

    package deal = pkgs.lxdvm.lxd.override useQemu = true;;


We rebuild the swap drive. It’s required to make use of the --impure possibility upon rebuilding whether it is requested by the system.

The explanation behind that is that Flakes runs in pure analysis mode which is underdocumented. Flakes forbids the utilization of absolute paths, which may trigger the analysis to be impure. This may occasionally occur as a result of we’re operating unsupported packages.

Getting began with LXD and Digital Machines

To get began with LXD, we advocate that you just initialize a storage pool. That is finished by sudo lxd init.

Afterwards, questions are requested regarding the first storage pool that LXD creates. We advocate this configuration for the primary utilization.

Would you want to make use of LXD clustering? (sure/no) [default=no]: no
Do you need to configure a brand new storage pool? (sure/no) [default=yes]: sure

Title of the brand new storage pool [default=default]: test-storage

Title of the storage backend to make use of (btrfs, dir, zfs) [default=zfs]: zfs

Create a brand new ZFS pool? (sure/no) [default=yes]:

Would you want to make use of an current empty block machine (e.g. a disk or partition)? (sure/no) [default=no]:

Measurement in GB of the brand new loop machine (1GB minimal) [default=30GB]:

Would you want to connect with a MAAS server? (sure/no) [default=no]:

Would you prefer to create a brand new native community bridge? (sure/no) [default=yes]:

What ought to the brand new bridge be known as? [default=lxdbr0]: test-bridge

What IPv4 tackle needs to be used? (CIDR subnet notation, “auto” or “none”) [default=auto]:

What IPv6 tackle needs to be used? (CIDR subnet notation, “auto” or “none”) [default=auto]:

Would you just like the LXD server to be obtainable over the community? (sure/no) [default=no]:

Would you want stale cached photographs to be up to date robotically? (sure/no) [default=yes]:

Would you want a YAML "lxd init" preseed to be printed? (sure/no) [default=no]:

When there isn’t any response, default is assumed.

As soon as the storage pool is configured, new digital machines may be initialized with lxc launch --vm -s . It robotically downloads the picture of your digital machine and units one up.

To verify your digital machines, do lxc ls.

Widespread points

If the rebuild fails, it is because of LXD already being put in. This results in nixos-rebuild swap not succeeding as a result of an LXD storage pool already exists. It implies that volumes are nonetheless mounted, and you have to delete them as a result of it’s essential to rebuild LXD from scratch.

Begin by regenerating your hardware-configuration.nix by doing nixos-generate-config.

On this file, the trail to your mounted volumes is talked about, and you have to dismount and take away them within the following means:

  • sudo umount -v /var/lib/lxd/storage-pools/ to dismount the storage pool.
  • sudo rm -r /var/lib/lxd to delete the entire LXD folder.

Rebuilding your system is critical once more.


Congratulations! You at the moment are in a position to launch digital machines utilizing LXD on NixOS, and also you discovered easy methods to use flakes to create an overlay in your nixpkgs.

This methodology will turn out to be out of date as soon as the pull request is merged, nevertheless it stays related if you wish to combine options that aren’t within the grasp department.