From eb0b0fe80cbd51709987c64dc02d3effac6f1204 Mon Sep 17 00:00:00 2001 From: Kroese Date: Sun, 12 May 2024 13:49:56 +0200 Subject: [PATCH] feat: Improved installation (#486) --- Dockerfile | 2 +- readme.md | 24 ++++++---- src/install.sh | 128 +++++++++++++++++++++++-------------------------- 3 files changed, 77 insertions(+), 77 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5e3d2cf..29a0caf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ FROM scratch -COPY --from=qemux/qemu-docker:5.02 / / +COPY --from=qemux/qemu-docker:5.03 / / ARG DEBCONF_NOWARNINGS "yes" ARG DEBIAN_FRONTEND "noninteractive" diff --git a/readme.md b/readme.md index 0def083..fdcbf18 100644 --- a/readme.md +++ b/readme.md @@ -138,21 +138,21 @@ docker run -it --rm --name windows -p 8006:8006 --device=/dev/kvm --cap-add NET_ * ### How do I install a custom image? - In order to download any ISO image that is not part of the list above, start a fresh container with the URL of that ISO specified in the `VERSION` environment variable, for example: + In order to download an unsupported ISO image that is not selectable from the list above, specify the URL of that ISO in the `VERSION` environment variable, for example: ```yaml environment: VERSION: "https://example.com/win.iso" ``` - Alternatively, you can also use a local file directly, and skip the download altogether, by binding it in your compose file in this way: + Alternatively, you can also skip the download and use a local file instead, by binding it in your compose file in this way: ```yaml volumes: - /home/user/example.iso:/custom.iso ``` - Replace the example path `/home/user/example.iso` with the filename of your desired ISO file. The value of `VERSION` will be ignored in this case. + Replace the example path `/home/user/example.iso` with the filename of your desired ISO file, the value of `VERSION` will be ignored in this case. * ### How do I customize the installation? @@ -180,9 +180,9 @@ docker run -it --rm --name windows -p 8006:8006 --device=/dev/kvm --cap-add NET_ * ### How do I perform a manual installation? - It's best to use the automatic installation, as it optimizes various settings for use with this container. These tweaks will give you maximum performance and prevent common issues. + It's best to use the automatic installation, as it optimizes various settings to give you maximum performance and prevent common issues. - However, if you insist on performing the installation manually, start a fresh container with the following environment variable: + However, if you insist on performing the installation manually, add the following environment variable to your compose file: ```yaml environment: @@ -193,17 +193,25 @@ docker run -it --rm --name windows -p 8006:8006 --device=/dev/kvm --cap-add NET_ - Start the container and connect to [port 8006](http://localhost:8006) of the container in your web browser. After the download is finished, you will see the Windows installation screen. - - Start the installation by clicking `Install now`. On the next screen, press 'OK' when prompted to `Load driver` and select the `VirtIO SCSI` driver from the list that matches your Windows version. So for Windows 11, select `D:\amd64\w11\vioscsi.inf` and click 'Next'. + - Start the installation by clicking `Install now`. On the next screen, press 'OK' when prompted to `Load driver`. + + - Select the `VirtIO SCSI` driver from the list that matches your Windows version. So for Windows 11, select `D:\amd64\w11\vioscsi.inf` and click 'Next'. - Accept the license agreement and select your preferred Windows edition, like Home or Pro. - - Choose `Custom: Install Windows only (advanced)`, and click `Load driver` on the next screen. Select 'Browse' and navigate to the `D:\NetKVM\w11\amd64` folder, and click 'OK'. Select the `VirtIO Ethernet Adapter` from the list and click 'Next'. + - Choose `Custom: Install Windows only (advanced)`, and click `Load driver` on the next screen. + + - Select 'Browse' and navigate to the `D:\NetKVM\w11\amd64` folder, and click 'OK'. + + - Select the `VirtIO Ethernet Adapter` from the list and click 'Next'. - Select `Drive 0` and click 'Next'. - Wait until Windows finishes copying files and completes the installation. - - Once you see the desktop, open File Explorer and navigate to the CD-ROM drive (E:). Double-click on `virtio-win-gt-x64.msi` and proceed to install the VirtIO drivers. + - Once you see the desktop, open File Explorer and navigate to the CD-ROM drive (`E:\`). + + - Double-click on `virtio-win-gt-x64.msi` and proceed to install the VirtIO drivers. Enjoy your brand new machine, and don't forget to star this repo! diff --git a/src/install.sh b/src/install.sh index 64a72ad..550e4f1 100644 --- a/src/install.sh +++ b/src/install.sh @@ -12,32 +12,58 @@ hasDisk() { [ -b "/disk1" ] && return 0 [ -b "/dev/disk1" ] && return 0 [ -b "${DEVICE:-}" ] && return 0 - - if [ -s "$STORAGE/data.img" ] || [ -s "$STORAGE/data.qcow2" ]; then - return 0 - fi + [ -s "$STORAGE/data.img" ] && return 0 + [ -s "$STORAGE/data.qcow2" ] && return 0 return 1 } skipInstall() { - if hasDisk && [ -f "$STORAGE/windows.boot" ]; then - return 0 + local iso="$1" + local magic byte + local boot="$STORAGE/windows.boot" + local previous="$STORAGE/windows.base" + + if [ -f "$previous" ]; then + previous=$(<"$previous") + if [ -n "$previous" ]; then + previous="$STORAGE/$previous" + if [[ "${previous,,}" != "${iso,,}" ]]; then + if [ -f "$boot" ] && hasDisk; then + info "Detected that the version was changed, but ignoring this because Windows is already installed." + info "Please start with an empty /storage folder, if you want to install a different version of Windows." + return 0 + fi + [ -f "$previous" ] && rm -f "$previous" + return 1 + fi + fi fi - return 1 + [ -f "$boot" ] && hasDisk && return 0 + + [ ! -f "$iso" ] && return 1 + [ ! -s "$iso" ] && return 1 + + # Check if the ISO was already processed by our script + magic=$(dd if="$iso" seek=0 bs=1 count=1 status=none | tr -d '\000') + magic="$(printf '%s' "$magic" | od -A n -t x1 -v | tr -d ' \n')" + byte="16" && [[ "$MANUAL" == [Yy1]* ]] && byte="17" + + if [[ "$magic" != "$byte" ]]; then + info "The ISO will be processed again because the configuration was changed..." + return 1 + fi + + return 0 } startInstall() { html "Starting $APP..." - if [ -n "$CUSTOM" ]; then - - ISO="$CUSTOM" - - else + if [ -z "$CUSTOM" ]; then local file="${VERSION/\//}.iso" @@ -49,59 +75,26 @@ startInstall() { fi - ISO="$STORAGE/$file" + BOOT="$STORAGE/$file" - ! migrateFiles "$ISO" "$VERSION" && error "Migration failed!" && exit 57 + ! migrateFiles "$BOOT" "$VERSION" && error "Migration failed!" && exit 57 fi - skipInstall && return 1 - - if [ -f "$ISO" ] && [ -s "$ISO" ]; then - - local magic - local auto="16" - local manual="17" - local byte="$auto" - [[ "$MANUAL" == [Yy1]* ]] && byte="$manual" - - # Check if the ISO was already processed by our script - magic=$(dd if="$ISO" seek=0 bs=1 count=1 status=none | tr -d '\000') - magic="$(printf '%s' "$magic" | od -A n -t x1 -v | tr -d ' \n')" - - if [[ "$magic" == "$byte" ]]; then - if [ -z "$CUSTOM" ] || [ -n "$ORIGINAL" ]; then - return 1 - fi - fi - - fi + skipInstall "$BOOT" && return 1 rm -rf "$TMP" mkdir -p "$TMP" if [ -z "$CUSTOM" ]; then - BOOT="$ISO" - ISO=$(basename "$ISO") + ISO=$(basename "$BOOT") ISO="$TMP/$ISO" if [ -f "$BOOT" ] && [ -s "$BOOT" ]; then mv -f "$BOOT" "$ISO" fi - else - - if [ -n "$ORIGINAL" ]; then - rm -f "$ISO" - ISO="$ORIGINAL" - CUSTOM="$ISO" - fi - - local size - size="$(stat -c%s "$ISO")" - BOOT="$STORAGE/windows.$size.iso" - fi rm -f "$BOOT" @@ -112,26 +105,34 @@ finishInstall() { local iso="$1" local aborted="$2" + local base byte if [ ! -s "$iso" ] || [ ! -f "$iso" ]; then error "Failed to find ISO file: $iso" && return 1 fi - if [ -w "$iso" ] && [[ "$aborted" != [Yy1]* ]]; then + if [[ "$aborted" != [Yy1]* ]]; then # Mark ISO as prepared via magic byte - local byte="16" - [[ "$MANUAL" == [Yy1]* ]] && byte="17" + byte="16" && [[ "$MANUAL" == [Yy1]* ]] && byte="17" if ! printf '%b' "\x$byte" | dd of="$iso" bs=1 seek=0 count=1 conv=notrunc status=none; then - error "Failed to set magic byte in ISO file: $iso" && return 1 + warn "failed to set magic byte in ISO file: $iso" fi fi rm -f "$STORAGE/windows.old" + rm -f "$STORAGE/windows.base" rm -f "$STORAGE/windows.boot" rm -f "$STORAGE/windows.mode" cp -f /run/version "$STORAGE/windows.ver" + if [[ "$iso" == "$STORAGE/"* ]]; then + if [[ "$aborted" != [Yy1]* ]] || [ -z "$CUSTOM" ]; then + base=$(basename "$iso") + echo "$base" > "$STORAGE/windows.base" + fi + fi + if [[ "${PLATFORM,,}" == "x64" ]]; then if [[ "${BOOT_MODE,,}" == "windows_legacy" ]]; then echo "$BOOT_MODE" > "$STORAGE/windows.mode" @@ -180,7 +181,6 @@ detectCustom() { local size base CUSTOM="" - ORIGINAL="" if [[ "${VERSION,,}" != "http"* ]]; then base="${VERSION/\/storage\//}" @@ -202,15 +202,9 @@ detectCustom() { size="$(stat -c%s "$file")" [ -z "$size" ] || [[ "$size" == "0" ]] && return 0 - base="$STORAGE/windows.$size.iso" - - if [ -f "$base" ] && [ -s "$base" ]; then - CUSTOM="$base" - ORIGINAL="$file" - else - rm -f "$base" - CUSTOM="$file" - fi + ISO="$file" + CUSTOM="$ISO" + BOOT="$STORAGE/windows.$size.iso" return 0 } @@ -1045,13 +1039,11 @@ bootWindows() { rm -rf "$TMP" - if [ ! -f "$ISO" ] || [ ! -s "$ISO" ]; then - ISO="/custom.iso" - [ ! -f "$ISO" ] && ISO="${STORAGE}$ISO" + if [ ! -f "$BOOT" ] || [ ! -s "$BOOT" ]; then + BOOT="/custom.iso" + [ ! -f "$BOOT" ] && BOOT="${STORAGE}$BOOT" fi - BOOT="$ISO" - [[ "${PLATFORM,,}" == "arm64" ]] && VGA="virtio-gpu" if [ -s "$STORAGE/windows.mode" ] && [ -f "$STORAGE/windows.mode" ]; then