Title: How to run a NixOS VM as an OpenBSD guest Author: Solène Date: 08 May 2021 Tags: openbsd nixos Description: # Introduction This guide is to help people installing the NixOS Linux distribution as a virtual machine guest hosted on OpenBSD VMM hypervisor. # Preparation Some operations are required on the host but specifics instructions will be needed on the guest as well. ## Create the disk We will create a qcow2 disk, this format allows not using all the reserved space upon creation, size will grow as the virtual disk will be filled with data. ```shell command vmctl create -s 20G nixos.qcow2 ``` ## Configure vmd We have to configure the hypervisor to run the VM. I've chose to define a new MAC address for the VM interface to avoid collision with the host MAC. ```configuration file /etc/vm.conf vm "nixos" { memory 2G disk "/home/virt/nixos.qcow2" cdrom "/home/virt/latest-nixos-minimal-x86_64-linux.iso" interface { lladdr "aa:bb:cc:dd:ee:ff" switch "uplink" } owner solene disable } switch "uplink" { interface bridge0 } ``` (HTM) vm.conf man page ## Configure network We need to create a bridge in which I will add my computer network interface "em0" to it. Virtual machines will be attached to this bridge and will be seen from the network. ```network configuration echo "add em0" > /etc/hostname.bridge0 sh /etc/netstart bridge0 ``` ## Start vmd We want to enable and then start vmd to use the virtual machine. ```rcctl instructions rcctl enable vmd rcctl start vmd ``` ## NixOS and serial console When you are ready to start the VM, type "vmctl start -c nixos", you will get automatically attached to the serial console, be sure to read the whole chapter because you will have a time frame of approximately 10 seconds before it boots automatically (if you don't type anything). If you see the grub display with letters displayed more than once, this is perfectly fine. We have to tell the kernel to enable the console output and the desired speed. On the first grub choice, press "tab" and append this text to the command line: "console=ttyS0,115200" (without the quotes). Press Enter to validate and boot, you should see the boot sequence. For me it took a long time on starting sshd, keep waiting, that will continue after less than a few minutes. ## Installation There is an excellent installation guide for NixOS in their official documentation. (HTM) Official installation guide I had issues with DHCP so I've set the network manually, my network is in 192.168.1.0/24 and my router 192.168.1.254 is offering DNS too. ``` systemctl stop NetworkManager ifconfig enp0s2 192.168.1.151/24 up route add -net default gw 192.168.1.254 echo "nameserver 192.168.1.254" >> /etc/resolv.conf ``` The installation process can be summarized with theses instructions: ```installation instructions sudo -i parted /dev/vda -- mklabel msdos parted /dev/vda -- mkpart primary 1MiB -1GiB # use every space for root except 1 GB for swap parted /dev/vda -- mkpart primary linux-swap -1GiB 100% mkfs.xfs -L nixos /dev/vda1 mkswap -L swap /dev/vda2 mount /dev/disk/by-label/nixos /mnt swapon /dev/vda2 nixos-generate-config --root /mnt nano /mnt/etc/nixos/configuration.nix nixos-install shutdown now ``` Here is my configuration.nix file on my VM guest, it's the most basic I could want and I stripped all the comments from the base example generated before install. ```example configuration file { config, pkgs, ... }: { imports = [ # Include the results of the hardware scan. ./hardware-configuration.nix ]; boot.loader.grub.enable = true; boot.loader.grub.version = 2; boot.loader.grub.extraConfig = '' serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1 terminal_input --append serial terminal_output --append serial ''; networking.hostName = "my-little-vm"; networking.useDHCP = false; # COMMENT THIS LINE IF YOU DON'T WANT DHCP # networking.interfaces.enp0s2.useDHCP = true; # BEGIN ADDITION # all of these variables were added or uncommented boot.loader.grub.device = "/dev/vda"; # required for serial console to work! boot.kernelParams = [ "console=ttyS0,115200n8" ]; systemd.services."serial-getty@ttyS0" = { enable = true; wantedBy = [ "getty.target" ]; # to start at boot serviceConfig.Restart = "always"; # restart when session is closed }; # use what you want time.timeZone = "Europe/Paris"; # BEGIN NETWORK # define network here networking.interfaces.enp0s2.ipv4.addresses = [ { address = "192.168.1.151"; prefixLength = 24; } ]; networking.defaultGateway = "192.168.1.254"; networking.nameservers = [ "192.168.1.254" ]; # END NETWORK # enable SSH and allow X11 Forwarding to work services.openssh.enable = true; services.openssh.forwardX11 = true; # Declare a user that can use sudo users.users.solene = { isNormalUser = true; extraGroups = [ "wheel" ]; }; # declare the list of packages you want installed globally environment.systemPackages = with pkgs; [ wget vim ]; # firewall configuration, only allow inbound TCP 22 networking.firewall.allowedTCPPorts = [ 22 ]; networking.firewall.enable = true; # END ADDITION # DONT TOUCH THIS EVER EVEN WHEN UPGRADING system.stateVersion = "20.09"; # Did you read the comment? } ``` Edit /etc/vm.conf to comment the cdrom line and reload vmd service. If you want the virtual machine to automatically start with vmd, you can remove the "disable" keyword. Once your virtual machine is started again with "vmctl start nixos", you should be able to connect to ssh to it. If you forgot to add users, you will have to access the VM console with "vmctl console", log as root, modify the configuration file, type "nixos-rebuild switch" to apply changes, and then "passwd user" to define the user password. You can set a public key when declaring a user if you prefer (I recommend). # Install packages There are three ways to install packages on NixOS: globally, per-user or for a single run. - globally: edit /etc/nixos/configuration.nix and add your packages names to the variable "environment.systemPackages" and then rebuild the system - per-user: type "nix-env -i nixos.firefox" to install Firefox for that user - for single run: type "nix-shell -p firefox" to create a shell with Firefox available in it Note that the single run doesn't mean the package will disappear, it's most likely... not "hooked" into your PATH so you can't use it. This is mostly useful when you make development and you need specific libraries to build a project and you don't always want them available for your user. # Conclusion While I never used a Linux system as a guest in OpenBSD it may be useful to run Linux specific software occasionally. With X forwarding, you can run Linux GUI programs that you couldn't run on OpenBSD, even if it's not really smooth it may be enough for some situations. I chose NixOS because it's a Linux distribution I like and it's quite easy to use in the regards it has only one configuration file to manage the whole system.