Did you know that it is rather easy to setup a VM to test your NixOs configuration?
# flake.nix
{
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
outputs = { self, nixpkgs, ... }:
let
system = "x86_64-linux";
in
{
# test is a hostname for our machine
nixosConfigurations.test = nixpkgs.lib.nixosSystem {
inherit system;
modules = [
./configuration.nix
];
};
};
}# configuration.nix
{ config, lib, pkgs, ... }: {
# customize kernel version
boot.kernelPackages = pkgs.linuxPackages_5_15;
users.groups.admin = {};
users.users = {
admin = {
isNormalUser = true;
extraGroups = [ "wheel" ];
password = "admin";
group = "admin";
};
};
virtualisation.vmVariant = {
# following configuration is added only when building VM with build-vm
virtualisation = {
memorySize = 2048; # Use 2048MiB memory.
cores = 3;
graphics = false;
};
};
services.openssh = {
enable = true;
settings.PasswordAuthentication = true;
};
networking.firewall.allowedTCPPorts = [ 22 ];
environment.systemPackages = with pkgs; [
htop
];
system.stateVersion = "23.05";
}git init # skip this step if you are inside already tracked repository
git add . # flakes requires at least tracking the files
nixos-rebuild build-vm --flake .#test
# expose port 22 from guest
export QEMU_NET_OPTS="hostfwd=tcp::2221-:22"
result/bin/run-nixos-vm# ssh onto the machine
ssh -oUserKnownHostsFile=/dev/null -oStrictHostKeyChecking=no admin@localhost -p 2221
@sanzoghenzo Yup, but this can easily be simplified with a function if you'd like to avoid repetition. For example:
Which can also be done for the system config:
Note: The
reckeyword allows us to refer tovm-testfrom within the same attrset (see Nix language basics β nix.dev).Also, you can include the
QEMU_NET_OPTSenv var into your dev shell:Just like with apps, you can write more devShells according to your needs and activate them with
nix develop .#devShells.<name>.Alternatively, you can forward the port in the system config with:
Notes:
nix run .#<name>andnix develop .#<name>instead ofnix run .#apps.<name>andnix develop .#devShells.<name>Now, we can refactor things a bit and import
mkAppVMandmkSystemfrom a separate file, which might make things cleaner:utils.nix
Which leaves us with this final configuration:
flake.nix
Thanks for suggesting this as it looks like an interesting and flexible tool, but for this usecase it makes more sense to me to use apps because it integrates directly with Nix, thus leveraging its full capabilites. Also, after removing the boilerplate, the Nix code looks cleaner and more readable to me.
That said, I'm curious if
taskand similar tools would be more suitable for more complex cases.