From e1b61af59272257afc0cc564cca32a8324b4ab9d Mon Sep 17 00:00:00 2001 From: Markus Otto Date: Thu, 4 Jul 2019 18:40:49 +0200 Subject: [PATCH 1/6] improve stage1 --- .gitignore | 2 +- Makefile | 84 +++++++++++++++++++++++++++++++++++------------------- stage1.ps1 | 29 ++++++++++++++----- 3 files changed, 77 insertions(+), 38 deletions(-) diff --git a/.gitignore b/.gitignore index dc4c1b0..ad8437c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ # Build outputs ssh_host* sshpass -stage?-complete +vm-stage? downloaded temporary *.qcow2 diff --git a/Makefile b/Makefile index 5d47f4c..fe07130 100644 --- a/Makefile +++ b/Makefile @@ -4,14 +4,16 @@ driver_url=https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/arch # Microsoft VM settings vm_url=https://az792536.vo.msecnd.net/vms/VMBuild_20171019/VirtualBox/MSEdge/MSEdge.Win10.VirtualBox.zip -initial_pw=Passw0rd! # default password of the VM -port=22022 # host binding port for SSH to VM +# default password of the VM +initial_pw=Passw0rd! +# host binding port for SSH to VM +port=22022 # Configuration to be applied to the VM -hostname=win10 +hostname=win10-openage username=chantal -password=Passw0rd! # you probably want to override this... +password=wololo # Shorthands @@ -22,28 +24,36 @@ pubkey=$(privkey).pub # Test for dependencies. Not sure if this is the right way to handle them. -# TODO: 7z, wget qemu +.PHONY: sshpass 7z wget qemu-img qemu-system-x86_64 sshpass: @which $@ > /dev/null || bash -c 'echo "$@ not found, please install it" && false' - touch $@ - +7z: + @which $@ > /dev/null || bash -c 'echo "$@ not found, please install it" && false' +wget: + @which $@ > /dev/null || bash -c 'echo "$@ not found, please install it" && false' +qemu-img: + @which $@ > /dev/null || bash -c 'echo "$@ not found, please install it" && false' +qemu-system-x86_64: + @which $@ > /dev/null || bash -c 'echo "$@ not found, please install it" && false' -# SSH hostkey generation. If not explicitly listed as target or aleady existent, -# the private key will be deleted automatically after ist is deployed to the VM. -$(privkey) $(pubkey): +# SSH hostkey generation. +$(privkey): + rm -f $(privkey) $(pubkey) ssh-keygen -f $(privkey) -t ed25519 -N '' +$(pubkey): $(privkey) + # Download and unpacking section $d: mkdir $@ -.PHONY: $d/virtio.iso -$d/virtio.iso: +$d/virtio.iso: | wget # Google for RedHat Windows virtio drivers - wget -c -O $@ $(driver_url) + wget -c -O $@.tmp $(driver_url) + mv $@.tmp $@ -$d/win10.zip: | $d +$d/win10.zip: | $d wget # New URLS to be found at modern.ie wget -c -O $@ $(vm_url) @@ -55,60 +65,74 @@ $d/win10.vmdk: $d/win10.ova # converted image -win10.qcow2: $d/win10.vmdk +win10.base.qcow2: $d/win10.vmdk | qemu-img qemu-img convert -O qcow2 $^ $@ +# overlay image +win10.qcow2: win10.base.qcow2 | qemu-img + qemu-img create -f qcow2 -b $^ $@ # helper files. cheap to create, will be automatically deleted when no longer needed $t: mkdir $@ -$t/helper.qcow2: | $t +$t/helper.qcow2: | $t qemu-img qemu-img create -f qcow2 $@ 1G -$t/ssh_host_ecdsa_key.pub: $d/win10.vmdk | $t +$t/vm_default_host_key.pub: $d/win10.vmdk | $t 7z 7z e -so $^ 'Program Files/OpenSSH/etc/ssh_host_ecdsa_key.pub' > $@ # Initial preparations in the VM. Includes changing hostname, username, password, disabling updates and installing viostor drivers -.ONESHELL: stage1-complete -stage1-complete: | $d/virtio.iso sshpass $t/ssh_host_ecdsa_key.pub $(pubkey) $(privkey) win10.qcow2 $t/helper.qcow2 - set -m - echo "[localhost]:$(port) $$(cut -d' ' -f1,2 $t/ssh_host_ecdsa_key.pub)" > $t/known_host +.ONESHELL: vm-stage1 +vm-stage1: | $d/virtio.iso $t/vm_default_host_key.pub $(pubkey) $(privkey) win10.qcow2 $t/helper.qcow2 qemu-system-x86_64 sshpass + @set -m + echo "[localhost]:$(port) $$(cut -d' ' -f1,2 $t/vm_default_host_key.pub)" > $t/known_host + echo Starting VM with virtio helper disk qemu-system-x86_64 \ -drive file=win10.qcow2,if=ide \ -drive file=$t/helper.qcow2,if=virtio \ -drive file=$d/virtio.iso,media=cdrom \ -machine type=q35,accel=kvm \ -m 8G -smp cores=2,threads=1 \ - -net nic -net user -redir tcp:$(port)::22 \ - -vga std -display sdl & - while ! nc -z localhost $(port); do sleep 1; done - while ! sshpass -p 'Passw0rd!' ssh -p $(port) -o UserKnownHostsFile=$t/known_host -o ConnectTimeout=1 IEUser@localhost 'echo "Machine is up"' 2> /dev/null; do sleep 1; done + -net nic -net user,hostfwd=tcp::$(port)-:22 \ + -vga std -display none & + echo Waiting for VM to respond on port 22 + sleep 5 + while ! sshpass -p '$(initial_pw)' ssh -p $(port) -o UserKnownHostsFile=$t/known_host -o ConnectTimeout=1 IEUser@localhost 'echo " Machine is up"' 2> /dev/null; do echo -n "."; sleep 1; done sshpass -p '$(initial_pw)' ssh -p $(port) -o UserKnownHostsFile=$t/known_host IEUser@localhost 'mkdir -p /cygdrive/c/stage1' sshpass -p '$(initial_pw)' scp -P $(port) -o UserKnownHostsFile=$t/known_host stage1.ps1 $(pubkey) $(privkey) IEUser@localhost:/cygdrive/c/stage1 sshpass -p '$(initial_pw)' ssh -p $(port) -o UserKnownHostsFile=$t/known_host IEUser@localhost 'powershell C:\\stage1\\stage1.ps1 -Hostname $(hostname) -Username $(username) -Password $(password)' fg touch $@ +.PHONY: cleanvm +cleanvm: + rm -f vm-stage1 win10.qcow2 + # This will install cmake, git, MSVC, vcpkg, python and all the other stuff. # Since this is project specific, we should have this in a script. -# We don't touch stage2-complete to just use this as a run target right now. -.ONESHELL: stage2-complete -stage2-complete: stage1-complete | win10.qcow2 $(pubkey) $t +# We don't touch vm-stage2 to just use this as a run target right now. +.ONESHELL: vm-stage2 +vm-stage2: vm-stage1 | win10.qcow2 $(pubkey) $t qemu-system-x86_64 set -m echo "[localhost]:$(port) $$(cut -d' ' -f1,2 $(pubkey))" > $t/known_host qemu-system-x86_64 \ -drive file=win10.qcow2,if=virtio \ -machine type=q35,accel=kvm \ -m 8G -smp cores=2,threads=1 \ - -net nic -net user -redir tcp:$(Port)::22 \ + -net nic -net user,hostfwd=tcp::$(port)-:22 \ -vga std -display sdl & fg + touch $@ + +.PHONY: run +run: vm-stage2 + rm -f $^ -.INTERMEDIATE: $d/win10.zip $d/win10.ova $d/win10.vmdk $d/virtio.iso $t/helper.qcow2 $(privkey) $t/ssh_host_ecdsa_key.pub +.INTERMEDIATE: $d/win10.zip $d/win10.ova $d/win10.vmdk $d/virtio.iso $t/helper.qcow2 $t/vm_default_host_key.pub $t/known_host .PRECIOUS: $d/win10.vmdk $d/virtio.iso diff --git a/stage1.ps1 b/stage1.ps1 index 7f4df58..a7b2f02 100755 --- a/stage1.ps1 +++ b/stage1.ps1 @@ -9,22 +9,29 @@ $ScriptDir = Split-Path $MyInvocation.InvocationName Start-Transcript "${ScriptDir}\stage1.log" # Kill Windows Update and make sure it stays dead +Write-Host "Getting rid of Windows Update." Stop-Service wuauserv Set-Service wuauserv -StartupType Disabled -# Change hostname and user -Rename-Computer -NewName "${Hostname}" +# Disable autostart stuff +Write-Host "Disabling BGInfo." +Remove-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run -Name * + +# User +Write-Host "Creating user '${Username}' with password '${Password}'." $SecurePassword = ConvertTo-SecureString -String "${Password}" -AsPlainText -Force -New-LocalUser -Name "${Username}" -Password $SecurePassword +New-LocalUser -Name "${Username}" -Password $SecurePassword | Out-Null Add-LocalGroupMember -Group Administrators -Member "${Username}" Disable-LocalUser IEUser + +Write-Host "Setting up automatic login for '${Username}'." Set-ItemProperty "HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Winlogon" DefaultPassword "${Password}" Set-ItemProperty "HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Winlogon" DefaultUserName "${Username}" # Reconfigure OpenSSHd +Write-Host "Setting up SSH access." $SID = Get-LocalUser $Username | select -ExpandProperty SID $PasswdLine = "${Username}:*:197612:197121:U-${Hostname}\${Username},${SID}:/cygdrive/c/Users/${Username}:/bin/sh" - Push-Location "${env:programfiles}\OpenSSH\etc" Add-Content -Path .\passwd "${PasswdLine}" Remove-Item ssh_host* @@ -32,6 +39,7 @@ Copy-Item "${ScriptDir}\ssh_host_*" . Pop-Location # Install virtio storage driver +Write-Host "Installing virtio storage drivers." # Thanks to https://stackoverflow.com/questions/36775331/extract-certificate-from-sys-file $InfFile = "D:\viostor\w10\amd64\viostor.inf" $SysFile = "D:\viostor\w10\amd64\viostor.sys" @@ -39,16 +47,23 @@ $CerFile = "${ScriptDir}\RedHat.cer" $ExportType = [System.Security.Cryptography.X509Certificates.X509ContentType]::Cert $Cert = (Get-AuthenticodeSignature $SysFile).SignerCertificate [System.IO.File]::WriteAllBytes($CerFile, $Cert.Export($ExportType)) -Import-Certificate -FilePath "$CerFile" -CertStoreLocation Cert:\LocalMachine\TrustedPublisher +Import-Certificate -FilePath "$CerFile" -CertStoreLocation Cert:\LocalMachine\TrustedPublisher | Out-Null Start-Process $InfFile -Verb Install Start-Sleep 5 # Initialize virtio dummy disk, so that virtio will work for the boot drive +Write-Host "Preparing virtio storage drivers for boot." Get-Disk | ?{ $_.PartitionStyle -eq "RAW" } | ` Initialize-Disk -PartitionStyle MBR -PassThru | ` New-Partition -AssignDriveLetter -UseMaximumSize | ` - Format-Volume -FileSystem NTFS -NewFileSystemLabel "dummy" -Confirm:$false + Format-Volume -FileSystem NTFS -NewFileSystemLabel "dummy" -Confirm:$false | Out-Null -# We are done. +# Hostname +Write-Host "Changing hostname to '${Hostname}'." +Rename-Computer -NewName "${Hostname}" | Out-Null + +# Shutdown +Write-Host "Shutting VM down." Start-Process -NoNewWindow "shutdown.exe" -ArgumentList "/s /t 0" + Stop-Transcript From f30023c15042fa79d0e60a057b7f7126a1a43677 Mon Sep 17 00:00:00 2001 From: Markus Otto Date: Thu, 4 Jul 2019 20:19:42 +0200 Subject: [PATCH 2/6] set display resolution to 1920x1080 --- Makefile | 2 +- stage1.ps1 | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index fe07130..68583f5 100644 --- a/Makefile +++ b/Makefile @@ -102,7 +102,7 @@ vm-stage1: | $d/virtio.iso $t/vm_default_host_key.pub $(pubkey) $(privkey) win10 while ! sshpass -p '$(initial_pw)' ssh -p $(port) -o UserKnownHostsFile=$t/known_host -o ConnectTimeout=1 IEUser@localhost 'echo " Machine is up"' 2> /dev/null; do echo -n "."; sleep 1; done sshpass -p '$(initial_pw)' ssh -p $(port) -o UserKnownHostsFile=$t/known_host IEUser@localhost 'mkdir -p /cygdrive/c/stage1' sshpass -p '$(initial_pw)' scp -P $(port) -o UserKnownHostsFile=$t/known_host stage1.ps1 $(pubkey) $(privkey) IEUser@localhost:/cygdrive/c/stage1 - sshpass -p '$(initial_pw)' ssh -p $(port) -o UserKnownHostsFile=$t/known_host IEUser@localhost 'powershell C:\\stage1\\stage1.ps1 -Hostname $(hostname) -Username $(username) -Password $(password)' + sshpass -p '$(initial_pw)' ssh -p $(port) -o UserKnownHostsFile=$t/known_host IEUser@localhost 'powershell C:\\stage1\\stage1.ps1 -Hostname $(hostname) -Username $(username) -Password $(password) -ResX 1920 -ResY 1080' fg touch $@ diff --git a/stage1.ps1 b/stage1.ps1 index a7b2f02..93de599 100755 --- a/stage1.ps1 +++ b/stage1.ps1 @@ -1,7 +1,9 @@ param( [String]$Hostname = "win10", [String]$Username = "chantal", - [String]$Password = "Passw0rd!" + [String]$Password = "wololo", + [Int]$ResX = 1920, + [Int]$ResY = 1080 ) $ScriptDir = Split-Path $MyInvocation.InvocationName @@ -58,6 +60,22 @@ Get-Disk | ?{ $_.PartitionStyle -eq "RAW" } | ` New-Partition -AssignDriveLetter -UseMaximumSize | ` Format-Volume -FileSystem NTFS -NewFileSystemLabel "dummy" -Confirm:$false | Out-Null +# Display resolution +Write-Host "Setting display resolution to ${ResX}x${ResY}." +Push-Location "HKLM:\SYSTEM\CurrentControlSet\Control\GraphicsDrivers\Configuration\MSBDD_NOEDID_1234_1111_00000000_00010000_0^FD62006E2425EAA7C207AF2974F7309B\00" +Set-ItemProperty -Path . -Name PrimSurfSize.cx -Value $ResX +Set-ItemProperty -Path . -Name PrimSurfSize.cy -Value $ResY +Set-ItemProperty -Path . -Name Stride -Value $(4 * $ResX) +Set-ItemProperty -Path 00 -Name PrimSurfSize.cx -Value $ResX +Set-ItemProperty -Path 00 -Name PrimSurfSize.cy -Value $ResY +Set-ItemProperty -Path 00 -Name Stride -Value $(4 * $ResX) +Set-ItemProperty -Path 00 -Name ActiveSize.cx -Value $ResX +Set-ItemProperty -Path 00 -Name ActiveSize.cy -Value $ResY +Set-ItemProperty -Path 00 -Name DwmClipBox.right -Value $ResX +Set-ItemProperty -Path 00 -Name DwmClipBox.bottom -Value $ResY +Set-ItemProperty -Path 00 -Name Flags -Value 0x830f8f +Pop-Location + # Hostname Write-Host "Changing hostname to '${Hostname}'." Rename-Computer -NewName "${Hostname}" | Out-Null From 285cb382c581ca6a15583b143d6943d628c9dc92 Mon Sep 17 00:00:00 2001 From: Markus Otto Date: Thu, 4 Jul 2019 20:34:33 +0200 Subject: [PATCH 3/6] update readme --- README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README.md b/README.md index 014a600..3541e00 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,17 @@ # kevin-win-setup Tools to automatically download and prepare a free Windows VM for kevin. + +# How +``` bash +make run +``` + +You will be dropped in a Windows 10 VM after a few minutes. Downloads will be cached for later. + +# Status +* VirtIO storage, autologin, display resolution and a bunch more work. +* Chantal has not yet been ported to Windows, need to find out what exactly is missing for that. +* Reference setup stages for Openage are being worked on. + +# U w0t? A Makefile? +Well, why not. There are a lot operations that involve building files from other files. Also this was a godd enough excuse to learn about some less well known features of `make`. From 10296011f3ef680704e94123a6a5617e52b50f46 Mon Sep 17 00:00:00 2001 From: Markus Otto Date: Thu, 4 Jul 2019 22:57:02 +0200 Subject: [PATCH 4/6] fix premature deletion of win10.zip --- Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 68583f5..7c52267 100644 --- a/Makefile +++ b/Makefile @@ -59,9 +59,11 @@ $d/win10.zip: | $d wget $d/win10.ova: $d/win10.zip unzip -p $^ > $@ + rm $^ $d/win10.vmdk: $d/win10.ova tar xOf $^ "MSEdge - Win10-disk001.vmdk" > $@ + rm $^ # converted image @@ -135,4 +137,4 @@ run: vm-stage2 .INTERMEDIATE: $d/win10.zip $d/win10.ova $d/win10.vmdk $d/virtio.iso $t/helper.qcow2 $t/vm_default_host_key.pub $t/known_host -.PRECIOUS: $d/win10.vmdk $d/virtio.iso +.PRECIOUS: $d/win10.zip $d/win10.ova $d/win10.vmdk $d/virtio.iso From 2af1f0722afef6995217f4afddb83ec1d3350547 Mon Sep 17 00:00:00 2001 From: Markus Otto Date: Thu, 4 Jul 2019 22:58:20 +0200 Subject: [PATCH 5/6] check for existence of unzip --- Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 7c52267..6ce7cb7 100644 --- a/Makefile +++ b/Makefile @@ -24,9 +24,11 @@ pubkey=$(privkey).pub # Test for dependencies. Not sure if this is the right way to handle them. -.PHONY: sshpass 7z wget qemu-img qemu-system-x86_64 +.PHONY: sshpass unzip 7z wget qemu-img qemu-system-x86_64 sshpass: @which $@ > /dev/null || bash -c 'echo "$@ not found, please install it" && false' +unzip: + @which $@ > /dev/null || bash -c 'echo "$@ not found, please install it" && false' 7z: @which $@ > /dev/null || bash -c 'echo "$@ not found, please install it" && false' wget: @@ -57,7 +59,7 @@ $d/win10.zip: | $d wget # New URLS to be found at modern.ie wget -c -O $@ $(vm_url) -$d/win10.ova: $d/win10.zip +$d/win10.ova: $d/win10.zip | unzip unzip -p $^ > $@ rm $^ From b986b3a0a2d73dd54d9ad0ada433fa37f03ea4f2 Mon Sep 17 00:00:00 2001 From: Markus Otto Date: Thu, 4 Jul 2019 23:58:37 +0200 Subject: [PATCH 6/6] add headless mode --- Makefile | 13 ++++++++++++- stage1.ps1 | 6 ++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 6ce7cb7..86b304c 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,7 @@ vm_url=https://az792536.vo.msecnd.net/vms/VMBuild_20171019/VirtualBox/MSEdge/MSE initial_pw=Passw0rd! # host binding port for SSH to VM port=22022 +rdpport=3389 # Configuration to be applied to the VM @@ -117,7 +118,6 @@ cleanvm: # This will install cmake, git, MSVC, vcpkg, python and all the other stuff. # Since this is project specific, we should have this in a script. -# We don't touch vm-stage2 to just use this as a run target right now. .ONESHELL: vm-stage2 vm-stage2: vm-stage1 | win10.qcow2 $(pubkey) $t qemu-system-x86_64 set -m @@ -132,6 +132,17 @@ vm-stage2: vm-stage1 | win10.qcow2 $(pubkey) $t qemu-system-x86_64 touch $@ +run-headless: vm-stage1 | win10.qcow2 $(pubkey) $t qemu-system-x86_64 + qemu-system-x86_64 \ + -drive file=win10.qcow2,if=virtio \ + -machine type=q35,accel=kvm \ + -m 8G -smp cores=2,threads=1 \ + -vga std -display none -net nic -net user,\ + hostfwd=tcp::$(port)-:22,\ + hostfwd=tcp::$(rdpport)-:3389,\ + hostfwd=udp::$(rdpport)-:3389 + + .PHONY: run run: vm-stage2 rm -f $^ diff --git a/stage1.ps1 b/stage1.ps1 index 93de599..de647a7 100755 --- a/stage1.ps1 +++ b/stage1.ps1 @@ -40,6 +40,12 @@ Remove-Item ssh_host* Copy-Item "${ScriptDir}\ssh_host_*" . Pop-Location +# Firewall +Write-Host "Setting up RDP access." +Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server" -Name fDenyTSConnections -Value 0 +Enable-NetFirewallRule -Name RemoteDesktop-UserMode-In-UDP +Enable-NetFirewallRule -Name RemoteDesktop-UserMode-In-TCP + # Install virtio storage driver Write-Host "Installing virtio storage drivers." # Thanks to https://stackoverflow.com/questions/36775331/extract-certificate-from-sys-file