Compare commits

..

No commits in common. "master" and "v4.29" have entirely different histories.

15 changed files with 114 additions and 190 deletions

View file

@ -21,7 +21,6 @@ body:
attributes: attributes:
label: Docker compose label: Docker compose
description: The compose file (or otherwise the `docker run` command used). description: The compose file (or otherwise the `docker run` command used).
render: yaml
validations: validations:
required: true required: true
- type: textarea - type: textarea
@ -29,7 +28,6 @@ body:
attributes: attributes:
label: Docker log label: Docker log
description: The logfile of the container (as shown by `docker logs windows`). description: The logfile of the container (as shown by `docker logs windows`).
render: shell
validations: validations:
required: true required: true
- type: textarea - type: textarea

View file

@ -23,7 +23,6 @@ body:
attributes: attributes:
label: Docker compose label: Docker compose
description: The compose file (or otherwise the `docker run` command used). description: The compose file (or otherwise the `docker run` command used).
render: yaml
validations: validations:
required: true required: true
- type: textarea - type: textarea
@ -31,7 +30,6 @@ body:
attributes: attributes:
label: Docker log label: Docker log
description: The logfile of the container (as shown by `docker logs windows`). description: The logfile of the container (as shown by `docker logs windows`).
render: shell
validations: validations:
required: true required: true
- type: textarea - type: textarea

View file

@ -50,7 +50,7 @@ jobs:
labels: | labels: |
org.opencontainers.image.title=${{ vars.NAME }} org.opencontainers.image.title=${{ vars.NAME }}
env: env:
DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest
- -
name: Set up Docker Buildx name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
@ -74,7 +74,7 @@ jobs:
context: . context: .
push: true push: true
provenance: false provenance: false
platforms: linux/amd64,linux/arm64 platforms: linux/arm64
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
annotations: ${{ steps.meta.outputs.annotations }} annotations: ${{ steps.meta.outputs.annotations }}

View file

@ -1,5 +1,5 @@
FROM scratch FROM scratch
COPY --from=qemux/qemu-arm:7.12 / / COPY --from=qemux/qemu-arm:7.07 / /
ARG VERSION_ARG="0.00" ARG VERSION_ARG="0.00"
ARG DEBCONF_NOWARNINGS="yes" ARG DEBCONF_NOWARNINGS="yes"
@ -15,8 +15,7 @@ RUN set -eu && \
dos2unix \ dos2unix \
cabextract \ cabextract \
libxml2-utils \ libxml2-utils \
libarchive-tools \ libarchive-tools && \
netcat-openbsd && \
apt-get clean && \ apt-get clean && \
echo "$VERSION_ARG" > /run/version && \ echo "$VERSION_ARG" > /run/version && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
@ -24,7 +23,7 @@ RUN set -eu && \
COPY --chmod=755 ./src /run/ COPY --chmod=755 ./src /run/
COPY --chmod=755 ./assets /run/assets COPY --chmod=755 ./assets /run/assets
ADD --chmod=664 https://github.com/qemus/virtiso-arm/releases/download/v0.1.271-1/virtio-win-0.1.271.tar.xz /var/drivers.txz ADD --chmod=664 https://github.com/qemus/virtiso-arm/releases/download/v0.1.266-1/virtio-win-0.1.266.tar.xz /drivers.txz
VOLUME /storage VOLUME /storage
EXPOSE 3389 8006 EXPOSE 3389 8006

View file

@ -326,6 +326,11 @@
<CommandLine>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters" /v "AllowInsecureGuestAuth" /t REG_DWORD /d 1 /f</CommandLine> <CommandLine>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters" /v "AllowInsecureGuestAuth" /t REG_DWORD /d 1 /f</CommandLine>
<Description>Allow guest access to network shares</Description> <Description>Allow guest access to network shares</Description>
</SynchronousCommand> </SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>2</Order>
<CommandLine>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Control\Lsa" /v LimitBlankPasswordUse /t REG_DWORD /d 0 /f</CommandLine>
<Description>Allow RDP login with blank password</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add"> <SynchronousCommand wcm:action="add">
<Order>3</Order> <Order>3</Order>
<CommandLine>reg.exe add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\PasswordLess\Device" /v "DevicePasswordLessBuildVersion" /t REG_DWORD /d 0 /f</CommandLine> <CommandLine>reg.exe add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\PasswordLess\Device" /v "DevicePasswordLessBuildVersion" /t REG_DWORD /d 0 /f</CommandLine>

View file

@ -329,6 +329,11 @@
<CommandLine>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters" /v "AllowInsecureGuestAuth" /t REG_DWORD /d 1 /f</CommandLine> <CommandLine>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters" /v "AllowInsecureGuestAuth" /t REG_DWORD /d 1 /f</CommandLine>
<Description>Allow guest access to network shares</Description> <Description>Allow guest access to network shares</Description>
</SynchronousCommand> </SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>2</Order>
<CommandLine>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Control\Lsa" /v LimitBlankPasswordUse /t REG_DWORD /d 0 /f</CommandLine>
<Description>Allow RDP login with blank password</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add"> <SynchronousCommand wcm:action="add">
<Order>3</Order> <Order>3</Order>
<CommandLine>reg.exe add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\PasswordLess\Device" /v "DevicePasswordLessBuildVersion" /t REG_DWORD /d 0 /f</CommandLine> <CommandLine>reg.exe add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\PasswordLess\Device" /v "DevicePasswordLessBuildVersion" /t REG_DWORD /d 0 /f</CommandLine>

View file

@ -326,6 +326,11 @@
<CommandLine>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters" /v "AllowInsecureGuestAuth" /t REG_DWORD /d 1 /f</CommandLine> <CommandLine>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters" /v "AllowInsecureGuestAuth" /t REG_DWORD /d 1 /f</CommandLine>
<Description>Allow guest access to network shares</Description> <Description>Allow guest access to network shares</Description>
</SynchronousCommand> </SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>2</Order>
<CommandLine>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Control\Lsa" /v LimitBlankPasswordUse /t REG_DWORD /d 0 /f</CommandLine>
<Description>Allow RDP login with blank password</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add"> <SynchronousCommand wcm:action="add">
<Order>3</Order> <Order>3</Order>
<CommandLine>reg.exe add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\PasswordLess\Device" /v "DevicePasswordLessBuildVersion" /t REG_DWORD /d 0 /f</CommandLine> <CommandLine>reg.exe add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\PasswordLess\Device" /v "DevicePasswordLessBuildVersion" /t REG_DWORD /d 0 /f</CommandLine>

View file

@ -355,6 +355,11 @@
<CommandLine>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters" /v "RequireSecuritySignature" /t REG_DWORD /d 0 /f</CommandLine> <CommandLine>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters" /v "RequireSecuritySignature" /t REG_DWORD /d 0 /f</CommandLine>
<Description>Disable SMB signing requirement</Description> <Description>Disable SMB signing requirement</Description>
</SynchronousCommand> </SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>3</Order>
<CommandLine>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Control\Lsa" /v LimitBlankPasswordUse /t REG_DWORD /d 0 /f</CommandLine>
<Description>Allow RDP login with blank password</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add"> <SynchronousCommand wcm:action="add">
<Order>4</Order> <Order>4</Order>
<CommandLine>reg.exe add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\PasswordLess\Device" /v "DevicePasswordLessBuildVersion" /t REG_DWORD /d 0 /f</CommandLine> <CommandLine>reg.exe add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\PasswordLess\Device" /v "DevicePasswordLessBuildVersion" /t REG_DWORD /d 0 /f</CommandLine>

View file

@ -354,6 +354,11 @@
<CommandLine>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters" /v "RequireSecuritySignature" /t REG_DWORD /d 0 /f</CommandLine> <CommandLine>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters" /v "RequireSecuritySignature" /t REG_DWORD /d 0 /f</CommandLine>
<Description>Disable SMB signing requirement</Description> <Description>Disable SMB signing requirement</Description>
</SynchronousCommand> </SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>3</Order>
<CommandLine>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Control\Lsa" /v LimitBlankPasswordUse /t REG_DWORD /d 0 /f</CommandLine>
<Description>Allow RDP login with blank password</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add"> <SynchronousCommand wcm:action="add">
<Order>4</Order> <Order>4</Order>
<CommandLine>reg.exe add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\PasswordLess\Device" /v "DevicePasswordLessBuildVersion" /t REG_DWORD /d 0 /f</CommandLine> <CommandLine>reg.exe add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\PasswordLess\Device" /v "DevicePasswordLessBuildVersion" /t REG_DWORD /d 0 /f</CommandLine>

View file

@ -355,6 +355,11 @@
<CommandLine>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters" /v "RequireSecuritySignature" /t REG_DWORD /d 0 /f</CommandLine> <CommandLine>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters" /v "RequireSecuritySignature" /t REG_DWORD /d 0 /f</CommandLine>
<Description>Disable SMB signing requirement</Description> <Description>Disable SMB signing requirement</Description>
</SynchronousCommand> </SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>3</Order>
<CommandLine>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Control\Lsa" /v LimitBlankPasswordUse /t REG_DWORD /d 0 /f</CommandLine>
<Description>Allow RDP login with blank password</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add"> <SynchronousCommand wcm:action="add">
<Order>4</Order> <Order>4</Order>
<CommandLine>reg.exe add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\PasswordLess\Device" /v "DevicePasswordLessBuildVersion" /t REG_DWORD /d 0 /f</CommandLine> <CommandLine>reg.exe add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\PasswordLess\Device" /v "DevicePasswordLessBuildVersion" /t REG_DWORD /d 0 /f</CommandLine>

View file

@ -53,7 +53,7 @@ services:
##### Via Docker CLI: ##### Via Docker CLI:
```bash ```bash
docker run -it --rm --name windows -p 8006:8006 --device=/dev/kvm --device=/dev/net/tun --cap-add NET_ADMIN -v "${PWD:-.}/windows:/storage" --stop-timeout 120 dockurr/windows docker run -it --rm --name windows -p 8006:8006 --device=/dev/kvm --device=/dev/net/tun --cap-add NET_ADMIN -v ${PWD:-.}/windows:/storage --stop-timeout 120 dockurr/windows
``` ```
##### Via Kubernetes: ##### Via Kubernetes:
@ -168,7 +168,7 @@ The example folder `./example` will be available as ` \\host.lan\Data`.
### How do I configure the username and password? ### How do I configure the username and password?
By default, a user called `Docker` is created during installation and its password is `admin`. By default, a user called `Docker` (with an empty password) is created during installation.
If you want to use different credentials, you can configure them in your compose file (only before installation): If you want to use different credentials, you can configure them in your compose file (only before installation):
@ -201,6 +201,15 @@ The example folder `./example` will be available as ` \\host.lan\Data`.
KEYBOARD: "en-US" KEYBOARD: "en-US"
``` ```
### How do I set the product key?
By default, an evaluation version of Windows will be installed, but if you have a product key you can add a `KEY` variable like this (before installation):
```yaml
environment:
KEY: "xxxxx-xxxxx-xxxxx-xxxxx-xxxxx"
```
### How do I install a custom image? ### How do I install a custom image?
In order to download an unsupported ISO image, specify its URL in the `VERSION` environment variable: In order to download an unsupported ISO image, specify its URL in the `VERSION` environment variable:
@ -214,7 +223,7 @@ The example folder `./example` will be available as ` \\host.lan\Data`.
```yaml ```yaml
volumes: volumes:
- ./example.iso:/boot.iso - ./example.iso:/custom.iso
``` ```
Replace the example path `./example.iso` with the filename of your desired ISO file. The value of `VERSION` will be ignored in this case. Replace the example path `./example.iso` with the filename of your desired ISO file. The value of `VERSION` will be ignored in this case.
@ -236,7 +245,7 @@ The example folder `./example` will be available as ` \\host.lan\Data`.
It's recommended to stick to the automatic installation, as it adjusts various settings to prevent common issues when running Windows inside a virtual environment. It's recommended 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 at your own risk, add the following environment variable to your compose file: However, if you insist on performing the installation manually on your own risk, add the following environment variable to your compose file:
```yaml ```yaml
environment: environment:
@ -247,7 +256,7 @@ The example folder `./example` will be available as ` \\host.lan\Data`.
The web-viewer is mainly meant to be used during installation, as its picture quality is low, and it has no audio or clipboard for example. The web-viewer is mainly meant to be used during installation, as its picture quality is low, and it has no audio or clipboard for example.
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 password `admin`. 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 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.
@ -318,12 +327,12 @@ The example folder `./example` will be available as ` \\host.lan\Data`.
### How do I pass-through a disk? ### How do I pass-through a disk?
It is possible to pass-through disk devices or partitions directly by adding them to your compose file in this way: It is possible to pass-through disk devices directly by adding them to your compose file in this way:
```yaml ```yaml
devices: devices:
- /dev/sdb:/disk1 - /dev/sdb:/disk1
- /dev/sdc1:/disk2 - /dev/sdc:/disk2
``` ```
Use `/disk1` if you want it to become your main drive (which will be formatted during installation), and use `/disk2` and higher to add them as secondary drives (which will stay untouched). Use `/disk1` if you want it to become your main drive (which will be formatted during installation), and use `/disk2` and higher to add them as secondary drives (which will stay untouched).

View file

@ -61,23 +61,20 @@ parseVersion() {
"8e" | "81e" | "8.1e" | "win8e" | "win81e" | "windows 8e" ) "8e" | "81e" | "8.1e" | "win8e" | "win81e" | "windows 8e" )
error "Windows 8 $msg" && return 1 error "Windows 8 $msg" && return 1
;; ;;
"7" | "win7" | "windows7" | "windows 7" | "7u" | "win7u" | "windows7u" | "windows 7u" | "7e" | \ "7" | "7e" | "win7" | "win7e" | "windows7" | "windows 7" | \
"win7e" | "windows7e" | "windows 7e" | "7x86" | "win7x86" | "win732" | "windows7x86" | "7ux86" | \ "7u" | "win7u" | "windows7u" | "windows 7u" | \
"7u32" | "win7x86-ultimate" | "7ex86" | "7e32" | "win7x86-enterprise" ) "7x86" | "win7x86" | "windows7x86" | "win7x86-enterprise" )
error "Windows 7 $msg" && return 1 error "Windows 7 $msg" && return 1
;; ;;
"vista" | "vs" | "6" | "winvista" | "windowsvista" | "windows vista" | "vistu" | "vu" | "6u" | "winvistu" | \ "vista" | "ve" | "6" | "winvista" | "windowsvista" | "windows vista" | \
"viste" | "ve" | "6e" | "winviste" | "vistax86" | "vista32" | "6x86" | "winvistax86" | "windowsvistax86" | \ "vistu" | "vu" | "6u" | "winvistu" | "windowsvistu" | "windows vistu" | \
"vux86" | "vu32" | "winvistax86-ultimate" | "vex86" | "ve32" | "winvistax86-enterprise" ) "vistax86" | "vex86" | "6x86" | "winvistax86" | "windowsvistax86" | "winvistax86-enterprise" )
error "Windows Vista $msg" && return 1 error "Windows Vista $msg" && return 1
;; ;;
"xp" | "xp32" | "xpx86" | "5" | "5x86" | "winxp" | "winxp86" | "windowsxp" | "windows xp" | \ "xp" | "xp32" | "xpx86" | "5" | "5x86" | "winxp" | "winxp86" | "windowsxp" | "windows xp" | \
"xp64" | "xpx64" | "5x64" | "winxp64" | "winxpx64" | "windowsxp64" | "windowsxpx64" ) "xp64" | "xpx64" | "5x64" | "winxp64" | "winxpx64" | "windowsxp64" | "windowsxpx64" )
error "Windows XP $msg" && return 1 error "Windows XP $msg" && return 1
;; ;;
"2k" | "2000" | "win2k" | "win2000" | "windows2k" | "windows2000" )
error "Windows 2000 $msg" && return 1
;;
"25" | "2025" | "win25" | "win2025" | "windows2025" | "windows 2025" ) "25" | "2025" | "win25" | "win2025" | "windows2025" | "windows 2025" )
error "Windows Server 2025 $msg" && return 1 error "Windows Server 2025 $msg" && return 1
;; ;;
@ -90,7 +87,7 @@ parseVersion() {
"16" | "2016" | "win16" | "win2016" | "windows2016" | "windows 2016" ) "16" | "2016" | "win16" | "win2016" | "windows2016" | "windows 2016" )
error "Windows Server 2016 $msg" && return 1 error "Windows Server 2016 $msg" && return 1
;; ;;
"hv" | "hyperv" | "hyper v" | "hyper-v" | "19hv" | "2019hv" | "win2019hv" ) "hv" | "hyperv" | "hyper v" | "hyper-v" | "19hv" | "2019hv" | "win2019hv")
error "Hyper-V Server 2019 $msg" && return 1 error "Hyper-V Server 2019 $msg" && return 1
;; ;;
"2012" | "2012r2" | "win2012" | "win2012r2" | "windows2012" | "windows 2012" ) "2012" | "2012r2" | "win2012" | "win2012r2" | "windows2012" | "windows 2012" )
@ -645,31 +642,6 @@ getLink2() {
sum="812dae6b5bf5215db63b61ae10d8f0ffd3aa8529a18d96e9ced53341e2c676ec" sum="812dae6b5bf5215db63b61ae10d8f0ffd3aa8529a18d96e9ced53341e2c676ec"
url="tiny11-core-arm64/tiny11%20core%20arm64.iso" url="tiny11-core-arm64/tiny11%20core%20arm64.iso"
;; ;;
"win11arm64" )
size=5460387840
sum="57d1dfb2c6690a99fe99226540333c6c97d3fd2b557a50dfe3d68c3f675ef2b0"
url="windows-11-24h2-arm64-iso/Win11_24H2_English_Arm64.iso"
;;
"win11arm64-enterprise" | "win11arm64-enterprise-eval" )
size=6872444928
sum="2bf0fd1d5abd267cd0ae8066fea200b3538e60c3e572428c0ec86d4716b61cb7"
url="win11-23h2-en-fr/ARM64/SW_DVD9_Win_Pro_11_23H2_Arm64_English_Pro_Ent_EDU_N_MLF_X23-59519.ISO"
;;
"win11arm64-ltsc" | "win11arm64-enterprise-ltsc-eval" )
size=5121449984
sum="f8f068cdc90c894a55d8c8530db7c193234ba57bb11d33b71383839ac41246b4"
url="Windows11LTSC/X23-81950_26100.1742.240906-0331.ge_release_svc_refresh_CLIENT_ENTERPRISES_OEM_A64FRE_en-us.iso"
;;
"win10arm64" | "win10arm64-enterprise" | "win10arm64-enterprise-eval" )
size=5192060928
sum="101079b911c8c3dd9c9a88499a16b930fbf00cbaf901761d8265bb3a8fcd9ea9"
url="win-pro-10-22-h-2.15-arm-64-eng-intl-pro-ent-edu-n-mlf-x-23-67222/Win_Pro_10_22H2.15_Arm64_Eng_Intl_Pro_Ent_EDU_N_MLF_X23-67222.ISO"
;;
"win10arm64-ltsc" | "win10arm64-enterprise-ltsc-eval" )
size=4430471168
sum="d265df49b30a1477d010c79185a7bc88591a1be4b3eb690c994bed828ea17c00"
url="windows-10-enterprise-ltsc-full-collection/en-us_windows_10_iot_enterprise_ltsc_2021_arm64_dvd_e8d4fc46.iso"
;;
esac esac
case "${ret,,}" in case "${ret,,}" in
@ -793,7 +765,7 @@ addFolder() {
cp -Lr "$folder/." "$dest" || return 1 cp -Lr "$folder/." "$dest" || return 1
local file local file
file=$(find "$dest" -maxdepth 1 -type f -iname install.bat -print -quit) file=$(find "$dest" -maxdepth 1 -type f -iname install.bat | head -n 1)
[ -f "$file" ] && unix2dos -q "$file" [ -f "$file" ] && unix2dos -q "$file"
return 0 return 0

View file

@ -128,8 +128,6 @@ finishInstall() {
rm -f "$STORAGE/windows.old" rm -f "$STORAGE/windows.old"
rm -f "$STORAGE/windows.vga" rm -f "$STORAGE/windows.vga"
rm -f "$STORAGE/windows.net"
rm -f "$STORAGE/windows.usb"
rm -f "$STORAGE/windows.args" rm -f "$STORAGE/windows.args"
rm -f "$STORAGE/windows.base" rm -f "$STORAGE/windows.base"
rm -f "$STORAGE/windows.boot" rm -f "$STORAGE/windows.boot"
@ -172,22 +170,10 @@ finishInstall() {
echo "$ARGS" > "$STORAGE/windows.args" echo "$ARGS" > "$STORAGE/windows.args"
fi fi
if [ -n "${VGA:-}" ] && [[ "${VGA:-}" != "virtio"* ]]; then
echo "$VGA" > "$STORAGE/windows.vga"
fi
if [ -n "${USB:-}" ] && [[ "${USB:-}" != "qemu-xhci"* ]]; then
echo "$USB" > "$STORAGE/windows.usb"
fi
if [ -n "${DISK_TYPE:-}" ] && [[ "${DISK_TYPE:-}" != "scsi" ]]; then if [ -n "${DISK_TYPE:-}" ] && [[ "${DISK_TYPE:-}" != "scsi" ]]; then
echo "$DISK_TYPE" > "$STORAGE/windows.type" echo "$DISK_TYPE" > "$STORAGE/windows.type"
fi fi
if [ -n "${ADAPTER:-}" ] && [[ "${ADAPTER:-}" != "virtio-net-pci" ]]; then
echo "$ADAPTER" > "$STORAGE/windows.net"
fi
rm -rf "$TMP" rm -rf "$TMP"
return 0 return 0
} }
@ -199,9 +185,8 @@ abortInstall() {
local efi local efi
[[ "${iso,,}" == *".esd" ]] && exit 60 [[ "${iso,,}" == *".esd" ]] && exit 60
[[ "${UNPACK:-}" == [Yy1]* ]] && exit 60
efi=$(find "$dir" -maxdepth 1 -type d -iname efi -print -quit) efi=$(find "$dir" -maxdepth 1 -type d -iname efi | head -n 1)
if [ -z "$efi" ]; then if [ -z "$efi" ]; then
[[ "${PLATFORM,,}" == "x64" ]] && BOOT_MODE="windows_legacy" [[ "${PLATFORM,,}" == "x64" ]] && BOOT_MODE="windows_legacy"
@ -222,14 +207,16 @@ abortInstall() {
return 1 return 1
} }
findFile() { detectCustom() {
local dir file base local dir file base
local fname="$1" local fname="custom.iso"
local boot="$STORAGE/windows.boot" local boot="$STORAGE/windows.boot"
dir=$(find / -maxdepth 1 -type d -iname "$fname" -print -quit) CUSTOM=""
[ ! -d "$dir" ] && dir=$(find "$STORAGE" -maxdepth 1 -type d -iname "$fname" -print -quit)
dir=$(find / -maxdepth 1 -type d -iname "$fname" | head -n 1)
[ ! -d "$dir" ] && dir=$(find "$STORAGE" -maxdepth 1 -type d -iname "$fname" | head -n 1)
if [ -d "$dir" ]; then if [ -d "$dir" ]; then
if ! hasDisk || [ ! -f "$boot" ]; then if ! hasDisk || [ ! -f "$boot" ]; then
@ -237,8 +224,8 @@ findFile() {
fi fi
fi fi
file=$(find / -maxdepth 1 -type f -iname "$fname" -print -quit) file=$(find / -maxdepth 1 -type f -iname "$fname" | head -n 1)
[ ! -s "$file" ] && file=$(find "$STORAGE" -maxdepth 1 -type f -iname "$fname" -print -quit) [ ! -s "$file" ] && file=$(find "$STORAGE" -maxdepth 1 -type f -iname "$fname" | head -n 1)
if [ ! -s "$file" ] && [[ "${VERSION,,}" != "http"* ]]; then if [ ! -s "$file" ] && [[ "${VERSION,,}" != "http"* ]]; then
base=$(basename "$VERSION") base=$(basename "$VERSION")
@ -254,25 +241,12 @@ findFile() {
[ -z "$size" ] || [[ "$size" == "0" ]] && return 0 [ -z "$size" ] || [[ "$size" == "0" ]] && return 0
ISO="$file" ISO="$file"
CUSTOM="$file" CUSTOM="$ISO"
BOOT="$STORAGE/windows.$size.iso" BOOT="$STORAGE/windows.$size.iso"
return 0 return 0
} }
detectCustom() {
CUSTOM=""
! findFile "custom.iso" && return 1
[ -n "$CUSTOM" ] && return 0
! findFile "boot.iso" && return 1
[ -n "$CUSTOM" ] && return 0
return 0
}
extractESD() { extractESD() {
local iso="$1" local iso="$1"
@ -362,7 +336,7 @@ extractImage() {
local dir="$2" local dir="$2"
local version="$3" local version="$3"
local desc="local ISO" local desc="local ISO"
local file size size_gb space space_gb local size size_gb space space_gb
if [ -z "$CUSTOM" ]; then if [ -z "$CUSTOM" ]; then
desc="downloaded ISO" desc="downloaded ISO"
@ -401,27 +375,8 @@ extractImage() {
error "Failed to extract ISO file: $iso" && return 1 error "Failed to extract ISO file: $iso" && return 1
fi fi
if [[ "${UNPACK:-}" != [Yy1]* ]]; then
LABEL=$(isoinfo -d -i "$iso" | sed -n 's/Volume id: //p') LABEL=$(isoinfo -d -i "$iso" | sed -n 's/Volume id: //p')
else
file=$(find "$dir" -maxdepth 1 -type f -iname "*.iso" -print -quit)
if [ -z "$file" ]; then
error "Failed to find any .iso file in archive!" && return 1
fi
if ! 7z x "$file" -o"$dir" > /dev/null; then
error "Failed to extract archive!" && return 1
fi
LABEL=$(isoinfo -d -i "$file" | sed -n 's/Volume id: //p')
rm -f "$file"
fi
return 0 return 0
} }
@ -602,14 +557,14 @@ detectImage() {
fi fi
local src wim info local src wim info
src=$(find "$dir" -maxdepth 1 -type d -iname sources -print -quit) src=$(find "$dir" -maxdepth 1 -type d -iname sources | head -n 1)
if [ ! -d "$src" ]; then if [ ! -d "$src" ]; then
warn "failed to locate 'sources' folder in ISO image, $FB" && return 1 warn "failed to locate 'sources' folder in ISO image, $FB" && return 1
fi fi
wim=$(find "$src" -maxdepth 1 -type f -iname install.wim -print -quit) wim=$(find "$src" -maxdepth 1 -type f -iname install.wim | head -n 1)
[ ! -f "$wim" ] && wim=$(find "$src" -maxdepth 1 -type f -iname install.esd -print -quit) [ ! -f "$wim" ] && wim=$(find "$src" -maxdepth 1 -type f -iname install.esd | head -n 1)
if [ ! -f "$wim" ]; then if [ ! -f "$wim" ]; then
warn "failed to locate 'install.wim' or 'install.esd' in ISO image, $FB" && return 1 warn "failed to locate 'install.wim' or 'install.esd' in ISO image, $FB" && return 1
@ -734,17 +689,16 @@ updateXML() {
sed -i "s/<Username>Docker<\/Username>/<Username>$user<\/Username>/g" "$asset" sed -i "s/<Username>Docker<\/Username>/<Username>$user<\/Username>/g" "$asset"
fi fi
[ -n "$PASSWORD" ] && pass="$PASSWORD" || pass="admin" if [ -n "$PASSWORD" ]; then
pass=$(printf '%s' "${PASSWORD}Password" | iconv -f utf-8 -t utf-16le | base64 -w 0)
pw=$(printf '%s' "${pass}Password" | iconv -f utf-8 -t utf-16le | base64 -w 0) admin=$(printf '%s' "${PASSWORD}AdministratorPassword" | iconv -f utf-8 -t utf-16le | base64 -w 0)
admin=$(printf '%s' "${pass}AdministratorPassword" | iconv -f utf-8 -t utf-16le | base64 -w 0)
sed -i "s/<Value>password<\/Value>/<Value>$admin<\/Value>/g" "$asset" sed -i "s/<Value>password<\/Value>/<Value>$admin<\/Value>/g" "$asset"
sed -i "s/<PlainText>true<\/PlainText>/<PlainText>false<\/PlainText>/g" "$asset" sed -i "s/<PlainText>true<\/PlainText>/<PlainText>false<\/PlainText>/g" "$asset"
sed -z "s/<Password>...........<Value \/>/<Password>\n <Value>$pw<\/Value>/g" -i "$asset" sed -z "s/<Password>...........<Value \/>/<Password>\n <Value>$pass<\/Value>/g" -i "$asset"
sed -z "s/<Password>...............<Value \/>/<Password>\n <Value>$pw<\/Value>/g" -i "$asset" sed -z "s/<Password>...............<Value \/>/<Password>\n <Value>$pass<\/Value>/g" -i "$asset"
sed -z "s/<AdministratorPassword>...........<Value \/>/<AdministratorPassword>\n <Value>$admin<\/Value>/g" -i "$asset" sed -z "s/<AdministratorPassword>...........<Value \/>/<AdministratorPassword>\n <Value>$admin<\/Value>/g" -i "$asset"
sed -z "s/<AdministratorPassword>...............<Value \/>/<AdministratorPassword>\n <Value>$admin<\/Value>/g" -i "$asset" sed -z "s/<AdministratorPassword>...............<Value \/>/<AdministratorPassword>\n <Value>$admin<\/Value>/g" -i "$asset"
fi
if [ -n "$EDITION" ]; then if [ -n "$EDITION" ]; then
[[ "${EDITION^^}" == "CORE" ]] && EDITION="STANDARDCORE" [[ "${EDITION^^}" == "CORE" ]] && EDITION="STANDARDCORE"
@ -834,7 +788,7 @@ addDrivers() {
warn "Windows version unknown, falling back to Windows 11 drivers..." warn "Windows version unknown, falling back to Windows 11 drivers..."
fi fi
if ! bsdtar -xf /var/drivers.txz -C "$drivers"; then if ! bsdtar -xf /drivers.txz -C "$drivers"; then
error "Failed to extract drivers from archive!" && return 1 error "Failed to extract drivers from archive!" && return 1
fi fi
@ -847,7 +801,7 @@ addDrivers() {
addDriver "$version" "$drivers" "$target" "qxl" || return 1 addDriver "$version" "$drivers" "$target" "qxl" || return 1
addDriver "$version" "$drivers" "$target" "viofs" || return 1 addDriver "$version" "$drivers" "$target" "viofs" || return 1
addDriver "$version" "$drivers" "$target" "sriov" || return 1 addDriver "$version" "$drivers" "$target" "sriov" || return 1
addDriver "$version" "$drivers" "$target" "smbus" || return 1 # Disable temporarily : addDriver "$version" "$drivers" "$target" "smbus" || return 1
addDriver "$version" "$drivers" "$target" "qxldod" || return 1 addDriver "$version" "$drivers" "$target" "qxldod" || return 1
addDriver "$version" "$drivers" "$target" "viorng" || return 1 addDriver "$version" "$drivers" "$target" "viorng" || return 1
addDriver "$version" "$drivers" "$target" "viostor" || return 1 addDriver "$version" "$drivers" "$target" "viostor" || return 1
@ -855,7 +809,7 @@ addDrivers() {
addDriver "$version" "$drivers" "$target" "NetKVM" || return 1 addDriver "$version" "$drivers" "$target" "NetKVM" || return 1
addDriver "$version" "$drivers" "$target" "Balloon" || return 1 addDriver "$version" "$drivers" "$target" "Balloon" || return 1
addDriver "$version" "$drivers" "$target" "vioscsi" || return 1 addDriver "$version" "$drivers" "$target" "vioscsi" || return 1
addDriver "$version" "$drivers" "$target" "pvpanic" || return 1 # Disable temporarily : addDriver "$version" "$drivers" "$target" "pvpanic" || return 1
addDriver "$version" "$drivers" "$target" "vioinput" || return 1 addDriver "$version" "$drivers" "$target" "vioinput" || return 1
addDriver "$version" "$drivers" "$target" "viogpudo" || return 1 addDriver "$version" "$drivers" "$target" "viogpudo" || return 1
addDriver "$version" "$drivers" "$target" "vioserial" || return 1 addDriver "$version" "$drivers" "$target" "vioserial" || return 1
@ -903,14 +857,14 @@ updateImage() {
rm -rf "$tmp" rm -rf "$tmp"
mkdir -p "$tmp" mkdir -p "$tmp"
src=$(find "$dir" -maxdepth 1 -type d -iname sources -print -quit) src=$(find "$dir" -maxdepth 1 -type d -iname sources | head -n 1)
if [ ! -d "$src" ]; then if [ ! -d "$src" ]; then
error "failed to locate 'sources' folder in ISO image, $FB" && return 1 error "failed to locate 'sources' folder in ISO image, $FB" && return 1
fi fi
wim=$(find "$src" -maxdepth 1 -type f -iname boot.wim -print -quit) wim=$(find "$src" -maxdepth 1 -type f -iname boot.wim | head -n 1)
[ ! -f "$wim" ] && wim=$(find "$src" -maxdepth 1 -type f -iname boot.esd -print -quit) [ ! -f "$wim" ] && wim=$(find "$src" -maxdepth 1 -type f -iname boot.esd | head -n 1)
if [ ! -f "$wim" ]; then if [ ! -f "$wim" ]; then
error "failed to locate 'boot.wim' or 'boot.esd' in ISO image, $FB" && return 1 error "failed to locate 'boot.wim' or 'boot.esd' in ISO image, $FB" && return 1
@ -973,7 +927,7 @@ updateImage() {
local find="$file" local find="$file"
[[ "$MANUAL" == [Yy1]* ]] && find="$org" [[ "$MANUAL" == [Yy1]* ]] && find="$org"
path=$(find "$dir" -maxdepth 1 -type f -iname "$find" -print -quit) path=$(find "$dir" -maxdepth 1 -type f -iname "$find" | head -n 1)
if [ -f "$path" ]; then if [ -f "$path" ]; then
if [[ "$MANUAL" != [Yy1]* ]]; then if [[ "$MANUAL" != [Yy1]* ]]; then
@ -1080,27 +1034,6 @@ bootWindows() {
ARGUMENTS="$ARGS ${ARGUMENTS:-}" ARGUMENTS="$ARGS ${ARGUMENTS:-}"
fi fi
if [ -s "$STORAGE/windows.vga" ] && [ -f "$STORAGE/windows.vga" ]; then
if [ -z "${VGA:-}" ]; then
VGA=$(<"$STORAGE/windows.vga")
VGA="${VGA//[![:print:]]/}"
fi
fi
if [ -s "$STORAGE/windows.usb" ] && [ -f "$STORAGE/windows.usb" ]; then
if [ -z "${USB:-}" ]; then
USB=$(<"$STORAGE/windows.usb")
USB="${USB//[![:print:]]/}"
fi
fi
if [ -s "$STORAGE/windows.net" ] && [ -f "$STORAGE/windows.net" ]; then
if [ -z "${ADAPTER:-}" ]; then
ADAPTER=$(<"$STORAGE/windows.net")
ADAPTER="${ADAPTER//[![:print:]]/}"
fi
fi
if [ -s "$STORAGE/windows.type" ] && [ -f "$STORAGE/windows.type" ]; then if [ -s "$STORAGE/windows.type" ] && [ -f "$STORAGE/windows.type" ]; then
if [ -z "${DISK_TYPE:-}" ]; then if [ -z "${DISK_TYPE:-}" ]; then
DISK_TYPE=$(<"$STORAGE/windows.type") DISK_TYPE=$(<"$STORAGE/windows.type")

View file

@ -472,18 +472,6 @@ getESD() {
return 0 return 0
} }
isCompressed() {
local file="$1"
case "${file,,}" in
*".7z" | *".zip" | *".rar" | *".lzma" | *".bz" | *".bz2" )
return 0 ;;
esac
return 1
}
verifyFile() { verifyFile() {
local iso="$1" local iso="$1"
@ -529,11 +517,9 @@ downloadFile() {
local size="$4" local size="$4"
local lang="$5" local lang="$5"
local desc="$6" local desc="$6"
local msg="Downloading $desc" local rc total total_gb progress domain dots space folder
local rc total total_gb progress domain dots agent space folder
rm -f "$iso" rm -f "$iso"
agent=$(get_agent)
if [ -n "$size" ] && [[ "$size" != "0" ]]; then if [ -n "$size" ] && [[ "$size" != "0" ]]; then
folder=$(dirname -- "$iso") folder=$(dirname -- "$iso")
@ -549,8 +535,8 @@ downloadFile() {
progress="--progress=dot:giga" progress="--progress=dot:giga"
fi fi
local msg="Downloading $desc"
html "$msg..." html "$msg..."
/run/progress.sh "$iso" "$size" "$msg ([P])..." &
domain=$(echo "$url" | awk -F/ '{print $3}') domain=$(echo "$url" | awk -F/ '{print $3}')
dots=$(echo "$domain" | tr -cd '.' | wc -c) dots=$(echo "$domain" | tr -cd '.' | wc -c)
@ -561,8 +547,9 @@ downloadFile() {
fi fi
info "$msg..." info "$msg..."
/run/progress.sh "$iso" "$size" "$msg ([P])..." &
{ wget "$url" -O "$iso" -q --timeout=30 --no-http-keep-alive --user-agent "$agent" --show-progress "$progress"; rc=$?; } || : { wget "$url" -O "$iso" -q --timeout=30 --no-http-keep-alive --show-progress "$progress"; rc=$?; } || :
fKill "progress.sh" fKill "progress.sh"
@ -570,17 +557,16 @@ downloadFile() {
total=$(stat -c%s "$iso") total=$(stat -c%s "$iso")
total_gb=$(formatBytes "$total") total_gb=$(formatBytes "$total")
if [ "$total" -lt 100000000 ]; then if [ "$total" -lt 100000000 ]; then
error "Invalid download link: $url (is only $total_gb ?). Please report this at $SUPPORT/issues" && return 1 error "Invalid download link: $url (is only $total_gb ?). Please report this at $SUPPORT/issues." && return 1
fi fi
verifyFile "$iso" "$size" "$total" "$sum" || return 1 verifyFile "$iso" "$size" "$total" "$sum" || return 1
isCompressed "$url" && UNPACK="Y"
html "Download finished successfully..." && return 0 html "Download finished successfully..." && return 0
fi fi
msg="Failed to download $url" msg="Failed to download $url"
(( rc == 3 )) && error "$msg , cannot write file (disk full?)" && return 1 (( rc == 3 )) && error "$msg , cannot write file (disk full?)" && return 1
(( rc == 4 )) && error "$msg , network failure!" && return 1 (( rc == 4 )) && error "$msg , network failure!" && return 1
(( rc == 8 )) && error "$msg , server issued an error response! Please report this at $SUPPORT/issues" && return 1 (( rc == 8 )) && error "$msg , server issued an error response! Please report this at $SUPPORT/issues." && return 1
error "$msg , reason: $rc" error "$msg , reason: $rc"
return 1 return 1
@ -598,14 +584,12 @@ downloadImage() {
local msg="Will retry after $delay seconds..." local msg="Will retry after $delay seconds..."
if [[ "${version,,}" == "http"* ]]; then if [[ "${version,,}" == "http"* ]]; then
base=$(basename "$iso") base=$(basename "$iso")
desc=$(fromFile "$base") desc=$(fromFile "$base")
downloadFile "$iso" "$version" "" "" "" "$desc" && return 0 downloadFile "$iso" "$version" "" "" "" "$desc" && return 0
info "$msg" && html "$msg" && sleep "$delay" info "$msg" && html "$msg" && sleep "$delay"
downloadFile "$iso" "$version" "" "" "" "$desc" && return 0 downloadFile "$iso" "$version" "" "" "" "$desc" && return 0
rm -f "$iso" rm -f "$iso"
return 1 return 1
fi fi

View file

@ -24,11 +24,10 @@ addShare() {
local comment="$3" local comment="$3"
mkdir -p "$dir" || return 1 mkdir -p "$dir" || return 1
ls -A "$dir" >/dev/null 2>&1 || return 1
if [ -z "$(ls -A "$dir")" ]; then if [ -z "$(ls -A "$dir")" ]; then
chmod 777 "$dir" || return 1 chmod 777 "$dir"
{ echo "--------------------------------------------------------" { echo "--------------------------------------------------------"
echo " $APP for Docker v$(</run/version)..." echo " $APP for Docker v$(</run/version)..."
@ -92,17 +91,10 @@ share="/data"
[ ! -d "$share" ] && [ -d "/shared" ] && share="/shared" [ ! -d "$share" ] && [ -d "/shared" ] && share="/shared"
[ ! -d "$share" ] && [ -d "$STORAGE/shared" ] && share="$STORAGE/shared" [ ! -d "$share" ] && [ -d "$STORAGE/shared" ] && share="$STORAGE/shared"
if ! addShare "$share" "Data" "Shared"; then addShare "$share" "Data" "Shared" || error "Failed to create shared folder!"
error "Failed to add shared folder '$share'. Please check its permissions." && return 0
fi
if [ -d "/data2" ]; then [ -d "/data2" ] && addShare "/data2" "Data2" "Shared"
addShare "/data2" "Data2" "Shared" || error "Failed to add shared folder '/data2'. Please check its permissions." [ -d "/data3" ] && addShare "/data3" "Data3" "Shared"
fi
if [ -d "/data3" ]; then
addShare "/data3" "Data3" "Shared" || error "Failed to add shared folder '/data3'. Please check its permissions."
fi
IFS=',' read -r -a dirs <<< "${SHARES:-}" IFS=',' read -r -a dirs <<< "${SHARES:-}"
for dir in "${dirs[@]}"; do for dir in "${dirs[@]}"; do
@ -121,7 +113,16 @@ if ! smbd; then
smbd -i --debug-stdout || true smbd -i --debug-stdout || true
fi fi
wsdd -i "$interface" -p -n "$hostname" & if [[ "${BOOT_MODE:-}" == "windows_legacy" ]]; then
echo "$!" > /var/run/wsdd.pid # Enable NetBIOS on Windows 7 and lower
if ! nmbd; then
error "NetBIOS daemon failed to start!"
nmbd -i --debug-stdout || true
fi
else
# Enable Web Service Discovery on Vista and up
wsdd -i "$interface" -p -n "$hostname" &
echo "$!" > /var/run/wsdd.pid
fi
return 0 return 0