From e3cf3ccf3d07ef3dfe90641010b942f2b0b7f95b Mon Sep 17 00:00:00 2001 From: Kroese Date: Mon, 20 Oct 2025 12:29:03 +0200 Subject: [PATCH 01/10] docs: Update docker run command (#1519) --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 4256727..adbb6bf 100644 --- a/readme.md +++ b/readme.md @@ -53,7 +53,7 @@ services: ##### Via Docker CLI: ```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 -e "VERSION=11" -p 8006:8006 --device=/dev/kvm --device=/dev/net/tun --cap-add NET_ADMIN -v "${PWD:-.}/windows:/storage" --stop-timeout 120 docker.io/dockurr/windows ``` ##### Via Kubernetes: From 8790b4ec7c1baa03de11336c5716efce2f88eb0e Mon Sep 17 00:00:00 2001 From: Kroese Date: Mon, 20 Oct 2025 13:59:27 +0200 Subject: [PATCH 02/10] fix: Remove SeaBIOS control characters (#1520) --- src/entry.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/entry.sh b/src/entry.sh index 2929503..71e939e 100644 --- a/src/entry.sh +++ b/src/entry.sh @@ -39,6 +39,8 @@ terminal tail -fn +0 "$QEMU_LOG" --pid=$$ 2>/dev/null & cat "$QEMU_TERM" 2> /dev/null | tee "$QEMU_PTY" | \ sed -u -e 's/\x1B\[[=0-9;]*[a-z]//gi' \ +-e 's/\x1B\x63//g' -e 's/\x1B\[[=?]7l//g' \ +-e '/^$/d' -e 's/\x44\x53\x73//g' \ -e 's/failed to load Boot/skipped Boot/g' \ -e 's/0): Not Found/0)/g' & wait $! || : From fa606aec5379b97ee9187ef23b27f1c11f006fc9 Mon Sep 17 00:00:00 2001 From: Kroese Date: Mon, 20 Oct 2025 14:48:46 +0200 Subject: [PATCH 03/10] build: Update wsddn package to v1.22 (#1521) --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 7fef6a8..6dd3afd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,7 +19,7 @@ RUN set -eu && \ cabextract \ libxml2-utils \ libarchive-tools && \ - wget "https://github.com/gershnik/wsdd-native/releases/download/v1.21/wsddn_1.21_${TARGETARCH}.deb" -O /tmp/wsddn.deb -q && \ + wget "https://github.com/gershnik/wsdd-native/releases/download/v1.22/wsddn_1.22_${TARGETARCH}.deb" -O /tmp/wsddn.deb -q && \ dpkg -i /tmp/wsddn.deb && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* From 9236127a865707de886c878aeb7f13fa204f21cb Mon Sep 17 00:00:00 2001 From: Kroese Date: Mon, 20 Oct 2025 14:50:37 +0200 Subject: [PATCH 04/10] fix: Add SELinux warning for shared folder (#1522) --- src/samba.sh | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/samba.sh b/src/samba.sh index d70cb1a..45228f9 100644 --- a/src/samba.sh +++ b/src/samba.sh @@ -46,10 +46,14 @@ addShare() { local cfg="$5" local owner="" - mkdir -p "$dir" || return 1 + if ! mkdir -p "$dir"; then + error "Failed to create directory $dir." && return 1 + fi if ! ls -A "$dir" >/dev/null 2>&1; then - error "Failed to access directory $dir" && return 1 + msg="Failed to access directory $dir." + msg+=" If SELinux is active, you need to add the \":Z\" flag to the bind mount." + error "$msg" && return 1 fi if [ -z "$(ls -A "$dir")" ]; then @@ -136,26 +140,21 @@ share="/shared" [ ! -d "$share" ] && [ -d "$STORAGE/data" ] && share="$STORAGE/data" [ ! -d "$share" ] && share="$tmp" -m1="Failed to add shared folder" -m2="Please check its permissions." - -if ! addShare "$share" "/shared" "Data" "Shared" "$SAMBA_CONFIG"; then - error "$m1 '$share'. $m2" && return 0 -fi +! addShare "$share" "/shared" "Data" "Shared" "$SAMBA_CONFIG" && return 0 if [ -d "/shared2" ]; then - addShare "/shared2" "/shared2" "Data2" "Shared" "$SAMBA_CONFIG" || error "$m1 '/shared2'. $m2" + addShare "/shared2" "/shared2" "Data2" "Shared" "$SAMBA_CONFIG" || : else if [ -d "/data2" ]; then - addShare "/data2" "/shared2" "Data2" "Shared" "$SAMBA_CONFIG" || error "$m1 '/data2'. $m2." + addShare "/data2" "/shared2" "Data2" "Shared" "$SAMBA_CONFIG" || : fi fi if [ -d "/shared3" ]; then - addShare "/shared3" "/shared3" "Data3" "Shared" "$SAMBA_CONFIG" || error "$m1 '/shared3'. $m2" + addShare "/shared3" "/shared3" "Data3" "Shared" "$SAMBA_CONFIG" || : else if [ -d "/data3" ]; then - addShare "/data3" "/shared3" "Data3" "Shared" "$SAMBA_CONFIG" || error "$m1 '/data3'. $m2" + addShare "/data3" "/shared3" "Data3" "Shared" "$SAMBA_CONFIG" || : fi fi From a0bcd719bed4b71228213a00d7b8690e3b44bbd4 Mon Sep 17 00:00:00 2001 From: Kroese Date: Tue, 21 Oct 2025 22:46:06 +0200 Subject: [PATCH 05/10] build: Add review workflow for shell formatting (#1527) --- .github/workflows/review.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .github/workflows/review.yml diff --git a/.github/workflows/review.yml b/.github/workflows/review.yml new file mode 100644 index 0000000..e18ca8c --- /dev/null +++ b/.github/workflows/review.yml @@ -0,0 +1,19 @@ +on: + pull_request: + +name: "Review" + +jobs: + review: + name: review + runs-on: ubuntu-latest + steps: + - + name: Checkout + uses: actions/checkout@v5 + - + name: Review + uses: reviewdog/action-shfmt@v1 + with: + shfmt_flags: "-i 2 -ci -bn" + github_token: ${{ secrets.REPO_ACCESS_TOKEN }} From f661df3abc0b6bebe97f03919336f1763109308a Mon Sep 17 00:00:00 2001 From: Kroese Date: Tue, 21 Oct 2025 23:19:54 +0200 Subject: [PATCH 06/10] build: Update QEMU base image to v7.27 (#1528) --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 6dd3afd..bf6dab2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,7 @@ ARG VERSION_ARG="latest" FROM scratch AS build-amd64 -COPY --from=qemux/qemu:7.26 / / +COPY --from=qemux/qemu:7.27 / / ARG TARGETARCH ARG DEBCONF_NOWARNINGS="yes" From c1c44c4da760d8e9c686db90c6841f9da7b3c4fd Mon Sep 17 00:00:00 2001 From: Kroese Date: Wed, 22 Oct 2025 01:23:25 +0200 Subject: [PATCH 07/10] build: Add code quality checks (#1529) --- .github/workflows/review.yml | 49 +++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/.github/workflows/review.yml b/.github/workflows/review.yml index e18ca8c..51f8503 100644 --- a/.github/workflows/review.yml +++ b/.github/workflows/review.yml @@ -3,6 +3,11 @@ on: name: "Review" +permissions: + contents: read + pull-requests: write + checks: write + jobs: review: name: review @@ -12,8 +17,50 @@ jobs: name: Checkout uses: actions/checkout@v5 - - name: Review + name: Spelling + uses: reviewdog/action-misspell@v1 + with: + locale: "US" + level: warning + pattern: | + *.md + *.sh + reporter: github-pr-review + github_token: ${{ secrets.REPO_ACCESS_TOKEN }} + - + name: Hadolint + uses: reviewdog/action-hadolint@v1 + with: + level: warning + reporter: github-pr-review + hadolint_ignore: DL3006 DL3008 + github_token: ${{ secrets.REPO_ACCESS_TOKEN }} + - + name: YamlLint + uses: reviewdog/action-yamllint@v1 + with: + level: warning + reporter: github-pr-review + github_token: ${{ secrets.REPO_ACCESS_TOKEN }} + - + name: ActionLint + uses: reviewdog/action-actionlint@v1 + with: + level: warning + reporter: github-pr-review + github_token: ${{ secrets.REPO_ACCESS_TOKEN }} + - + name: Shellformat uses: reviewdog/action-shfmt@v1 with: + level: warning shfmt_flags: "-i 2 -ci -bn" github_token: ${{ secrets.REPO_ACCESS_TOKEN }} + - + name: Shellcheck + uses: reviewdog/action-shellcheck@v1 + with: + level: warning + reporter: github-pr-review + shellcheck_flags: -x -e SC1091 -e SC2001 -e SC2002 -e SC2034 -e SC2064 -e SC2153 -e SC2317 -e SC2028 + github_token: ${{ secrets.REPO_ACCESS_TOKEN }} From 122d1ff98ed91a0813c8b31637289f7f5e89d05d Mon Sep 17 00:00:00 2001 From: Kroese Date: Wed, 22 Oct 2025 10:06:26 +0200 Subject: [PATCH 08/10] fix: Inherit owner from parent folder (#1526) --- src/install.sh | 84 ++++++++++++++++++++++++++++++++++++++++---------- src/mido.sh | 5 ++- src/power.sh | 4 ++- 3 files changed, 74 insertions(+), 19 deletions(-) diff --git a/src/install.sh b/src/install.sh index f9bd402..89d1795 100644 --- a/src/install.sh +++ b/src/install.sh @@ -22,7 +22,11 @@ backup () { fi - mkdir -p "$root" + if ! makeDir "$root"; then + error "Failed to create directory \"$root\" !" + return 1 + fi + local folder="$name" local dir="$root/$folder" @@ -34,7 +38,11 @@ backup () { done rm -rf "$dir" - mkdir -p "$dir" + + if ! makeDir "$dir"; then + error "Failed to create directory \"$dir\" !" + return 1 + fi [ -f "$iso" ] && mv -f "$iso" "$dir/" find "$STORAGE" -maxdepth 1 -type f -iname 'data.*' -not -iname '*.iso' -exec mv -n {} "$dir/" \; @@ -156,7 +164,9 @@ startInstall() { ! backup "" && error "Backup failed!" fi - mkdir -p "$TMP" + if ! makeDir "$TMP"; then + error "Failed to create directory \"$TMP\" !" + fi if [ -z "$CUSTOM" ]; then @@ -178,6 +188,20 @@ startInstall() { return 0 } +writeFile() { + + local txt="$1" + local path="$2" + + echo "$txt" >"$path" + + if ! setOwner "$path"; then + error "Failed to set the owner for \"$path\" !" + fi + + return 0 +} + finishInstall() { local iso="$1" @@ -188,6 +212,10 @@ finishInstall() { error "Failed to find ISO file: $iso" && return 1 fi + if [[ "$iso" == "$STORAGE/"* ]]; then + ! setOwner "$iso" && error "Failed to set the owner for \"$iso\" !" + fi + if [[ "$aborted" != [Yy1]* ]]; then # Mark ISO as prepared via magic byte byte="16" && [[ "$MANUAL" == [Yy1]* ]] && byte="17" @@ -196,56 +224,68 @@ finishInstall() { fi fi - cp -f /run/version "$STORAGE/windows.ver" + local file="$STORAGE/windows.ver" + cp -f /run/version "$file" + ! setOwner "$file" && error "Failed to set the owner for \"$file\" !" if [[ "$iso" == "$STORAGE/"* ]]; then if [[ "$aborted" != [Yy1]* ]] || [ -z "$CUSTOM" ]; then base=$(basename "$iso") - echo "$base" > "$STORAGE/windows.base" + file="$STORAGE/windows.base" + writeFile "$base" "$file" fi fi if [[ "${PLATFORM,,}" == "x64" ]]; then if [[ "${BOOT_MODE,,}" == "windows_legacy" ]]; then - echo "$BOOT_MODE" > "$STORAGE/windows.mode" + file="$STORAGE/windows.mode" + writeFile "$BOOT_MODE" "$file" if [[ "${MACHINE,,}" != "q35" ]]; then - echo "$MACHINE" > "$STORAGE/windows.old" + file="$STORAGE/windows.old" + writeFile "$MACHINE" "$file" fi else # Enable secure boot + TPM on manual installs as Win11 requires if [[ "$MANUAL" == [Yy1]* || "$aborted" == [Yy1]* ]]; then if [[ "${DETECTED,,}" == "win11"* ]]; then BOOT_MODE="windows_secure" - echo "$BOOT_MODE" > "$STORAGE/windows.mode" + file="$STORAGE/windows.mode" + writeFile "$BOOT_MODE" "$file" fi fi # Enable secure boot on multi-socket systems to workaround freeze if [ -n "$SOCKETS" ] && [[ "$SOCKETS" != "1" ]]; then BOOT_MODE="windows_secure" - echo "$BOOT_MODE" > "$STORAGE/windows.mode" + file="$STORAGE/windows.mode" + writeFile "$BOOT_MODE" "$file" fi fi fi if [ -n "${ARGS:-}" ]; then ARGUMENTS="$ARGS ${ARGUMENTS:-}" - echo "$ARGS" > "$STORAGE/windows.args" + file="$STORAGE/windows.args" + writeFile "$ARGS" "$file" fi if [ -n "${VGA:-}" ] && [[ "${VGA:-}" != "virtio"* ]]; then - echo "$VGA" > "$STORAGE/windows.vga" + file="$STORAGE/windows.vga" + writeFile "$VGA" "$file" fi if [ -n "${USB:-}" ] && [[ "${USB:-}" != "qemu-xhci"* ]]; then - echo "$USB" > "$STORAGE/windows.usb" + file="$STORAGE/windows.usb" + writeFile "$USB" "$file" fi if [ -n "${DISK_TYPE:-}" ] && [[ "${DISK_TYPE:-}" != "scsi" ]]; then - echo "$DISK_TYPE" > "$STORAGE/windows.type" + file="$STORAGE/windows.type" + writeFile "$DISK_TYPE" "$file" fi if [ -n "${ADAPTER:-}" ] && [[ "${ADAPTER:-}" != "virtio-net-pci" ]]; then - echo "$ADAPTER" > "$STORAGE/windows.net" + file="$STORAGE/windows.net" + writeFile "$ADAPTER" "$file" fi rm -rf "$TMP" @@ -351,7 +391,10 @@ extractESD() { fi rm -rf "$dir" - mkdir -p "$dir" + + if ! makeDir "$dir"; then + error "Failed to create directory \"$dir\" !" && return 1 + fi size=9606127360 size_gb=$(formatBytes "$size") @@ -407,6 +450,8 @@ extractESD() { error "Adding WinPE failed ($retVal)" && return 1 } + fKill "progress.sh" + local msg="Extracting $desc setup" info "$msg..." @@ -486,14 +531,17 @@ extractImage() { info "$msg..." && html "$msg..." rm -rf "$dir" - mkdir -p "$dir" + + if ! makeDir "$dir"; then + error "Failed to create directory \"$dir\" !" && return 1 + fi size=$(stat -c%s "$iso") size_gb=$(formatBytes "$size") space=$(df --output=avail -B 1 "$dir" | tail -n 1) space_gb=$(formatBytes "$space") - if ((size<100000000)); then + if (( size < 100000000 )); then error "Invalid ISO file: Size is smaller than 100 MB" && return 1 fi @@ -1177,6 +1225,8 @@ buildImage() { [[ "$error" != "$hide" ]] && echo "$error" mv -f "$out" "$BOOT" || return 1 + ! setOwner "$BOOT" && error "Failed to set the owner for \"$BOOT\" !" + return 0 } diff --git a/src/mido.sh b/src/mido.sh index cc5b251..369fc17 100644 --- a/src/mido.sh +++ b/src/mido.sh @@ -487,8 +487,11 @@ getESD() { info "$msg" && html "$msg" rm -rf "$dir" - mkdir -p "$dir" + if ! makeDir "$dir"; then + error "Failed to create directory \"$dir\" !" && return 1 + fi + local xFile="products.xml" local eFile="esd_edition.xml" local fFile="products_filter.xml" diff --git a/src/power.sh b/src/power.sh index 8acb57b..98a6f73 100644 --- a/src/power.sh +++ b/src/power.sh @@ -105,7 +105,9 @@ finish() { if [ ! -f "$STORAGE/windows.boot" ] && [ -f "$BOOT" ]; then # Remove CD-ROM ISO after install if ready; then - touch "$STORAGE/windows.boot" + local file="$STORAGE/windows.boot" + touch "$file" + ! setOwner "$file" && error "Failed to set the owner for \"$file\" !" if [[ "$REMOVE" != [Nn]* ]]; then rm -f "$BOOT" 2>/dev/null || true fi From 544501107af0d4c4ede89ffb2e108ccbfd5f8028 Mon Sep 17 00:00:00 2001 From: Kroese Date: Wed, 22 Oct 2025 12:19:39 +0200 Subject: [PATCH 09/10] feat: Check if shared folder is writeable (#1531) --- src/samba.sh | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/samba.sh b/src/samba.sh index 45228f9..7cd3210 100644 --- a/src/samba.sh +++ b/src/samba.sh @@ -46,16 +46,23 @@ addShare() { local cfg="$5" local owner="" - if ! mkdir -p "$dir"; then - error "Failed to create directory $dir." && return 1 + if [ ! -d "$dir" ]; then + if ! mkdir -p "$dir"; then + error "Failed to create shared folder ($dir)." && return 1 + fi fi if ! ls -A "$dir" >/dev/null 2>&1; then - msg="Failed to access directory $dir." + msg="No permission to access shared folder ($dir)." msg+=" If SELinux is active, you need to add the \":Z\" flag to the bind mount." error "$msg" && return 1 fi + if [ ! -w "$dir" ]; then + msg="shared folder ($dir) is not writeable!" + warn "$msg" + fi + if [ -z "$(ls -A "$dir")" ]; then if ! chmod 2777 "$dir"; then error "Failed to set permissions for directory $dir" && return 1 From 11a19f6a9d88857be72ccf0fa6215daeef5c4f4f Mon Sep 17 00:00:00 2001 From: Kroese Date: Fri, 24 Oct 2025 04:33:47 +0200 Subject: [PATCH 10/10] fix: Remove unnecessary operation (#1534) --- src/install.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/src/install.sh b/src/install.sh index 89d1795..7be2996 100644 --- a/src/install.sh +++ b/src/install.sh @@ -135,7 +135,6 @@ startInstall() { if [[ "${VERSION,,}" == "http"* ]]; then file=$(basename "${VERSION%%\?*}") - file="${file//+/ }" printf -v file '%b' "${file//%/\\x}" file="${file//[!A-Za-z0-9._-]/_}"