From 6a0b6a1511501afb32aaedbacfc9790fa8d4a9c4 Mon Sep 17 00:00:00 2001 From: Michel Abboud Date: Thu, 29 Jan 2026 07:24:03 +0000 Subject: [PATCH] feat: Add ARM64 architecture auto-detection and image selection Auto-detect machine architecture via uname and use the correct Docker image (dockurr/windows for x86, dockurr/windows-arm for ARM64). Block unsupported versions on ARM with a clear error message, and show [x86 only] tags in the list command. Compose files now use a configurable WINDOWS_IMAGE variable with a default fallback. Co-Authored-By: Claude Opus 4.5 --- .env.example | 1 + .env.legacy | 3 ++ .env.modern | 3 ++ WINCTL_GUIDE.md | 22 ++++++++++++++ compose/desktop/win10.yml | 6 ++-- compose/desktop/win11.yml | 6 ++-- compose/desktop/win7.yml | 4 +-- compose/desktop/win8.yml | 4 +-- compose/legacy/vista.yml | 2 +- compose/legacy/win2k.yml | 2 +- compose/legacy/winxp.yml | 2 +- compose/server/win2003.yml | 2 +- compose/server/win2008.yml | 2 +- compose/server/win2012.yml | 2 +- compose/server/win2016.yml | 2 +- compose/server/win2019.yml | 2 +- compose/server/win2022.yml | 2 +- compose/server/win2025.yml | 2 +- compose/tiny/tiny10.yml | 2 +- compose/tiny/tiny11.yml | 2 +- readme.md | 2 +- winctl.sh | 59 +++++++++++++++++++++++++++++++++++++- 22 files changed, 110 insertions(+), 24 deletions(-) diff --git a/.env.example b/.env.example index c37b0cc..56bd37c 100644 --- a/.env.example +++ b/.env.example @@ -23,3 +23,4 @@ # SAMBA=Y # Enable file sharing (Y/N) # RESTART_POLICY=on-failure # Restart policy (no, on-failure, always, unless-stopped) # DEBUG=N # Debug mode (Y/N) +# WINDOWS_IMAGE=dockurr/windows # Docker image (dockurr/windows-arm for ARM64) diff --git a/.env.legacy b/.env.legacy index 31aea64..9f72db3 100644 --- a/.env.legacy +++ b/.env.legacy @@ -25,5 +25,8 @@ SAMBA=Y # Restart Policy (no, on-failure, always, unless-stopped) RESTART_POLICY=on-failure +# Docker Image (dockurr/windows for x86, dockurr/windows-arm for ARM64) +WINDOWS_IMAGE=dockurr/windows + # Debug DEBUG=N diff --git a/.env.modern b/.env.modern index 40819d0..ac5e811 100644 --- a/.env.modern +++ b/.env.modern @@ -25,5 +25,8 @@ SAMBA=Y # Restart Policy (no, on-failure, always, unless-stopped) RESTART_POLICY=on-failure +# Docker Image (dockurr/windows for x86, dockurr/windows-arm for ARM64) +WINDOWS_IMAGE=dockurr/windows + # Debug DEBUG=N diff --git a/WINCTL_GUIDE.md b/WINCTL_GUIDE.md index 94e89fe..e2835cb 100644 --- a/WINCTL_GUIDE.md +++ b/WINCTL_GUIDE.md @@ -35,6 +35,27 @@ A comprehensive guide to managing Windows Docker containers with `winctl.sh`. | **Server** | win2025, win2022, win2019, win2016, win2012, win2008, win2003 | | **Tiny** | tiny11, tiny10 | +### ARM64 Support + +The script auto-detects your CPU architecture. On ARM64 systems (e.g., Apple Silicon, Ampere), only the following versions are supported: + +| Version | Name | +|---------|------| +| win11 | Windows 11 Pro | +| win11e | Windows 11 Enterprise | +| win11l | Windows 11 LTSC | +| win10 | Windows 10 Pro | +| win10e | Windows 10 Enterprise | +| win10l | Windows 10 LTSC | + +To run on ARM64, set the Docker image in your `.env.modern` file: + +```bash +WINDOWS_IMAGE=dockurr/windows-arm +``` + +The `winctl.sh list` command shows `[x86 only]` tags on ARM64 for unsupported versions, and `winctl.sh start` blocks unsupported versions with a clear error message. + ### Port Mappings Each version has unique ports to avoid conflicts: @@ -435,6 +456,7 @@ DEBUG=N | `SAMBA` | Enable file sharing | Y | | `RESTART_POLICY` | Container restart policy | on-failure | | `DEBUG` | Debug mode | N | +| `WINDOWS_IMAGE` | Docker image | dockurr/windows | ### Restart Policy Options diff --git a/compose/desktop/win10.yml b/compose/desktop/win10.yml index 610210f..a88e417 100644 --- a/compose/desktop/win10.yml +++ b/compose/desktop/win10.yml @@ -1,6 +1,6 @@ services: win10: - image: dockurr/windows + image: ${WINDOWS_IMAGE:-dockurr/windows} container_name: win10 env_file: ../../.env.modern environment: @@ -20,7 +20,7 @@ services: stop_grace_period: 2m win10e: - image: dockurr/windows + image: ${WINDOWS_IMAGE:-dockurr/windows} container_name: win10e env_file: ../../.env.modern environment: @@ -40,7 +40,7 @@ services: stop_grace_period: 2m win10l: - image: dockurr/windows + image: ${WINDOWS_IMAGE:-dockurr/windows} container_name: win10l env_file: ../../.env.modern environment: diff --git a/compose/desktop/win11.yml b/compose/desktop/win11.yml index 065ad04..fa3eeaa 100644 --- a/compose/desktop/win11.yml +++ b/compose/desktop/win11.yml @@ -1,6 +1,6 @@ services: win11: - image: dockurr/windows + image: ${WINDOWS_IMAGE:-dockurr/windows} container_name: win11 env_file: ../../.env.modern environment: @@ -20,7 +20,7 @@ services: stop_grace_period: 2m win11e: - image: dockurr/windows + image: ${WINDOWS_IMAGE:-dockurr/windows} container_name: win11e env_file: ../../.env.modern environment: @@ -40,7 +40,7 @@ services: stop_grace_period: 2m win11l: - image: dockurr/windows + image: ${WINDOWS_IMAGE:-dockurr/windows} container_name: win11l env_file: ../../.env.modern environment: diff --git a/compose/desktop/win7.yml b/compose/desktop/win7.yml index 091e217..aa24640 100644 --- a/compose/desktop/win7.yml +++ b/compose/desktop/win7.yml @@ -1,6 +1,6 @@ services: win7: - image: dockurr/windows + image: ${WINDOWS_IMAGE:-dockurr/windows} container_name: win7 env_file: ../../.env.legacy environment: @@ -20,7 +20,7 @@ services: stop_grace_period: 2m win7e: - image: dockurr/windows + image: ${WINDOWS_IMAGE:-dockurr/windows} container_name: win7e env_file: ../../.env.legacy environment: diff --git a/compose/desktop/win8.yml b/compose/desktop/win8.yml index 8440c6b..f91b98d 100644 --- a/compose/desktop/win8.yml +++ b/compose/desktop/win8.yml @@ -1,6 +1,6 @@ services: win81: - image: dockurr/windows + image: ${WINDOWS_IMAGE:-dockurr/windows} container_name: win81 env_file: ../../.env.legacy environment: @@ -20,7 +20,7 @@ services: stop_grace_period: 2m win81e: - image: dockurr/windows + image: ${WINDOWS_IMAGE:-dockurr/windows} container_name: win81e env_file: ../../.env.legacy environment: diff --git a/compose/legacy/vista.yml b/compose/legacy/vista.yml index ba0ec05..8df7848 100644 --- a/compose/legacy/vista.yml +++ b/compose/legacy/vista.yml @@ -1,6 +1,6 @@ services: vista: - image: dockurr/windows + image: ${WINDOWS_IMAGE:-dockurr/windows} container_name: vista env_file: ../../.env.legacy environment: diff --git a/compose/legacy/win2k.yml b/compose/legacy/win2k.yml index 68db30e..2f09863 100644 --- a/compose/legacy/win2k.yml +++ b/compose/legacy/win2k.yml @@ -1,6 +1,6 @@ services: win2k: - image: dockurr/windows + image: ${WINDOWS_IMAGE:-dockurr/windows} container_name: win2k env_file: ../../.env.legacy environment: diff --git a/compose/legacy/winxp.yml b/compose/legacy/winxp.yml index 0280663..7942037 100644 --- a/compose/legacy/winxp.yml +++ b/compose/legacy/winxp.yml @@ -1,6 +1,6 @@ services: winxp: - image: dockurr/windows + image: ${WINDOWS_IMAGE:-dockurr/windows} container_name: winxp env_file: ../../.env.legacy environment: diff --git a/compose/server/win2003.yml b/compose/server/win2003.yml index 7ee1c41..7995784 100644 --- a/compose/server/win2003.yml +++ b/compose/server/win2003.yml @@ -1,6 +1,6 @@ services: win2003: - image: dockurr/windows + image: ${WINDOWS_IMAGE:-dockurr/windows} container_name: win2003 env_file: ../../.env.legacy environment: diff --git a/compose/server/win2008.yml b/compose/server/win2008.yml index 46a73ac..8aa46c1 100644 --- a/compose/server/win2008.yml +++ b/compose/server/win2008.yml @@ -1,6 +1,6 @@ services: win2008: - image: dockurr/windows + image: ${WINDOWS_IMAGE:-dockurr/windows} container_name: win2008 env_file: ../../.env.legacy environment: diff --git a/compose/server/win2012.yml b/compose/server/win2012.yml index 8a45438..95dbe9f 100644 --- a/compose/server/win2012.yml +++ b/compose/server/win2012.yml @@ -1,6 +1,6 @@ services: win2012: - image: dockurr/windows + image: ${WINDOWS_IMAGE:-dockurr/windows} container_name: win2012 env_file: ../../.env.legacy environment: diff --git a/compose/server/win2016.yml b/compose/server/win2016.yml index 823f947..e3792bc 100644 --- a/compose/server/win2016.yml +++ b/compose/server/win2016.yml @@ -1,6 +1,6 @@ services: win2016: - image: dockurr/windows + image: ${WINDOWS_IMAGE:-dockurr/windows} container_name: win2016 env_file: ../../.env.modern environment: diff --git a/compose/server/win2019.yml b/compose/server/win2019.yml index 4eb0439..846d3c8 100644 --- a/compose/server/win2019.yml +++ b/compose/server/win2019.yml @@ -1,6 +1,6 @@ services: win2019: - image: dockurr/windows + image: ${WINDOWS_IMAGE:-dockurr/windows} container_name: win2019 env_file: ../../.env.modern environment: diff --git a/compose/server/win2022.yml b/compose/server/win2022.yml index 51c7dbe..03448af 100644 --- a/compose/server/win2022.yml +++ b/compose/server/win2022.yml @@ -1,6 +1,6 @@ services: win2022: - image: dockurr/windows + image: ${WINDOWS_IMAGE:-dockurr/windows} container_name: win2022 env_file: ../../.env.modern environment: diff --git a/compose/server/win2025.yml b/compose/server/win2025.yml index 8ede87c..55c9f09 100644 --- a/compose/server/win2025.yml +++ b/compose/server/win2025.yml @@ -1,6 +1,6 @@ services: win2025: - image: dockurr/windows + image: ${WINDOWS_IMAGE:-dockurr/windows} container_name: win2025 env_file: ../../.env.modern environment: diff --git a/compose/tiny/tiny10.yml b/compose/tiny/tiny10.yml index a7f03e6..2d36783 100644 --- a/compose/tiny/tiny10.yml +++ b/compose/tiny/tiny10.yml @@ -1,6 +1,6 @@ services: tiny10: - image: dockurr/windows + image: ${WINDOWS_IMAGE:-dockurr/windows} container_name: tiny10 env_file: ../../.env.legacy environment: diff --git a/compose/tiny/tiny11.yml b/compose/tiny/tiny11.yml index 06cc891..094a6f7 100644 --- a/compose/tiny/tiny11.yml +++ b/compose/tiny/tiny11.yml @@ -1,6 +1,6 @@ services: tiny11: - image: dockurr/windows + image: ${WINDOWS_IMAGE:-dockurr/windows} container_name: tiny11 env_file: ../../.env.legacy environment: diff --git a/readme.md b/readme.md index 71aa872..641f1b1 100644 --- a/readme.md +++ b/readme.md @@ -224,7 +224,7 @@ data/ # VM storage (per-version folders) | `2003` | Windows Server 2003 | 0.6 GB | > [!TIP] -> To install ARM64 versions of Windows use [dockur/windows-arm](https://github.com/dockur/windows-arm/). +> To install ARM64 versions of Windows use [dockur/windows-arm](https://github.com/dockur/windows-arm/). The `winctl.sh` script auto-detects your architecture and blocks unsupported versions on ARM. Set `WINDOWS_IMAGE=dockurr/windows-arm` in your `.env.modern` file when running on ARM64. Only Windows 10 and 11 variants are supported on ARM64. ### How do I change the storage location? diff --git a/winctl.sh b/winctl.sh index a0f78eb..f157464 100755 --- a/winctl.sh +++ b/winctl.sh @@ -62,6 +62,11 @@ readonly ALL_VERSIONS=( tiny11 tiny10 ) +# Versions supported on ARM64 +readonly ARM_VERSIONS=( + win11 win11e win11l win10 win10e win10l +) + # Port mappings (web) declare -A VERSION_PORTS_WEB=( ["win11"]=8011 ["win11e"]=8012 ["win11l"]=8013 @@ -199,6 +204,36 @@ table_header() { printf '%s\n' " ${DIM}$(printf '─%.0s' {1..66})${RESET}" } +# ============================================================================== +# ARCHITECTURE DETECTION +# ============================================================================== + +DETECTED_ARCH="" + +detect_arch() { + if [[ -n "$DETECTED_ARCH" ]]; then + return + fi + local machine + machine=$(uname -m) + case "$machine" in + x86_64|amd64) DETECTED_ARCH="amd64" ;; + aarch64|arm64) DETECTED_ARCH="arm64" ;; + *) DETECTED_ARCH="amd64" ;; + esac +} + +is_arm_supported() { + local version="$1" + local v + for v in "${ARM_VERSIONS[@]}"; do + if [[ "$v" == "$version" ]]; then + return 0 + fi + done + return 1 +} + # ============================================================================== # PREREQUISITES CHECKS # ============================================================================== @@ -692,6 +727,16 @@ cmd_start() { validate_version "$v" || exit 1 done + # Check ARM compatibility + detect_arch + if [[ "$DETECTED_ARCH" == "arm64" ]]; then + for v in "${versions[@]}"; do + if ! is_arm_supported "$v"; then + die "${VERSION_DISPLAY_NAMES[$v]} ($v) is not supported on ARM64. Supported: ${ARM_VERSIONS[*]}" + fi + done + fi + # Run prerequisite checks check_docker || exit 1 check_kvm || exit 1 @@ -1027,6 +1072,7 @@ cmd_rebuild() { cmd_list() { local category="${1:-all}" + detect_arch header "Available Windows Versions" local categories=() @@ -1062,7 +1108,11 @@ cmd_list() { else resource_tag="${DIM}(2G RAM)${RESET}" fi - printf " %-10s %-28s %s %s\n" "$v" "${VERSION_DISPLAY_NAMES[$v]}" "$resource_tag" "$status" + local arch_tag="" + if [[ "$DETECTED_ARCH" == "arm64" ]] && ! is_arm_supported "$v"; then + arch_tag="${RED}[x86 only]${RESET}" + fi + printf " %-10s %-28s %s %s %s\n" "$v" "${VERSION_DISPLAY_NAMES[$v]}" "$resource_tag" "$arch_tag" "$status" fi done done @@ -1155,7 +1205,14 @@ cmd_monitor() { } cmd_check() { + detect_arch run_all_checks + printf '%s\n' " ${BOLD}Architecture:${RESET} ${DETECTED_ARCH}" + if [[ "$DETECTED_ARCH" == "arm64" ]]; then + printf '%s\n' " ${BOLD}ARM64 image:${RESET} dockurr/windows-arm" + printf '%s\n' " ${BOLD}Supported:${RESET} ${ARM_VERSIONS[*]}" + fi + printf '\n' } cmd_refresh() {