- mv /etc/nixos/ /etc/nixos.bak
- ln -s /home/nx/nixos-config /etc/nixos
- sudo nixos-rebuild switch --flake ".#hp"
- Add entry to
vms/registry.nix, e.g.:{ name = "nvim"; short = "n"; ip = "10.0.0.1"; autostart = true; nat = true; sshKeyName = "nvim-vm"; extraSSH = { RemoteForward = "4713 localhost:4713"; }; }
- Add a local VM definition to
vms/definitions.nix - Create the VM module at
vms/{name}/default.nix- Create a host ssh key for the VM:
ssh-keygen -C my-vm
- Create a host ssh key for the VM:
- If the VM should participate in file sharing between VMs, use on the host:
vmcopy-keys <new-vm-name>and rebuild again - Import modules as needed; examples now live in the VM
default.nixfiles such asvms/nvim/default.nix
- cp-vm {name} privat.asc public.asc
- in vm: gpg --import privat.asc and gpg --import public.asc
chmod 700 ~/.gnupg
chmod 600 ~/.gnupg/*
gpg --list-keys
gpg --edit-key <KEY-ID>
# dann im GPG-Prompt:
# trust
# 5
# y
# quit- gh auth login
- To increase the size of a .img image file by 30GB:
sudo truncate -s +30G filename.img- After enlarging the .img file resize it in the vm:
lsblk
sudo resize2fs /dev/vdX- sudo iptables -I INPUT 1 -p tcp --dport 22 -s 10.0.0.1 -j ACCEPT
- And directly remove it again:
- sudo iptables -D INPUT -p tcp --dport 22 -s 10.0.0.1 -j ACCEPT
- https://nikhilism.com/post/2023/remote-dbus-notifications/
- Implemented in common-config.nix and registry.nix (changed ssh.nix logic for it to make it possible to have the same key twice)
- Configured dbus-proxy
The system now follows a more Qubes-like split:
- the host is mainly responsible for:
- hypervisor duties
- local L2 plumbing
- running MicroVMs and libvirt
sys-netis the main external network boundary- regular MicroVMs use the internal host bridge and route through
sys-net - libvirt guest trust zones are bridged on the host, but L3/NAT/DHCP policy for migrated external zones lives in
sys-net
vm-internal- host internal bridge for MicroVMs
- host address:
10.0.0.254/24 sys-netrouter address:10.0.0.253/24
virbr0- bridge-backed libvirt network for
default - guest-facing gateway is provided by
sys-neton192.168.122.1
- bridge-backed libvirt network for
virbr1- bridge-backed libvirt network for
Whonix-External - guest-facing gateway is provided by
sys-neton10.0.2.2
- bridge-backed libvirt network for
virbr2Whonix-Internal- currently kept as a separate protected trust domain
Host systemd-networkd must not manage libvirt vnet* interfaces.
The fix is in machines/common-configuration.nix:
"38-vnet-libvirt-ignore" = {
matchConfig.Name = "vnet*";
linkConfig.Unmanaged = "yes";
};Without this, host systemd-networkd reconfigures libvirt tap devices and breaks their bridge forwarding state.
The host still uses sys-net as its default gateway via vm-internal, but host egress is now intended to stay minimal.
Current design goal:
- host may reach VMs for management
- VMs should not reach the host by default
- host internet should ideally be restricted to maintenance traffic such as:
- SSH
- HTTP/HTTPS
- DNS
- NTP
- ICMP for diagnostics
This restriction is enforced in vms/sys-net/default.nix on traffic coming from host address 10.0.0.254 via vm-lan.
Printing and mDNS/Avahi service ownership were moved off the host and into sys-net.
sys-netnow runs CUPS and Avahi- the
officeVM tunnels tosys-netinstead of to the host - in the
officeVM,/root/.ssh/print-gatewayis the private key used to SSH tosys-net - the matching public key must be authorized on
sys-net
Note: this printer migration is configured, but end-to-end runtime testing is still pending.
- virsh list --all --name
- virsh dumpxml mein-vm-name > /pfad/zu/deinem/backup/mein-vm-name.xml
- RESTORE: sudo rsync -avh --progress --sparse /run/media/nx/Backup/nixos-host/tails-amd64-6.15.1.img /run/media/nx/Backup/nixos-host/Whonix-Gateway.qcow2 /var/lib/libvirt/images/
- RESTORE: sudo virsh define /pfad/zu/deinem/backup/mein-vm-name.xml
vm: mpv http://192.168.178.20:8082/stream host: wl-screenrec --output eDP-1 | ffmpeg -re -i - -f mpegts -codec:v mpeg1video -b:v 3000k -bf 0 http://0.0.0.0:8082/stream
- Actually only sharing should be on per module basis per vm which participates in sharable. If that could be possible with wprs?
- sudo modprobe iwlwifi
nmcli radio allnmcli radio wifi on-
Test migrated printing path via
sys-netend-to-end -
Is there any virtue in exposing nvim to the host? Remove the host-share and implement proper write back or remove exposing host to nvim.
-
Remove not strictly needed host software
-
think over dropping zellij and zsh on the host
-
modularize config
-
restructure vms/ vm folders should not live on the same level as modules/ vmcopy-keys/ etc.
-
fix steam-vm bug: reboot is needed -> currently no way to do that. Maybe automate early reboot after first start and logging specific issue as trigger.
-
improve steam-vm: initial wlserver: backend/hedless... is taking quiet long till steam starts (about 30s)
-
let steam-vm participate in file sharing?
-
think about removing fluxbox workflow. what's with wine vm? a libvirt vm could be an alternative. -> kind of have done that, but wine-vm is still experimental and probably needs hyprland.
-
Monitor occasionally occurring shared libs error in nvim-vm
-
Monitor element-desktop tray issue
-
Monitor bug that occasionally occurs at boot: Bootscreen isn't displayed and tty seems frozen till password is typed in blindly and boot finished successfully
sudo dmesg -T | grep -iE "drm" [Mi Mai 6 19:02:30 2026] ACPI: bus type drm_connector registered [Mi Mai 6 19:02:30 2026] simple-framebuffer simple-framebuffer.0: [drm] Registered 1 planes with drm panic [Mi Mai 6 19:02:30 2026] [drm] Initialized simpledrm 1.0.0 for simple-framebuffer.0 on minor 0 [Mi Mai 6 19:02:30 2026] simple-framebuffer simple-framebuffer.0: [drm] fb0: simpledrmdrmfb frame buffer device [Mi Mai 6 19:02:31 2026] i915 0000:00:02.0: [drm] Found alderlake_s/raptorlake_s (device ID a788) integrated display version 12.00 stepping D0 [Mi Mai 6 19:02:31 2026] i915 0000:00:02.0: [drm] VT-d active for gfx access [Mi Mai 6 19:02:31 2026] i915 0000:00:02.0: [drm] Using Transparent Hugepages [Mi Mai 6 19:02:31 2026] i915 0000:00:02.0: [drm] Finished loading DMC firmware i915/adls_dmc_ver2_01.bin (v2.1) [Mi Mai 6 19:02:31 2026] i915 0000:00:02.0: [drm] GT0: GuC firmware i915/tgl_guc_70.bin version 70.49.4 [Mi Mai 6 19:02:31 2026] i915 0000:00:02.0: [drm] GT0: HuC firmware i915/tgl_huc.bin version 7.9.3 [Mi Mai 6 19:02:31 2026] i915 0000:00:02.0: [drm] GT0: HuC: authenticated for all workloads [Mi Mai 6 19:02:31 2026] i915 0000:00:02.0: [drm] GT0: GUC: submission enabled [Mi Mai 6 19:02:31 2026] i915 0000:00:02.0: [drm] GT0: GUC: SLPC enabled [Mi Mai 6 19:02:31 2026] i915 0000:00:02.0: [drm] GT0: GUC: RC enabled [Mi Mai 6 19:02:32 2026] i915 0000:00:02.0: [drm] Registered 4 planes with drm panic [Mi Mai 6 19:02:32 2026] [drm] Initialized i915 1.6.0 for 0000:00:02.0 on minor 1 [Mi Mai 6 19:02:32 2026] fbcon: i915drmfb (fb0) is primary device [Mi Mai 6 19:02:32 2026] i915 0000:00:02.0: [drm] fb0: i915drmfb frame buffer device [Mi Mai 6 19:02:55 2026] systemd[1]: Load Kernel Module drm skipped, unmet condition check ConditionKernelModuleLoaded=!drm
- Same on 14.05.2026
-
create sys-firewall
lspci -nn | grep -E "VGA|3D|Audio" nvidia-smi || true ls -lah /dev/dri sudo dmesg -T | grep -iE "nvidia|drm|nouveau" | tail -n 200 sudo cat /var/log/steam-autostart.log || true
~#@❯ sudo cp -f --reflink=auto ./result-steam-qcow2/steam-os.qcow2 /var/lib/libvirt/images/steam-os.qcow2 ~#@❯ sudo sync ~#@❯ sudo stat -c '%n inode=%i size=%s mtime=%y' /var/lib/libvirt/images/steam-os.qcow2 /var/lib/libvirt/images/steam-os.qcow2 inode=32506532 size=9143189504 mtime=2026-01-07 15:40:27.739643137 +0100
-
Geräte vor VM-Start freigeben:
Sorge dafür, dass die USB- und PCI-Geräte vor dem VM-Start nicht vom Host verwendet werden.
Prüfe mit:lsof /dev/bus/usb/*/* fuser /dev/bus/usb/*/* -
Automatisches Unbinden der Geräte:
Füge ein Skript oder einen systemd-Service hinzu, der vor dem VM-Start die Geräte unbindet:echo '1-1' > /sys/bus/usb/drivers/usb/unbind(Passe die Busnummer an dein Gerät an.)
-
VFIO-Binding sicherstellen:
Stelle sicher, dass die PCI-Geräte vor dem VM-Start an VFIO gebunden sind:echo 0000:02:00.0 > /sys/bus/pci/devices/0000:02:00.0/driver/unbind echo 8086 1234 > /sys/bus/pci/drivers/vfio-pci/new_id echo 0000:02:00.0 > /sys/bus/pci/drivers/vfio-pci/bind(IDs und Pfade anpassen!)
-
systemd-Unit für sauberes Binding:
Erstelle eine systemd-Unit auf dem Host, die vor dem VM-Start die Geräte vorbereitet.
~#@❯ rm windowrules.conf ~#@❯ ln -s /home/nx/nixos-config/home/windowrules.conf /home/nx/.local/share/hypr/windowrules.conf ~#@❯ rm windowrules.conf ~#@❯ ln -s /home/nx/nixos-config/home/windowrules.conf /home/nx/.config/hypr/windowrules.conf
- Check value of option: e.g. sudo nixos-option home-manager.users.nx.xdg.enable
- nix build ".#nixosConfigurations.xmg.config.system.build.toplevel" --dry-run
nix develop --store /mnt/user-store --extra-experimental-features nix-command --extra-experimental-features flakes nix store gc --store /mnt/user-store --extra-experimental-features nix-command
"nix.conf".text = ''
store = /mnt/user-store
substituters = https://cache.nixos.org/
trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
sandbox = false
require-sigs = true
auto-optimise-store = false
extra-experimental-features = nix-command flakes
'';
systemd.tmpfiles.rules = [
# alternative user store
"d /home/user/.config/nix 0755 user users -"
"L+ /home/user/.config/nix/nix.conf - - - - /etc/nix.conf"
];nix profile add 'nixpkgs#devenv'
mkdir -p ~/.local/bin
echo '#!/bin/sh
exec $(find /mnt/user-store/nix/store -type f -name devenv | sort | tail -1) "$@"
' > ~/.local/bin/devenv
chmod +x ~/.local/bin/devenv- gpg --list-secret-keys --keyid-format LONG
- gpg --export-secret-keys XXXXXXXXXX > privat.asc
- gpg --export XXXXXXXXXX > public.asc
- workaround for oom errors
export MAKEFLAGS="-j1"
export CFLAGS="-O0"
export CXXFLAGS="-O0"
nvim --headless "+TSUninstall gitcommit" "+TSInstall gitcommit" +qa