Skip to content

Commit

Permalink
feat: Improved installation (#545)
Browse files Browse the repository at this point in the history
  • Loading branch information
kroese authored May 27, 2024
1 parent a96941c commit fd83861
Show file tree
Hide file tree
Showing 9 changed files with 1,435 additions and 269 deletions.
5 changes: 3 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
FROM scratch
COPY --from=qemux/qemu-docker:5.07 / /
COPY --from=qemux/qemu-docker:5.08 / /

ARG VERSION_ARG="0.0"
ARG DEBCONF_NOWARNINGS="yes"
Expand All @@ -14,6 +14,7 @@ RUN set -eu && \
7zip \
wsdd \
samba \
xz-utils \
wimtools \
dos2unix \
cabextract \
Expand All @@ -27,7 +28,7 @@ COPY --chmod=755 ./src /run/
COPY --chmod=755 ./assets /run/assets

ADD --chmod=755 https://raw.githubusercontent.com/christgau/wsdd/v0.8/src/wsdd.py /usr/sbin/wsdd
ADD --chmod=664 https://github.com/qemus/virtiso/releases/download/v0.1.248/virtio-win-0.1.248.iso /run/drivers.iso
ADD --chmod=664 https://github.com/qemus/virtiso/releases/download/v0.1.248/virtio-win-0.1.248.tar.xz /drivers.txz

EXPOSE 8006 3389
VOLUME /storage
Expand Down
453 changes: 453 additions & 0 deletions assets/win11x64-iot.xml

Large diffs are not rendered by default.

453 changes: 453 additions & 0 deletions assets/win11x64-ltsc.xml

Large diffs are not rendered by default.

65 changes: 14 additions & 51 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,12 @@ kubectl apply -f kubernetes.yml
|---|---|---|
| `win11` | Windows 11 Pro | 6.4 GB |
| `win11e` | Windows 11 Enterprise | 5.8 GB |
| `win10` | Windows 10 Pro | 5.8 GB |
| `win10` | Windows 10 Pro | 5.7 GB |
| `ltsc10` | Windows 10 LTSC | 4.6 GB |
| `win10e` | Windows 10 Enterprise | 5.2 GB |
||||
| `win8` | Windows 8.1 Pro | 4.2 GB |
| `win8e` | Windows 8.1 Enterprise | 3.8 GB |
| `win8` | Windows 8.1 Pro | 4.0 GB |
| `win8e` | Windows 8.1 Enterprise | 3.7 GB |
| `win7` | Windows 7 Enterprise | 3.0 GB |
| `vista` | Windows Vista Enterprise | 3.0 GB |
| `winxp` | Windows XP Professional | 0.6 GB |
Expand Down Expand Up @@ -179,22 +179,9 @@ kubectl apply -f kubernetes.yml

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?

If you want to modify the settings used during the automatic installation, you can do this by editing the answer file corresponding to your Windows edition, for example [win11x64.xml](https://raw.githubusercontent.com/dockur/windows/master/assets/win11x64.xml) in the case of Windows 11 Pro.

Apply your modifications to it, and add this line to your compose file:

```yaml
volumes:
- /home/user/example.xml:/custom.xml
```

Replace the example path `/home/user/example.xml` with the filename of the modified XML file.

* ### How do I run a script after installation?

To run your own script after installation, you can create a file called `install.bat` and place it in a folder together with other files it needs (programs to install for example). Then bind it in your compose file like this:
To run your own script after installation, you can create a file called `install.bat` and place it in a folder together with any additional files it needs (software to be installed for example). Then bind that folder in your compose file like this:

```yaml
volumes:
Expand All @@ -205,7 +192,7 @@ kubectl apply -f kubernetes.yml

* ### How do I perform a manual installation?

It's best to use the automatic installation, as it prevents common issues that occur when running Windows inside a virtualized environment and optimizes various settings to give you maximum performance.
It's best to stick to the automatic installation, as it adjusts various settings to prevent common issues when running Windows inside a virtual environment.

However, if you insist on performing the installation manually, add the following environment variable to your compose file:

Expand All @@ -214,32 +201,6 @@ kubectl apply -f kubernetes.yml
MANUAL: "Y"
```

Then follow these steps:

- 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`.

- 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'.

- 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.

Enjoy your brand new machine, and don't forget to star this repo!

* ### How do I verify if my system supports KVM?

To verify if your system supports KVM, run the following commands:
Expand All @@ -251,11 +212,11 @@ kubectl apply -f kubernetes.yml

If you receive an error from `kvm-ok` indicating that KVM acceleration can't be used, check the virtualization settings in the BIOS.

* ### How do I increase the amount of CPU or RAM?
* ### How do I change the amount of CPU or RAM?

By default, 2 CPU cores and 4 GB of RAM are allocated to the container, as those are the minimum requirements of Windows 11.
By default, the container will be allowed to use a maximum of 2 CPU cores and 4 GB of RAM.

If there arises a need to increase this, add the following environment variables:
If you want to adjust this, you can specify the desired amount using the following environment variables:

```yaml
environment:
Expand All @@ -265,12 +226,14 @@ kubectl apply -f kubernetes.yml

* ### How do I configure the username and password?

By default, a user called `Docker` is created during installation with an empty password. You can change these credentials in your compose file:
By default, a user called `Docker` is created during the installation, with an empty password.

If you want to use different credentials, you can change them in your compose file:

```yaml
environment:
USERNAME: "john"
PASSWORD: "secret"
USERNAME: "bill"
PASSWORD: "gates"
```

* ### How do I connect using RDP?
Expand All @@ -279,7 +242,7 @@ kubectl apply -f kubernetes.yml

So for a better experience you can connect using any Microsoft Remote Desktop client to the IP of the container, using the username `Docker` and by leaving the password empty.

There is a good RDP client for [Android](https://play.google.com/store/apps/details?id=com.microsoft.rdc.androidx) available from the Play Store and one for [iOS](https://apps.apple.com/nl/app/microsoft-remote-desktop/id714464092?l=en-GB) in the Apple Store. For Linux you can use [FreeRDP](https://www.freerdp.com/) and on Windows just type `mstsc` in the search box.
There is a RDP client for [Android](https://play.google.com/store/apps/details?id=com.microsoft.rdc.androidx) available from the Play Store and one for [iOS](https://apps.apple.com/nl/app/microsoft-remote-desktop/id714464092?l=en-GB) in the Apple Store. For Linux you can use [FreeRDP](https://www.freerdp.com/) and on Windows just type `mstsc` in the search box.

* ### How do I assign an individual IP address to the container?

Expand Down
128 changes: 99 additions & 29 deletions src/define.sh
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ parseVersion() {
VERSION="win10x64-enterprise-iot-eval"
[ -z "$DETECTED" ] && DETECTED="win10x64-iot"
;;
"ltsc11" | "11ltsc" | "win11-ltsc" | "win11x64-ltsc" | "win11x64-enterprise-ltsc-eval" )
VERSION="win11x64-enterprise-ltsc-eval"
[ -z "$DETECTED" ] && DETECTED="win11x64-iot"
;;
"ltsc10" | "10ltsc" | "win10-ltsc" | "win10x64-ltsc" | "win10x64-enterprise-ltsc-eval" )
VERSION="win10x64-enterprise-ltsc-eval"
[ -z "$DETECTED" ] && DETECTED="win10x64-ltsc"
Expand Down Expand Up @@ -358,6 +362,10 @@ printVersion() {
"win10"* ) desc="Windows 10" ;;
"win11"* ) desc="Windows 11" ;;
"winxp"* ) desc="Windows XP" ;;
"win9x"* ) desc="Windows ME" ;;
"win98"* ) desc="Windows 98" ;;
"win95"* ) desc="Windows 95" ;;
"win2k"* ) desc="Windows 2000" ;;
"winvista"* ) desc="Windows Vista" ;;
"win2025"* ) desc="Windows Server 2025" ;;
"win2022"* ) desc="Windows Server 2022" ;;
Expand Down Expand Up @@ -556,19 +564,10 @@ getVersion() {
*" enterprise"* ) id="$id-enterprise" ;;
esac
;;
"win10"* )
case "${name,,}" in
*" iot"* ) id="$id-iot" ;;
*" ltsc"* ) id="$id-ltsc" ;;
*" home"* ) id="$id-home" ;;
*" education"* ) id="$id-education" ;;
*" enterprise evaluation"* ) id="$id-enterprise-eval" ;;
*" enterprise"* ) id="$id-enterprise" ;;
esac
;;
"win11"* )
"win10"* | "win11"* )
case "${name,,}" in
*" iot"* ) id="$id-iot" ;;
*" ltsc"* ) id="$id-ltsc" ;;
*" home"* ) id="$id-home" ;;
*" education"* ) id="$id-education" ;;
*" enterprise evaluation"* ) id="$id-enterprise-eval" ;;
Expand Down Expand Up @@ -629,6 +628,14 @@ getMido() {
size=6209064960
sum="c8dbc96b61d04c8b01faf6ce0794fdf33965c7b350eaa3eb1e6697019902945c"
;;
"win11x64-enterprise-ltsc-eval" )
size=4428627968
sum="8abf91c9cd408368dc73aab3425d5e3c02dae74900742072eb5c750fc637c195"
;;
"win11x64-enterprise-iot-eval" )
size=4428627968
sum="8abf91c9cd408368dc73aab3425d5e3c02dae74900742072eb5c750fc637c195"
;;
"win10x64" )
size=6140975104
sum="a6f470ca6d331eb353b815c043e327a347f594f37ff525f17764738fe812852e"
Expand Down Expand Up @@ -1034,6 +1041,18 @@ getLink4() {
"zh" | "zh-"* ) url="zh-cn_windows_11_business_editions_version_23h2_updated_april_2024_x64_dvd_3db5a62b.iso" ;;
esac
;;
"win11x64-iot" | "win11x64-enterprise-iot-eval" )
[[ "${lang,,}" != "en" ]] && [[ "${lang,,}" != "en-us" ]] && return 0
size=4821989376
sum="e8f1431c4e6289b3997c20eadbb2576670300bb6e1cf8948b5d7af179010a962"
url="26100.1.240331-1435.ge_release_CLIENTENTERPRISE_OEM_x64FRE_en-us.iso"
;;
"win11x64-ltsc" | "win11x64-enterprise-ltsc-eval" )
[[ "${lang,,}" != "en" ]] && [[ "${lang,,}" != "en-us" ]] && return 0
size=4821989376
sum="e8f1431c4e6289b3997c20eadbb2576670300bb6e1cf8948b5d7af179010a962"
url="26100.1.240331-1435.ge_release_CLIENTENTERPRISE_OEM_x64FRE_en-us.iso"
;;
"win10x64" )
case "${culture,,}" in
"ar" | "ar-"* ) url="ar-sa_windows_10_consumer_editions_version_22h2_updated_april_2024_x64_dvd_9a92dc89.iso" ;;
Expand Down Expand Up @@ -1169,12 +1188,6 @@ getLink4() {
"zh" | "zh-"* ) url="zh-cn_windows_10_enterprise_ltsc_2021_x64_dvd_033b7312.iso" ;;
esac
;;
"win11x64-iot" | "win11x64-enterprise-iot-eval" )
[[ "${lang,,}" != "en" ]] && [[ "${lang,,}" != "en-us" ]] && return 0
size=6248140800
sum="5d9b86ad467bc89f488d1651a6c5ad3656a7ea923f9f914510657a24c501bb86"
url="en-us_windows_11_iot_enterprise_version_23h2_x64_dvd_fb37549c.iso"
;;
"win10x64-iot" | "win10x64-enterprise-iot-eval" )
[[ "${lang,,}" != "en" ]] && [[ "${lang,,}" != "en-us" ]] && return 0
size=4851668992
Expand Down Expand Up @@ -1918,6 +1931,32 @@ prepareLegacy() {
return 1
}

prepare9x() {

local iso="$1"
local dir="$2"
local file="$dir/boot.img"

ETFS=$(basename "$file")
[ -f "$file" ] && [ -s "$file" ] && return 0
rm -f "$file"

local src="[BOOT]/Boot-1.44M.img"
[ ! -f "$dir/$src" ] && error "Boot floppy not found!" && return 1

cp "$dir/$src" "$file" && return 0

return 1
}

prepare2k() {

local dir="$2"
ETFS="[BOOT]/Boot-NoEmul.img"

return 0
}

prepareXP() {

local dir="$2"
Expand All @@ -1932,10 +1971,13 @@ prepareXP() {
target="$dir/AMD64"
fi

rm -rf "$drivers"
local msg="Adding drivers to image..."
info "$msg" && html "$msg"

mkdir -p "$drivers"

if ! 7z x /run/drivers.iso -o"$drivers" > /dev/null; then
error "Failed to extract driver ISO file!" && return 1
if ! tar -xf /drivers.txz -C "$drivers" --warning=no-timestamp; then
error "Failed to extract driver!" && return 1
fi

cp "$drivers/viostor/xp/$arch/viostor.sys" "$target"
Expand Down Expand Up @@ -1978,14 +2020,16 @@ prepareXP() {
sed -i '/^\[SCSI\]/s/$/\niaStor=\"Intel\(R\) SATA RAID\/AHCI Controller\"/' "$target/TXTSETUP.SIF"
sed -i '/^\[HardwareIdsDatabase\]/s/$/\nPCI\\VEN_8086\&DEV_2922\&CC_0106=\"iaStor\"/' "$target/TXTSETUP.SIF"

local key pid setup
rm -rf "$drivers"

local key pid file setup
setup=$(find "$target" -maxdepth 1 -type f -iname setupp.ini | head -n 1)
pid=$(<"$setup")
pid="${pid:(-4)}"
pid="${pid:0:3}"

if [[ "$pid" == "270" ]]; then
info "Warning: this XP version requires a volume license, it will reject the generic key during installation."
warn "this version of Windows XP requires a volume license key (VLK), it will ask for one during installation."
fi

if [[ "${arch,,}" == "x86" ]]; then
Expand All @@ -1998,10 +2042,28 @@ prepareXP() {
key="B2RBK-7KPT9-4JP6X-QQFWM-PJD6G"
fi

local oem=""
local folder="/oem"

[ ! -d "$folder" ] && folder="/OEM"
[ ! -d "$folder" ] && folder="$STORAGE/oem"
[ ! -d "$folder" ] && folder="$STORAGE/OEM"

if [ -d "$folder" ]; then

file=$(find "$folder" -maxdepth 1 -type f -iname install.bat | head -n 1)

if [ -f "$file" ]; then
unix2dos -q "$file"
oem="\"Script\"=\"cmd /C start \\\"Install\\\" \\\"cmd /C C:\\\\OEM\\\\install.bat\\\"\""
fi
fi

local username="Docker"
local password="*"
[ -n "$USERNAME" ] && username="$USERNAME"

[ -n "$PASSWORD" ] && password="$PASSWORD"
[ -n "$USERNAME" ] && username=$(echo "$USERNAME" | sed 's/[^[:alnum:]@!._-]//g')

find "$target" -maxdepth 1 -type f -iname winnt.sif -exec rm {} \;

Expand Down Expand Up @@ -2055,9 +2117,6 @@ prepareXP() {
echo " Home_Page = http://www.google.com"
echo " Search_Page = http://www.google.com"
echo ""
echo "[RegionalSettings]"
echo " Language=00000409"
echo ""
echo "[TerminalServices]"
echo " AllowConnections=1"
echo ""
Expand Down Expand Up @@ -2098,10 +2157,10 @@ prepareXP() {
echo "\"DefaultSettings.XResolution\"=dword:00000780"
echo "\"DefaultSettings.YResolution\"=dword:00000438"
echo ""
echo "[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnceEx]"
echo "[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce]"
echo "\"ScreenSaver\"=\"reg add \\\"HKCU\\\\Control Panel\\\\Desktop\\\" /f /v \\\"SCRNSAVE.EXE\\\" /t REG_SZ /d \\\"off\\\"\""
echo "\"ScreenSaverOff\"=\"reg add \\\"HKCU\\\\Control Panel\\\\Desktop\\\" /f /v \\\"ScreenSaveActive\\\" /t REG_SZ /d \\\"0\\\"\""
echo ""
echo "$oem"
} | unix2dos > "$dir/\$OEM\$/install.reg"

{ echo "Set WshShell = WScript.CreateObject(\"WScript.Shell\")"
Expand All @@ -2118,7 +2177,18 @@ prepareXP() {
echo ""
} | unix2dos > "$dir/\$OEM\$/cmdlines.txt"

rm -rf "$drivers"
[ ! -d "$folder" ] && return 0

msg="Adding OEM folder to image..."
info "$msg" && html "$msg"

local dest="$dir/\$OEM\$/\$1/"
mkdir -p "$dest"

if ! cp -r "$folder" "$dest"; then
error "Failed to copy OEM folder!" && return 1
fi

return 0
}

Expand Down
2 changes: 1 addition & 1 deletion src/entry.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,4 @@ cat "$QEMU_TERM" 2> /dev/null | tee "$QEMU_PTY" &
wait $! || :

sleep 1 & wait $!
finish 0
[ ! -f "$QEMU_END" ] && finish 0
Loading

0 comments on commit fd83861

Please sign in to comment.