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. |