Compare commits

...

14 Commits

Author SHA1 Message Date
Astro 110fe11f00 install openssh from github
this removes the need for the windows version's OpenSSH.Server
feature-on-demand package which is not publicly available.

fixes gitea issue #6 <M-Labs/wfvm#6>
2021-06-16 15:13:12 +02:00
Astro 07813c3c4f remove wimsplit, do imageSelection by name 2021-06-05 20:43:55 +02:00
Astro 54d9f41a6d autounattend: use ForceShutdownNow instead of FirstLogonCommands shutdown
this moves the return a little earlier in the installation process.
it is less of a hack, and less problematic with custom `defaultUser`
settings.
2021-04-18 00:55:01 +02:00
Astro ec54c9bf9b install and use virtio drivers
(virtio disk, qxl vga, virtio net)

fixes Gitea issue #7
2021-04-11 10:03:47 +08:00
Astro 4771cee64b layers: add collapseLayers 2021-04-10 23:25:29 +02:00
Astro 78c9363b64 demo-image: use empty installCommands for impureMode 2021-04-10 23:25:29 +02:00
Astro 9f8a1b6e17 layers: add disable-firewall, disable-autosleep, disable-autolock 2021-04-10 23:25:29 +02:00
Markus Partheymüller f1b52c0da7 autounattend: Revert back to driveLetter D 2021-03-10 13:35:49 +01:00
Markus Partheymüller 0becb115f6 win: Use maximum size to split install.wim 2021-03-10 11:10:09 +01:00
Markus Partheymüller 84ef1ec7e5 win: cdimage naming, closure shrinking 2021-03-10 11:09:49 +01:00
Markus Partheymüller 1357f493bd Add support for legacy installations 2021-03-09 10:48:29 +01:00
Markus Partheymüller e8232ab89a win: Allow for selection specific image
This is useful if the install.wim contains multiple Windows versions
(e.g., Home, Pro, ..), because the autounattend file will always select
index 1. With this mechanism, a variant different from the first one can
be automatically selected. imageSelection can be either an index (1-N)
or the image name wiminfo can list all images contained in a given WIM
file.

The default case is index 1, which has the same effect as before, with
the possibility of having a slightly smaller install.wim file because
all unwanted variants are discarded.
2021-03-09 10:36:56 +01:00
Markus Partheymüller 90cc7b14a4 Use q35 and xHCI for more performance 2021-03-09 10:36:56 +01:00
Markus Partheymüller fbd5b97d79 Split install.wim before creating USB image
With newer Windows 10 versions, `install.wim` can become larger than
4GiB, which can't be placed in a FAT32 partition anymore. By splitting
it into chunks with `wimsplit` and removing `install.wim`, the larger
images work fine.
2021-03-09 10:36:56 +01:00
8 changed files with 167 additions and 41 deletions

View File

@ -13,7 +13,9 @@
, timeZone ? "UTC"
, services ? {}
, impureShellCommands ? []
, driveLetter ? "E:"
, driveLetter ? "D:"
, efi ? true
, imageSelection ? "Windows 10 Pro"
, ...
}:
@ -48,12 +50,8 @@ let
# mkDirsDesc ++ writeKeysDesc ++
[
{
Path = ''powershell.exe Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0 -Source ${driveLetter}\fod -LimitAccess'';
Description = "Add OpenSSH service.";
}
{
Path = ''powershell.exe Set-Service -Name sshd -StartupType Automatic'';
Description = "Enable SSH by default.";
Path = ''powershell.exe ${driveLetter}\install-ssh.ps1'';
Description = "Install OpenSSH service.";
}
];
@ -75,7 +73,7 @@ let
++ setupCommands
++ [
{
Path = ''powershell.exe ${driveLetter}\ssh-setup.ps1'';
Path = ''powershell.exe ${driveLetter}\setup.ps1'';
Description = "Setup SSH and keys";
}
]
@ -123,6 +121,9 @@ let
# 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);
diskId =
if efi then 2 else 1;
autounattendXML = pkgs.writeText "autounattend.xml" ''
<?xml version="1.0" encoding="utf-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend">
@ -135,6 +136,15 @@ let
<PathAndCredentials wcm:action="add" wcm:keyValue="2">
<Path>E:\</Path>
</PathAndCredentials>
<PathAndCredentials wcm:action="add" wcm:keyValue="3">
<Path>C:\virtio\amd64\w10</Path>
</PathAndCredentials>
<PathAndCredentials wcm:action="add" wcm:keyValue="4">
<Path>C:\virtio\NetKVM\w10\amd64</Path>
</PathAndCredentials>
<PathAndCredentials wcm:action="add" wcm:keyValue="5">
<Path>C:\virtio\qxldod\w10\amd64</Path>
</PathAndCredentials>
</DriverPaths>
</component>
<component name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
@ -144,12 +154,12 @@ let
<CreatePartitions>
<CreatePartition wcm:action="add">
<Order>1</Order>
<Type>EFI</Type>
<Size>100</Size>
<Type>${if efi then "EFI" else "Primary"}</Type>
<Size>300</Size>
</CreatePartition>
<CreatePartition wcm:action="add">
<Order>2</Order>
<Type>MSR</Type>
<Type>${if efi then "MSR" else "Primary"}</Type>
<Size>16</Size>
</CreatePartition>
<CreatePartition wcm:action="add">
@ -161,7 +171,7 @@ let
<ModifyPartitions>
<ModifyPartition wcm:action="add">
<Order>1</Order>
<Format>FAT32</Format>
<Format>${if efi then "FAT32" else "NTFS"}</Format>
<Label>System</Label>
<PartitionID>1</PartitionID>
</ModifyPartition>
@ -177,7 +187,7 @@ let
<PartitionID>3</PartitionID>
</ModifyPartition>
</ModifyPartitions>
<DiskID>0</DiskID>
<DiskID>${toString diskId}</DiskID>
<WillWipeDisk>true</WillWipeDisk>
</Disk>
</DiskConfiguration>
@ -185,13 +195,13 @@ let
<ImageInstall>
<OSImage>
<InstallTo>
<DiskID>0</DiskID>
<DiskID>${toString diskId}</DiskID>
<PartitionID>3</PartitionID>
</InstallTo>
<InstallFrom>
<MetaData wcm:action="add">
<Key>/IMAGE/INDEX</Key>
<Value>1</Value>
<Key>/IMAGE/NAME</Key>
<Value>${imageSelection}</Value>
</MetaData>
</InstallFrom>
</OSImage>
@ -262,14 +272,12 @@ let
</AutoLogon>
''}
<FirstLogonCommands>
<SynchronousCommand wcm:action="add">
<Order>1</Order>
<CommandLine>cmd /C shutdown /s /f /t 00</CommandLine>
<Description>ChangeHideFiles</Description>
</SynchronousCommand>
</FirstLogonCommands>
</component>
<component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Reseal>
<ForceShutdownNow>true</ForceShutdownNow>
<Mode>OOBE</Mode>
</Reseal>
</component>
</settings>
@ -291,7 +299,7 @@ let
</component>
</settings>
<cpi:offlineImage cpi:source="wim:c:/wim/windows-10/install.wim#Windows 10 Enterprise LTSC 2019 Evaluation" xmlns:cpi="urn:schemas-microsoft-com:cpi" />
<cpi:offlineImage cpi:source="wim:c:/wim/windows-10/install.wim#${imageSelection}" xmlns:cpi="urn:schemas-microsoft-com:cpi" />
</unattend>
'';
@ -302,7 +310,7 @@ in {
'';
# autounattend.xml is _super_ picky about quotes and other things
setupScript = pkgs.writeText "ssh-setup.ps1" (
setupScript = pkgs.writeText "setup.ps1" (
''
# Setup SSH and keys
'' +

View File

@ -37,7 +37,17 @@ wfvm.makeWindowsImage {
# administratorPassword = "12345";
# Imperative installation commands, to be installed incrementally
installCommands = with wfvm.layers; [ anaconda3 msys2 msvc msvc-ide-unbreak ];
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

42
wfvm/install-ssh.ps1 Normal file
View File

@ -0,0 +1,42 @@
Write-Host "Expanding OpenSSH"
Expand-Archive D:\OpenSSH-Win64.zip C:\
Push-Location C:\OpenSSH-Win64
Write-Host "Installing OpenSSH"
& .\install-sshd.ps1
Write-Host "Generating host keys"
.\ssh-keygen.exe -A
Write-Host "Fixing host file permissions"
& .\FixHostFilePermissions.ps1 -Confirm:$false
Write-Host "Fixing user file permissions"
& .\FixUserFilePermissions.ps1 -Confirm:$false
Pop-Location
$newPath = 'C:\OpenSSH-Win64;' + [Environment]::GetEnvironmentVariable("PATH", [EnvironmentVariableTarget]::Machine)
[Environment]::SetEnvironmentVariable("PATH", $newPath, [EnvironmentVariableTarget]::Machine)
#Write-Host "Adding public key to authorized_keys"
#$keyPath = "~\.ssh\authorized_keys"
#New-Item -Type Directory ~\.ssh > $null
#$sshKey | Out-File $keyPath -Encoding Ascii
Write-Host "Opening firewall port 22"
New-NetFirewallRule -Protocol TCP -LocalPort 22 -Direction Inbound -Action Allow -DisplayName SSH
Write-Host "Setting sshd service startup type to 'Automatic'"
Set-Service sshd -StartupType Automatic
Set-Service ssh-agent -StartupType Automatic
Write-Host "Setting sshd service restart behavior"
sc.exe failure sshd reset= 86400 actions= restart/500
#Write-Host "Configuring sshd"
#(Get-Content C:\ProgramData\ssh\sshd_config).replace('#TCPKeepAlive yes', 'TCPKeepAlive yes').replace('#ClientAliveInterval 0', 'ClientAliveInterval 300').replace('#ClientAliveCountMax 3', 'ClientAliveCountMax 3') | Set-Content C:\ProgramData\ssh\sshd_config
Write-Host "Starting sshd service"
Start-Service sshd
Start-Service ssh-agent

View File

@ -122,4 +122,47 @@ in
sleep 40
'';
};
# Disable the Windows firewall
disable-firewall = {
name = "disable-firewall";
script = ''
echo Disabling firewall
win-exec "netsh advfirewall set allprofiles state off"
'';
};
# Disable automatic power management which causes the machine to go
# into standby after periods without mouse wiggling.
disable-autosleep = {
name = "disable-autosleep";
script = ''
echo Disabling autosleep
win-exec "powercfg /x -hibernate-timeout-ac 0"
win-exec "powercfg /x -hibernate-timeout-dc 0"
win-exec "powercfg /x -disk-timeout-ac 0"
win-exec "powercfg /x -disk-timeout-dc 0"
win-exec "powercfg /x -monitor-timeout-ac 0"
win-exec "powercfg /x -monitor-timeout-dc 0"
win-exec "powercfg /x -standby-timeout-ac 0"
win-exec "powercfg /x -standby-timeout-dc 0"
'';
};
# Turn off automatic locking of idle user sessions
disable-autolock = {
name = "disable-autolock";
script = ''
echo Disabling autolock
win-exec "reg add HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\Personalization /v NoLockScreen /t REG_DWORD /d 1"
'';
};
# Chain together layers that are quick to run so that the VM does
# not have to be started/shutdown for each.
collapseLayers = scripts: {
name = pkgs.lib.concatMapStringsSep "-" ({ name, ... }: name) scripts;
script = builtins.concatStringsSep "\n" (
map ({ script, ... }: script) scripts
);
buildInputs =
builtins.concatMap ({ buildInputs ? [], ... }: buildInputs) scripts;
};
}

View File

@ -1 +0,0 @@
This file is not publicaly acessible anywhere so had to be extracted from a connected instance

Binary file not shown.

View File

@ -1,4 +1,4 @@
{ pkgs, baseRtc ? "2020-04-20T14:21:42", cores ? "4", qemuMem ? "4G" }:
{ pkgs, baseRtc ? "2020-04-20T14:21:42", cores ? "4", qemuMem ? "4G", efi ? true }:
rec {
# qemu_test is a smaller closure only building for a single system arch
@ -9,10 +9,13 @@ rec {
"-cpu host"
"-smp ${cores}"
"-m ${qemuMem}"
"-bios ${pkgs.OVMF.fd}/FV/OVMF.fd"
"-M q35"
"-vga qxl"
"-rtc base=${baseRtc}"
"-device piix3-usb-uhci"
"-device e1000,netdev=n1"
"-device qemu-xhci"
"-device virtio-net-pci,netdev=n1"
] ++ pkgs.lib.optionals efi [
"-bios ${pkgs.OVMF.fd}/FV/OVMF.fd"
] ++ extraFlags;
# Pass empty config file to prevent ssh from failing to create ~/.ssh

View File

@ -5,12 +5,15 @@
, impureMode ? false
, installCommands ? []
, users ? {}
# autounattend always installs index 1, so this default is backward-compatible
, imageSelection ? "Windows 10 Pro"
, efi ? true
, ...
}@attrs:
let
lib = pkgs.lib;
utils = import ./utils.nix { inherit pkgs; };
utils = import ./utils.nix { inherit pkgs efi; };
libguestfs = pkgs.libguestfs-with-appliance;
# p7zip on >20.03 has known vulns but we have no better option
@ -38,7 +41,16 @@ let
sha256 = "668fe1af70c2f7416328aee3a0bb066b12dc6bbd2576f40f812b95741e18bc3a";
};
openSshServerPackage = ./openssh/server-package.cab;
# stable as of 2021-04-08
virtioWinIso = pkgs.fetchurl {
url = "https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.185-2/virtio-win-0.1.185.iso";
sha256 = "11n3kjyawiwacmi3jmfmn311g9xvfn6m0ccdwnjxw1brzb4kqaxg";
};
openSshServerPackage = pkgs.fetchurl {
url = "https://github.com/PowerShell/Win32-OpenSSH/releases/download/V8.6.0.0p1-Beta/OpenSSH-Win64.zip";
sha256 = "1dw6n054r0939501dpxfm7ghv21ihmypdx034van8cl21gf1b4lz";
};
autounattend = import ./autounattend.nix (
attrs // {
@ -60,15 +72,16 @@ let
# Packages required to drive installation of other packages
bootstrapPkgs =
runQemuCommand "bootstrap-win-pkgs.img" ''
mkdir -p pkgs/fod
7z x -y ${virtioWinIso} -opkgs/virtio
cp ${bundleInstaller} pkgs/"$(stripHash "${bundleInstaller}")"
# Install optional windows features
cp ${openSshServerPackage} pkgs/fod/OpenSSH-Server-Package~31bf3856ad364e35~amd64~~.cab
cp ${openSshServerPackage} pkgs/OpenSSH-Win64.zip
# SSH setup script goes here because windows XML parser sucks
cp ${autounattend.setupScript} pkgs/ssh-setup.ps1
cp ${./install-ssh.ps1} pkgs/install-ssh.ps1
cp ${autounattend.setupScript} pkgs/setup.ps1
virt-make-fs --partition --type=fat pkgs/ $out
'';
@ -83,12 +96,12 @@ let
"usb-storage,drive=virtio-win"
# USB boot
"-drive"
"id=win-install,file=usbimage.img,if=none,format=raw,readonly=on"
"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"
"usb-storage,drive=win-install"
# Output image
"-drive"
"file=c.img,index=0,media=disk,cache=unsafe"
"file=c.img,index=0,media=disk,if=virtio,cache=unsafe"
# Network
"-netdev user,id=n1,net=192.168.1.0/24,restrict=on"
]);
@ -96,7 +109,7 @@ let
''
#!${pkgs.runtimeShell}
set -euxo pipefail
export PATH=${lib.makeBinPath [ p7zip utils.qemu libguestfs ]}:$PATH
export PATH=${lib.makeBinPath [ p7zip utils.qemu libguestfs pkgs.wimlib ]}:$PATH
# Create a bootable "USB" image
# Booting in USB mode circumvents the "press any key to boot from cdrom" prompt
@ -106,9 +119,17 @@ let
mkdir -p win/nix-win
7z x -y ${windowsIso} -owin
# Split image so it fits in FAT32 partition
wimsplit win/sources/install.wim win/sources/install.swm 4090
rm win/sources/install.wim
cp ${autounattend.autounattendXML} win/autounattend.xml
${if efi then ''
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
# Qemu requires files to be rw
@ -131,7 +152,7 @@ let
qemuParams = utils.mkQemuFlags (lib.optional (!impureMode) "-display none" ++ [
# Output image
"-drive"
"file=c.img,index=0,media=disk,cache=unsafe"
"file=c.img,index=0,media=disk,if=virtio,cache=unsafe"
# Network - enable SSH forwarding
"-netdev user,id=n1,net=192.168.1.0/24,restrict=on,hostfwd=tcp::2022-:22"
]);