| 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 | |
| } | |
| ``` | |
| 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. | |
| 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 … | |
| 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. |