hey there, building on the recent xen work in nixpkgs - I have created a NixOS template which you can find here:
this is my first stab at creating public nix packages / modules so apologies in advance
many of the basics are working at this point, details in the README. no RPM yet for aid with install. if you want to try it out before I get that working you should be able to use the nixos installer under HVM mode, and then can switch over to a config using this with PVH.
Post a Qubes Backup of the template with the password “a” on github or someplace else and I will look into it. Really if I have to put hours just to install… you lost me. Don’t ask for mine!
Here is an idea based on my understanding of Nix history. Knoppix (Linux written in Assembly) is the precursor of Nix. The last act of Knopper was a Debian kernel.
I would take a ISO editor to a very good Debian eliminate a lot of things, add Qubes functions and add Nix. This has been done already and it is not easy. This is very hard because you have to configure a lot of things and make the Nix part retentive/persistent. I guess solicitation for Qubes template is the same as solicitation of drugs or beggin on a street corner on this forum. Let them shoot themselves in the foot.
Just as a friendly reminder for anyone who might be reading, Qubes Backups will contain metadata about qubes which are not selected for inclusion in the backup (you can see this warning in the bold text at the bottom of the first screen that opens after selecting “Qubes Backup” from the “Qubes Tools” menu. This may or may not be relevant to your threat model, but posting a public backup is potentially dangerous even if none of the qubes you selected contain sensitive data.
Thanks @evq for your work on this. Like @Rnd3sB3g13rng I’m not 100% sure of the process.
I tried to install nixos via .iso in a hvm and couldn’t even get that far. When I try to boot it I get:
SeaBIOS (version 1.13.0-3.fc32)
Machine UUID 7a...
Booting from Hard Disk...
GRUB _
this is probably down to my HVM nativity, but any pointer would be much appreciated. Here is my process:
download nixos iso
create HVM qvm-create nixos --class StandaloneVM --label red --prop virt_mod=hvm --prop kernel='' --prop size=40G --prop private=40G --prop memory=8000 --prop maxmem=16000 --prop default_dispvm=''
set system storage size to 30gb
launch with iso image qvm-start nixos --cdrom=disp534:/home/user/Downloads/nixos-minimal.iso
setup networking
go to VM settings identifiy:
HVM IP addres: 10.137.0.49
gateway addres: 10.138.35.49
Virtual DNS: 10.139.1.1, 10.139.1.2
set up IP address
sudo ip a add 10.137.0.49/32 dev enX0
sudo ip l set dev enX0 up
configure connection to net qube
sudo ip r add 10.138.35.49 dev enX0
sudo ip r add default via 10.138.35.49
Also, it looks like you missed the third backtick in the “generate config” section, causing the code snippets and commentary to be reversed (happens to everyone sometimes ).
Thanks @skyvine. It isn’t obvious how to edit the post to correct the formatting.
Anyway here is the grub.cfg generated by nixos-install:
# Automatically generated. DO NOT EDIT THIS FILE!
search --set=drive` --fs-uuid 6f2b...ee8
if [ -s $prefix/grubenv ]; then
load_env
fi
# grub-reboot sets a one-time saved entry, which we process here and
# then delete.
if [ "${next_entry}" ]; then
set default="${next_entry}"
set next_entry=
save_env next_entry
set timeout=1
set boot_once=true
else
set default=0
set timeout=5
fi
set timeout_style=menu
function savedefault {
if [ -z "${boot_once}"]; then
saved_entry="${chosen}"
save_env saved_entry
fi
}
# Setup the graphics stack for bios and efi systems
if [ "${grub_platform}" = "efi" ]; then
insmod efi_gop
insmod efi_uga
else
insmod vbe
fi
insmod font
if loadfont ($drive1)//converted-font.pf2; then
insmod gfxterm
if [ "${grub_platform}" = "efi: ]; then
set gfxmode=auto
set gfxpayload=keep
else
set gfxmode=1024x768
set gfxpayload=text
fi
terminal_output gfterm
fi
background_color `#2F302F`
insmod png
if background_image --mode `normal` ($drive1)//background.png; then
set color_normal=white/black
set color_highlight=black/white
else
set menu_color_normal=cyan/blue
set menu_color_highlight=white/blue
fi
menuentry "NixOS" --class nixos --unrestricted {
search --set=drive1 --fs-uuid 6f2b...ee8
linux ($drive1)//kernels/1kp51...zm4-linux-6.6.52-bzImage init=/nix/store/i7z1q...sx2-nixos-system-nixos-24.05.5287.759537f06e69/init loglevel=4
initrd ($drive1)//kernels/m1xly...kzh-initrd-linux-6.6.52-initrd
}
submenu "NixOS - All configurations" --class submenu {
menuentry "NixOS - Configuration 1 (2024-09-27 - 24.05.5287.759537f06e69)" --class nixos {
search --set=drive1 --fs-uuid 6f2b...ee8
linux ($drive1)//kernels/1kp51...zm4-linux-6.6.52-bzImage init=/nix/store/i7z1q...sx2-nixos-system-nixos-24.05.5287.759537f06e69/init loglevel=4
initrd ($drive1)//kernels/m1xly...kzh-initrd-linux-6.6.52-initrd
}
}
Does the error message you printed appear after selecting an entry in the boot menu or do you not even get to the boot menu?
Can you load an ISO and confirm that the filesystem with the UUID listed in:
search --set=drive1 --fs-uuid 6f2b...ee8
exists? You can use findfs UUID=6f2b...ee8 (with the full hash instead of the …). If it does, can you mount it and confirm that the files from the line following the search command exist? In particular, /kernels/...-bzimage and /nix/store/.../init.
I suspect the problem is that NIXROOT is not getting mounted. In my grub.cfg’s menu entries the linux command contains root=GUIX_ROOT but there isn’t anything similar in yours. As a quick test you should be able to add root=NIXROOT manually to that line, anywhere after the *-bzImage should be fine but mine is immediately after it. The file will probably have read-only permissions because it was copied from the store but it shouldn’t be a symlink to the store so making it writable is safe. You might want to double-check that in case NixOS is different, but I don’t think symlinking would technically work for files on /boot. The manual edits will get overwritten the next time you reconfigure but this will prove/disprove the root of the problem. If this fixes it we can start looking at a long-term solution.
I could write the file using sudo. I made the change you suggested but still get this:
SeaBIOS (version 1.13.0-3.fc32)
Machine UUID 7a88b9...ab5
Booting from Hard Disk...
GRUB _
I then commented out the selection section and replaced it with timeout=10 and I still didn’t get presented with a menu. I am not sure the grub.cfg file is being used?
Should that machine UUID correlate some UUID on xvda? I cannot find a reference to it anywhere else.
My assumption is that the UUID is what Xen assigned to the VM. You can double-check this by running xenstore-read -f /vm | grep 'name = "nixos"' in a dom0 terminal. The -f tells it to print the full path in every line, and the UUID appears in the path.
I’m thinking about why Grub might fail to find the config. You can mount the filesystem and it has the configuration file in it, so that should be fine. My machine also uses ext4 so unless your Grub has a strange configuration that shouldn’t be the problem. Personally, I don’t keep /boot on my BIOS boot partition. From what I understand from random things I’ve read in various places (so not the most reliable information, but it’s lined up with my experiences) the BIOS uses a very early part of the disk which the filesystem doesn’t use for historical reasons that are technically unrelated to the BIOS. So it’s supposed to be safe to do that, and the fact that you’re able to explore the filesystem and the output indicates that Grub is loading (but hitting some error condition) makes me think that this isn’t the source of the problem.
Some loosening up of qubes security needs to be implemented, …
I don’t think I’ll be changing to that. heh
However, would that imply that with their work it would be easier to make a NixOS template now? (like, them already having some of the qubes packages done)
IMO it would be easiest if everybody was pooling their efforts. If I was working on NixOS instead of Guix I would look into what changes need to be made in NixOS to support the secure update process and add an explainer to the GitHub issue.
But yes, I would assume that their package definitions will include at least some of the work required to build a fully supported NixOS template.
QREXEC_CLIENT_DOM0 = "/usr/bin/qrexec-client"
QREXEC_CLIENT_VM = "/usr/bin/qrexec-client-vm"
RPC_MULTIPLEXER = "/usr/lib/qubes/qubes-rpc-multiplexer"
VERSION = None
if pathlib.Path(QREXEC_CLIENT_DOM0).is_file():
VERSION = "dom0"
elif pathlib.Path(QREXEC_CLIENT_VM).is_file():
VERSION = "vm"
The logic to determine whether we are running on dom0 or domU relies on the existence of a file specific to dom0 or domU. In the rpm specs these files are installed by either qubes-core-qrexec-dom0 or qubes-core-qrexec-vm.
In Nix-based systems, the equivalent of this would be installing to separate outputs. However, this creates a problem because of the paths to the executables. In order for this to work on Nix-based systems we need to update those paths to be store paths. However, as Nix scans files for hashes to other packages/outputs in order to find implicit dependencies this means that the base package is dependent on both dom0 and domU. This causes two problems.
The first problem is that this creates a circular dependency: both the dom0 and domU packages depend on the base package for shared code, but now the base package also depends on both of them. Nix explicitly forbids circular dependencies, and even if it didn’t it’s pretty smelly.
The second problem is that it means that both the dom0 and domU packages need to be installed on every machine (this is currently what the pull request does because it does not have separate outputs). This is wrong in principle and it breaks the above version-checking logic on domU (the pull request wouldn’t run into this problem because they’re focused on dom0, and the logic coincidentally checks for the dom0 path first).
My initial thought is to put 2 values in QubesDB: one noting whether or not the current VM is dom0 and one with the path to the qrexec-client executable. This way qrexec can check the database and not worry about hardcoded paths.
The multiplexer path is fine because that’s stored in the base package.
please read the rest of the README to see notes about getting nix to play nicely with the qubes update proxy as well as for a list of working / untested / not working features.
I’m curious, do you have a config with X11, and some apps working? I would love to give your config a quick spin to see what it’s capable of without investing too much time into the nix expression myself.