[wip] nix_flakes support #14

Draft
mwojcik wants to merge 12 commits from mwojcik/wfvm:nix_flakes into master
12 changed files with 184 additions and 158 deletions

View File

@ -28,21 +28,14 @@ How to use
Install a Windows image Install a Windows image
----------------------- -----------------------
1. Adjust demo-image.nix accordingly 1. Adjust demo-image in ``flake.nix`` accordingly
2. Run: 2. Run:
If in impure mode
```shell ```shell
nix-build demo-image.nix nix build .#demo-image
./result ./result
``` ```
Results in a file called c.img
If in pure mode
```shell
nix-build demo-image.nix
ls -la ./result
```
Results in a symlink to the image in the nix store Results in a symlink to the image in the nix store
@ -52,3 +45,5 @@ Impure/pure mode
Sometimes it can be useful to build the image _outside_ of the Nix sandbox for debugging purposes. Sometimes it can be useful to build the image _outside_ of the Nix sandbox for debugging purposes.
For this purpose we have an attribute called `impureMode` which outputs the shell script used by Nix inside the sandbox to build the image. For this purpose we have an attribute called `impureMode` which outputs the shell script used by Nix inside the sandbox to build the image.
When building an image with flakes, use ``nix build .#demo-image-impure`` instead.

27
flake.lock Normal file
View File

@ -0,0 +1,27 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1593034146,
"narHash": "sha256-EypP7RyPq5Yv05VgsQoIkdn26KJUIgQCItHgVY1MMQE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "f8248ab6d9e69ea9c07950d73d48807ec595e923",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "f8248ab6d9e69ea9c07950d73d48807ec595e923",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

129
flake.nix Normal file
View File

@ -0,0 +1,129 @@
{
description = "A Nix library to create and manage virtual machines running Windows.";
inputs.nixpkgs.url = github:NixOS/nixpkgs/f8248ab6d9e69ea9c07950d73d48807ec595e923;
outputs = { self, nixpkgs }:
let
pkgs = import nixpkgs { system = "x86_64-linux"; };
lib = pkgs.lib;
# utils
utils = (import wfvm/utils.nix { inherit pkgs; });
# layers
layers = (import wfvm/layers { inherit pkgs; }); # end of layers
# makeWindowsImage
makeWindowsImage = attrs: import wfvm/win.nix ({ inherit pkgs; } // attrs );
build-demo-image = { impureMode ? false }: makeWindowsImage {
# Build install script & skip building iso
inherit impureMode;
# Custom base iso
# windowsImage = pkgs.requireFile rec {
# name = "Win10_21H1_English_x64.iso";
# sha256 = "1sl51lnx4r6ckh5fii7m2hi15zh8fh7cf7rjgjq9kacg8hwyh4b9";
# message = "Get ${name} from https://www.microsoft.com/en-us/software-download/windows10ISO";
# };
# impureShellCommands = [
# "powershell.exe echo Hello"
# ];
# User accounts
# users = {
# artiq = {
# password = "1234";
# # description = "Default user";
# # displayName = "Display name";
# groups = [
# "Administrators"
# ];
# };
# };
# Auto login
# defaultUser = "artiq";
# fullName = "M-Labs";
# organization = "m-labs";
# administratorPassword = "12345";
# Imperative installation commands, to be installed incrementally
installCommands = if impureMode then [] else (with layers; [
(collapseLayers [
disable-autosleep
disable-autolock
disable-firewall
])
anaconda3 msys2 msvc msvc-ide-unbreak
]);
# services = {
# # Enable remote management
# WinRm = {
# Status = "Running";
# PassThru = true;
# };
# };
# License key (required)
# productKey = throw "Search the f* web"
# imageSelection = "1";
# Locales
# uiLanguage = "en-US";
# inputLocale = "en-US";
# userLocale = "en-US";
# systemLocale = "en-US";
};
in {
# bundle dev env
devShell.x86_64-linux = pkgs.mkShell {
name = "wfvm-dev-shell";
buildInputs = with pkgs; [
go
];
shellHook = ''
unset GOPATH
'';
};
inherit utils;
inherit makeWindowsImage;
inherit layers;
demo-ssh = utils.wfvm-run {
name = "demo-ssh";
image = build-demo-image {};
isolateNetwork = false;
script = ''
${pkgs.sshpass}/bin/sshpass -p1234 -- ${pkgs.openssh}/bin/ssh -p 2022 wfvm@localhost -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null
'';
};
packages.x86_64-linux = {
demo-image = build-demo-image {};
demo-image-impure = build-demo-image { impureMode = true; };
make-msys-packages = utils.wfvm-run {
name = "get-msys-packages";
image = makeWindowsImage { installCommands = [ layers.msys2 ]; };
script = ''
cat > getmsyspackages.bat << EOF
set MSYS=C:\\MSYS64
set TOOLPREF=mingw-w64-x86_64-
set PATH=%MSYS%\usr\bin;%MSYS%\mingw64\bin;%PATH%
pacman -Sp %TOOLPREF%gcc %TOOLPREF%binutils make autoconf automake libtool texinfo > packages.txt
EOF
\${utils.win-put}/bin/win-put getmsyspackages.bat
\${utils.win-exec}/bin/win-exec getmsyspackages
\${utils.win-get}/bin/win-get packages.txt
'';
};
};
};
}

View File

@ -15,7 +15,7 @@
, impureShellCommands ? [] , impureShellCommands ? []
, driveLetter ? "D:" , driveLetter ? "D:"
, efi ? true , efi ? true
, imageSelection ? "Windows 10 Pro" , imageSelection ? "1"
, ... , ...
}: }:
@ -200,7 +200,7 @@ let
</InstallTo> </InstallTo>
<InstallFrom> <InstallFrom>
<MetaData wcm:action="add"> <MetaData wcm:action="add">
<Key>/IMAGE/NAME</Key> <Key>/IMAGE/INDEX</Key>
<Value>${imageSelection}</Value> <Value>${imageSelection}</Value>
</MetaData> </MetaData>
</InstallFrom> </InstallFrom>

View File

@ -1,10 +0,0 @@
{ pkgs }:
pkgs.runCommandNoCC "win-bundle-installer.exe" {} ''
mkdir bundle
cd bundle
cp ${./go.mod} go.mod
cp ${./main.go} main.go
env HOME=$(mktemp -d) GOOS=windows GOARCH=amd64 ${pkgs.go}/bin/go build
mv bundle.exe $out
''

View File

@ -1,13 +0,0 @@
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
buildInputs = [
pkgs.go
];
shellHook = ''
unset GOPATH
'';
}

View File

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

View File

@ -1,72 +0,0 @@
{ pkgs ? import <nixpkgs> {}, impureMode ? false }:
let
wfvm = (import ./default.nix { inherit pkgs; });
in
wfvm.makeWindowsImage {
# Build install script & skip building iso
inherit impureMode;
# Custom base iso
# windowsImage = pkgs.requireFile rec {
# name = "Win10_21H1_English_x64.iso";
# sha256 = "1sl51lnx4r6ckh5fii7m2hi15zh8fh7cf7rjgjq9kacg8hwyh4b9";
# message = "Get ${name} from https://www.microsoft.com/en-us/software-download/windows10ISO";
# };
# impureShellCommands = [
# "powershell.exe echo Hello"
# ];
# User accounts
# users = {
# artiq = {
# password = "1234";
# # description = "Default user";
# # displayName = "Display name";
# groups = [
# "Administrators"
# ];
# };
# };
# Auto login
# defaultUser = "artiq";
# fullName = "M-Labs";
# organization = "m-labs";
# administratorPassword = "12345";
# Imperative installation commands, to be installed incrementally
installCommands =
if impureMode
then []
else with wfvm.layers; [
(collapseLayers [
disable-autosleep
disable-autolock
disable-firewall
])
anaconda3 msys2 msvc msvc-ide-unbreak
];
# services = {
# # Enable remote management
# WinRm = {
# Status = "Running";
# PassThru = true;
# };
# };
# License key (required)
# productKey = throw "Search the f* web"
imageSelection = "Windows 10 Pro";
# Locales
# uiLanguage = "en-US";
# inputLocale = "en-US";
# userLocale = "en-US";
# systemLocale = "en-US";
}

View File

@ -1,13 +0,0 @@
{ pkgs ? import <nixpkgs> {} }:
let
wfvm = (import ./default.nix { inherit pkgs; });
in
wfvm.utils.wfvm-run {
name = "demo-ssh";
image = import ./demo-image.nix { inherit pkgs; };
isolateNetwork = false;
script = ''
${pkgs.sshpass}/bin/sshpass -p1234 -- ${pkgs.openssh}/bin/ssh -p 2022 wfvm@localhost -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null
'';
}

View File

@ -1,6 +1,7 @@
{ pkgs }: { pkgs }:
let let
wfvm = import ../. { inherit pkgs; }; makeWindowsImage = attrs: import ../win.nix ({ inherit pkgs; } // attrs );
utils = import ../utils.nix { inherit pkgs; };
in in
{ {
anaconda3 = { anaconda3 = {
@ -72,20 +73,20 @@ in
bootstrapper = pkgs.fetchurl { bootstrapper = pkgs.fetchurl {
name = "RESTRICTDIST-vs_Community.exe"; name = "RESTRICTDIST-vs_Community.exe";
url = "https://aka.ms/vs/16/release/vs_community.exe"; url = "https://aka.ms/vs/16/release/vs_community.exe";
sha256 = "0b3csxz0qsafnvc0d74ywfpralwz8chv4zf9k07akpm8lp8ycgq0"; sha256 = "sha256-bxi8LsvNxSZshkTbhK/FEmMx84NKYB7TUNOm9sAKXS8=";
}; };
# This touchy-feely "community" piece of trash seems deliberately crafted to break Wine, so we use the VM to run it. # This touchy-feely "community" piece of trash seems deliberately crafted to break Wine, so we use the VM to run it.
download-vs = wfvm.utils.wfvm-run { download-vs = utils.wfvm-run {
name = "download-vs"; name = "download-vs";
image = wfvm.makeWindowsImage { }; image = makeWindowsImage { };
isolateNetwork = false; isolateNetwork = false;
script = script =
'' ''
ln -s ${bootstrapper} vs_Community.exe ln -s ${bootstrapper} vs_Community.exe
${wfvm.utils.win-put}/bin/win-put vs_Community.exe ${utils.win-put}/bin/win-put vs_Community.exe
rm vs_Community.exe rm vs_Community.exe
${wfvm.utils.win-exec}/bin/win-exec "vs_Community.exe --quiet --norestart --layout c:\vslayout --add Microsoft.VisualStudio.Workload.NativeDesktop --includeRecommended --lang en-US" ${utils.win-exec}/bin/win-exec "vs_Community.exe --quiet --norestart --layout c:\vslayout --add Microsoft.VisualStudio.Workload.NativeDesktop --includeRecommended --lang en-US"
${wfvm.utils.win-get}/bin/win-get /c:/vslayout ${utils.win-get}/bin/win-get /c:/vslayout
''; '';
}; };
cache = pkgs.stdenv.mkDerivation { cache = pkgs.stdenv.mkDerivation {

View File

@ -2,27 +2,7 @@
set -e set -e
nix-build -E " nix build .#make-msys-packages
let
pkgs = import <nixpkgs> {};
wfvm = import ../default.nix { inherit pkgs; };
in
wfvm.utils.wfvm-run {
name = \"get-msys-packages\";
image = wfvm.makeWindowsImage { installCommands = [ wfvm.layers.msys2 ]; };
script = ''
cat > getmsyspackages.bat << EOF
set MSYS=C:\\MSYS64
set TOOLPREF=mingw-w64-x86_64-
set PATH=%MSYS%\usr\bin;%MSYS%\mingw64\bin;%PATH%
pacman -Sp %TOOLPREF%gcc %TOOLPREF%binutils make autoconf automake libtool texinfo > packages.txt
EOF
\${wfvm.utils.win-put}/bin/win-put getmsyspackages.bat
\${wfvm.utils.win-exec}/bin/win-exec getmsyspackages
\${wfvm.utils.win-get}/bin/win-get packages.txt
'';
}
"
./result/bin/wfvm-run-get-msys-packages ./result/bin/wfvm-run-get-msys-packages

View File

@ -8,6 +8,7 @@
# autounattend always installs index 1, so this default is backward-compatible # autounattend always installs index 1, so this default is backward-compatible
, imageSelection ? "Windows 10 Pro" , imageSelection ? "Windows 10 Pro"
, efi ? true , efi ? true
, bundleInstaller ? {}
, ... , ...
}@attrs: }@attrs:
@ -23,6 +24,16 @@ let
}; };
}); });
# bundle
bundleInstaller = pkgs.runCommandNoCC "win-bundle-installer.exe" {} ''
mkdir bundle
cd bundle
cp ${bundle/go.mod} go.mod
cp ${bundle/main.go} main.go
env HOME=$(mktemp -d) GOOS=windows GOARCH=amd64 ${pkgs.go}/bin/go build
mv bundle.exe $out
'';
runQemuCommand = name: command: ( runQemuCommand = name: command: (
pkgs.runCommandNoCC name { buildInputs = [ p7zip utils.qemu libguestfs ]; } pkgs.runCommandNoCC name { buildInputs = [ p7zip utils.qemu libguestfs ]; }
( (
@ -36,8 +47,8 @@ let
); );
windowsIso = if windowsImage != null then windowsImage else pkgs.requireFile rec { windowsIso = if windowsImage != null then windowsImage else pkgs.requireFile rec {
name = "Win10_21H1_English_x64.iso"; name = "xks67i4frg8k7rmlv5298aac0s4n5nih-RESTRICTDIST-release_svc_refresh_CLIENT_LTSC_EVAL_x64FRE_en-us.iso";
sha256 = "1sl51lnx4r6ckh5fii7m2hi15zh8fh7cf7rjgjq9kacg8hwyh4b9"; sha256 = "0fmw30g7959bh47z8xi5pmmxq4kb0sxs1qxf51il3xy2f2py33v6";
message = "Get ${name} from https://www.microsoft.com/en-us/software-download/windows10ISO"; message = "Get ${name} from https://www.microsoft.com/en-us/software-download/windows10ISO";
}; };
@ -67,8 +78,6 @@ let
} }
); );
bundleInstaller = pkgs.callPackage ./bundle {};
# Packages required to drive installation of other packages # Packages required to drive installation of other packages
bootstrapPkgs = bootstrapPkgs =
runQemuCommand "bootstrap-win-pkgs.img" '' runQemuCommand "bootstrap-win-pkgs.img" ''