nixos VM in lxd

Setting up VM images with nixos is incredibly powerful when coupled with declarative nature of nix language itself.

I am using it for running homelab type services and lab type setups. Here is how I have it working for me:

Create the VM

This is a snippet from a shell script I use

name=nixos1
img=nixos/24.05
cpu=4
mem=8
disk=100
incus launch images:$img $name \
    --vm \
    -c limits.cpu=4 \
    -c limits.memory=${mem}GiB \
    -c security.secureboot=false \
    --device root,size=${disk}GiB

Configure the VM

Assuming you have some nixos configuration, you can upload the config
and update the VM.

incus file push ./configuration.nix $name/etc/nixos/configuration.nix
incus exec "$name" -- /run/current-system/sw/bin/bash -i -c "nixos-rebuild switch"

Example Configuration

configuration.nix

    { config, pkgs, lib, modulesPath, ... }:

    {
      imports =
        [
          # Include the default lxd configuration.
          "${modulesPath}/virtualisation/lxd-virtual-machine.nix"
          # Include the container-specific autogenerated configuration.
          ./lxd.nix
        ];

      boot.supportedFilesystems = [ "nfs" ];

      networking = {
        hostName = "nixos1"; # Define your hostname.
        dhcpcd.enable = false;
        useDHCP = false;
        useHostResolvConf = false;
      };


      # For plex...
      virtualisation.oci-containers.backend = "docker";

      virtualisation.oci-containers.containers = {
        plex = {
          image = "plexinc/pms-docker";
          volumes = [
            "/srv/plex/config:/config"
            "/srv/plex/tmp:/transcode"
            "/data/movies:/data/movies"
            "/data/TV:/data/TV"
          ];
          extraOptions = [
            "--network=host"
          ];
          environment = {
            PLEX_CLAIM = "claim-XXX";
            TZ = "America/Los_Angeles";
          };
        };
      };

      programs.bash.enableCompletion = true;
      services.jellyfin.enable = true;

      environment.systemPackages = with pkgs; [
        vim
        wget
        curl
        emacs
        git

      ];

      services.openssh.enable = true;
      networking.firewall.enable = false;

      systemd.network = {
        enable = true;
        networks."50-enp5s0" = {
          matchConfig.Name = "enp5s0";
          networkConfig = {
            DHCP = "ipv4";
            IPv6AcceptRA = true;
          };
          linkConfig.RequiredForOnline = "routable";
        };
      };


      system.stateVersion = "24.05"; # Did you read the comment?
    }