Compare commits

...

7 Commits

Author SHA1 Message Date
e811c7c5d8 README: windows 11 2024-06-11 13:14:36 +08:00
8051ad647a utils.nix: pass all attrs
Fixes passing baseRtc and other parameters
2023-06-26 15:48:34 +02:00
ec1c08956b default.nix: remove superfluous parentheses 2023-06-26 15:48:18 +02:00
7e09796a9b Revert "remove configurable efi flag"
This reverts commit af9218e652.
2023-06-08 18:42:48 +02:00
4dcd3699fe add 'nix run' demo 2023-05-27 15:36:00 +08:00
bf681b20aa remove MSVC from demo image
Usually broken due to Microsoft's war on reproducibility.
2023-05-27 15:15:51 +08:00
3cbddd7218 update nixpkgs 2023-05-27 15:15:33 +08:00
8 changed files with 43 additions and 20 deletions

View File

@ -6,7 +6,7 @@ WFVM
A Nix library to create and manage virtual machines running Windows, a medieval operating system found on most computers in 2020. The F stands for "Functional" or a four-letter word of your choice. A Nix library to create and manage virtual machines running Windows, a medieval operating system found on most computers in 2020. The F stands for "Functional" or a four-letter word of your choice.
* Reproducible - everything runs in the Nix sandbox with no tricks. * Reproducible - everything runs in the Nix sandbox with no tricks.
* Fully automatic, parameterizable Windows 10 installation. * Fully automatic, parameterizable Windows 11 installation.
* Uses QEMU with KVM. * Uses QEMU with KVM.
* Supports incremental installation (using "layers") of additional software via QEMU copy-on-write backing chains. For example, ``wfvm.makeWindowsImage { installCommands = [ wfvm.layers.anaconda3 ]; };`` gives you a VM image with Anaconda3 installed, and ``wfvm.makeWindowsImage { installCommands = [ wfvm.layers.anaconda3 wfvm.layers.msys2 ]; };`` gives you one with both Anaconda3 and MSYS2 installed. The base Windows installation and the Anaconda3 data are shared between both images, and only the MSYS2 installation is performed when building the second image after the first one has been built. * Supports incremental installation (using "layers") of additional software via QEMU copy-on-write backing chains. For example, ``wfvm.makeWindowsImage { installCommands = [ wfvm.layers.anaconda3 ]; };`` gives you a VM image with Anaconda3 installed, and ``wfvm.makeWindowsImage { installCommands = [ wfvm.layers.anaconda3 wfvm.layers.msys2 ]; };`` gives you one with both Anaconda3 and MSYS2 installed. The base Windows installation and the Anaconda3 data are shared between both images, and only the MSYS2 installation is performed when building the second image after the first one has been built.
* Included layers: Anaconda3, a software installer chock full of bugs that pretends to be a package manager, Visual Studio, a spamming system for Microsoft accounts that includes a compiler, and MSYS2, which is the only sane component in the whole lot. * Included layers: Anaconda3, a software installer chock full of bugs that pretends to be a package manager, Visual Studio, a spamming system for Microsoft accounts that includes a compiler, and MSYS2, which is the only sane component in the whole lot.

12
flake.lock generated
View File

@ -2,16 +2,16 @@
"nodes": { "nodes": {
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1665449268, "lastModified": 1685004253,
"narHash": "sha256-cw4xrQIAZUyJGj58Dp5VLICI0rscd+uap83afiFzlcA=", "narHash": "sha256-AbVL1nN/TDicUQ5wXZ8xdLERxz/eJr7+o8lqkIOVuaE=",
"owner": "nixos", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "285e77efe87df64105ec14b204de6636fb0a7a27", "rev": "3e01645c40b92d29f3ae76344a6d654986a91a91",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "nixos", "owner": "NixOS",
"ref": "nixos-unstable", "ref": "nixos-23.05",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }

View File

@ -2,7 +2,7 @@
description = "WFVM: Windows Functional Virtual Machine"; description = "WFVM: Windows Functional Virtual Machine";
inputs = { inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.05";
}; };
outputs = { self, nixpkgs }: outputs = { self, nixpkgs }:
@ -12,13 +12,26 @@
pkgs = nixpkgs.legacyPackages.${system}; pkgs = nixpkgs.legacyPackages.${system};
in { in rec {
lib = import ./wfvm { lib = import ./wfvm {
inherit pkgs; inherit pkgs;
}; };
packages.${system}.demoImage = import ./wfvm/demo-image.nix { packages.${system} = rec {
demoImage = import ./wfvm/demo-image.nix {
inherit self; inherit self;
}; };
default = lib.utils.wfvm-run {
name = "demo";
image = demoImage;
script =
''
echo "Windows booted. Press Enter to terminate VM."
read
'';
display = true;
};
};
}; };
} }

View File

@ -14,6 +14,7 @@
, services ? {} , services ? {}
, impureShellCommands ? [] , impureShellCommands ? []
, driveLetter ? "D:" , driveLetter ? "D:"
, efi ? true
, imageSelection ? "Windows 11 Pro N" , imageSelection ? "Windows 11 Pro N"
, enableTpm , enableTpm
, ... , ...
@ -119,7 +120,8 @@ let
# Windows expects a flat list of users while we want to manage them as a set # Windows expects a flat list of users while we want to manage them as a set
flatUsers = builtins.attrValues (builtins.mapAttrs (name: s: s // { inherit name; }) users); flatUsers = builtins.attrValues (builtins.mapAttrs (name: s: s // { inherit name; }) users);
diskId = 2; diskId =
if efi then 2 else 1;
autounattendXML = pkgs.writeText "autounattend.xml" '' autounattendXML = pkgs.writeText "autounattend.xml" ''
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
@ -159,12 +161,12 @@ let
<CreatePartitions> <CreatePartitions>
<CreatePartition wcm:action="add"> <CreatePartition wcm:action="add">
<Order>1</Order> <Order>1</Order>
<Type>EFI</Type> <Type>${if efi then "EFI" else "Primary"}</Type>
<Size>300</Size> <Size>300</Size>
</CreatePartition> </CreatePartition>
<CreatePartition wcm:action="add"> <CreatePartition wcm:action="add">
<Order>2</Order> <Order>2</Order>
<Type>MSR</Type> <Type>${if efi then "MSR" else "Primary"}</Type>
<Size>16</Size> <Size>16</Size>
</CreatePartition> </CreatePartition>
<CreatePartition wcm:action="add"> <CreatePartition wcm:action="add">
@ -176,7 +178,7 @@ let
<ModifyPartitions> <ModifyPartitions>
<ModifyPartition wcm:action="add"> <ModifyPartition wcm:action="add">
<Order>1</Order> <Order>1</Order>
<Format>FAT32</Format> <Format>${if efi then "FAT32" else "NTFS"}</Format>
<Label>System</Label> <Label>System</Label>
<PartitionID>1</PartitionID> <PartitionID>1</PartitionID>
</ModifyPartition> </ModifyPartition>

View File

@ -2,6 +2,6 @@
{ {
makeWindowsImage = attrs: import ./win.nix ({ inherit pkgs; } // attrs); makeWindowsImage = attrs: import ./win.nix ({ inherit pkgs; } // attrs);
layers = (import ./layers { inherit pkgs; }); layers = import ./layers { inherit pkgs; };
utils = (import ./utils.nix { inherit pkgs; }); utils = import ./utils.nix { inherit pkgs; };
} }

View File

@ -57,7 +57,7 @@ wfvm.makeWindowsImage {
disable-autolock disable-autolock
disable-firewall disable-firewall
]) ])
anaconda3 msys2 msvc msvc-ide-unbreak anaconda3 msys2
]; ];
# services = { # services = {

View File

@ -2,7 +2,9 @@
, baseRtc ? "2022-10-10T10:10:10" , baseRtc ? "2022-10-10T10:10:10"
, cores ? "4" , cores ? "4"
, qemuMem ? "4G" , qemuMem ? "4G"
, efi ? true
, enableTpm ? false , enableTpm ? false
, ...
}: }:
rec { rec {
@ -23,6 +25,7 @@ rec {
"-rtc base=${baseRtc}" "-rtc base=${baseRtc}"
"-device qemu-xhci" "-device qemu-xhci"
"-device virtio-net-pci,netdev=n1" "-device virtio-net-pci,netdev=n1"
] ++ pkgs.lib.optionals efi [
"-bios ${OVMF.fd}/FV/OVMF.fd" "-bios ${OVMF.fd}/FV/OVMF.fd"
] ++ pkgs.lib.optionals enableTpm [ ] ++ pkgs.lib.optionals enableTpm [
"-chardev" "socket,id=chrtpm,path=tpm.sock" "-chardev" "socket,id=chrtpm,path=tpm.sock"

View File

@ -8,12 +8,13 @@
, enableTpm ? true , enableTpm ? true
# autounattend always installs index 1, so this default is backward-compatible # autounattend always installs index 1, so this default is backward-compatible
, imageSelection ? "Windows 11 Pro N" , imageSelection ? "Windows 11 Pro N"
, efi ? true
, ... , ...
}@attrs: }@attrs:
let let
lib = pkgs.lib; lib = pkgs.lib;
utils = import ./utils.nix { inherit pkgs enableTpm; }; utils = import ./utils.nix ({ inherit pkgs efi enableTpm; } // attrs);
inherit (pkgs) guestfs-tools; inherit (pkgs) guestfs-tools;
# p7zip on >20.03 has known vulns but we have no better option # p7zip on >20.03 has known vulns but we have no better option
@ -95,7 +96,7 @@ let
"usb-storage,drive=virtio-win" "usb-storage,drive=virtio-win"
# USB boot # USB boot
"-drive" "-drive"
"id=win-install,file=usbimage.img,if=none,format=raw,readonly=on,media=disk" "id=win-install,file=${if efi then "usb" else "cd"}image.img,if=none,format=raw,readonly=on,media=${if efi then "disk" else "cdrom"}"
"-device" "-device"
"usb-storage,drive=win-install" "usb-storage,drive=win-install"
# Output image # Output image
@ -124,7 +125,11 @@ let
cp ${autounattend.autounattendXML} win/autounattend.xml cp ${autounattend.autounattendXML} win/autounattend.xml
${if efi then ''
virt-make-fs --partition --type=fat win/ usbimage.img virt-make-fs --partition --type=fat win/ usbimage.img
'' else ''
${pkgs.cdrkit}/bin/mkisofs -iso-level 4 -l -R -udf -D -b boot/etfsboot.com -no-emul-boot -boot-load-size 8 -hide boot.catalog -eltorito-alt-boot -o cdimage.img win/
''}
rm -rf win rm -rf win
${utils.tpmStartCommands} ${utils.tpmStartCommands}