Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Improved installation #63

Merged
merged 15 commits into from
Jan 22, 2024
3 changes: 0 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,7 @@ RUN apt-get update \

COPY ./src /run/
COPY ./assets /run/assets

ADD https://github.com/qemus/virtiso/raw/master/virtio-win.iso /run/drivers.iso
ADD https://raw.githubusercontent.com/ElliotKillick/Mido/main/Mido.sh /run/mido.sh

RUN chmod +x /run/*.sh

EXPOSE 8006 3389
Expand Down
10 changes: 5 additions & 5 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ docker run -it --rm -p 8006:8006 --device=/dev/kvm --cap-add NET_ADMIN dockurr/w

- Start the container and get some coffee.

- Connect to port 8006 of the container in your web browser.
- Connect to [port 8006](http://localhost:8006) of the container in your web browser.

- Sit back and relax while the magic happens, the whole installation will be performed fully automatic.

Expand Down Expand Up @@ -127,7 +127,7 @@ docker run -it --rm -p 8006:8006 --device=/dev/kvm --cap-add NET_ADMIN dockurr/w

Then follow these steps:

- Start the container and connect to port 8006 of the container in your web browser. After the download is finished, you will see the Windows installation screen.
- 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'.

Expand All @@ -143,16 +143,16 @@ docker run -it --rm -p 8006:8006 --device=/dev/kvm --cap-add NET_ADMIN dockurr/w

- Now your Windows installation is ready for use. Enjoy it, and don't forget to star this repo!

* ### How do I install an unsupported version?
* ### How do I install a custom image?

You can specify an URL in the `VERSION` environment variable, in order to download a custom ISO image:
In order to download a custom ISO image, specify an URL in the `VERSION` environment variable:

```yaml
environment:
VERSION: "https://example.com/win.iso"
```

During the installation you may need to add some drivers as described in [manual installation](https://github.com/dockur/windows/tree/master?tab=readme-ov-file#how-do-i-perform-a-manual-installation) above.
Make sure your `/storage` folder is empty before starting the container. Alternatively, you can also place a file called `custom.iso` in that folder to skip the download.

* ### How do I pass-through a disk?

Expand Down
142 changes: 89 additions & 53 deletions src/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
set -Eeuo pipefail

: "${MANUAL:=""}"
: "${EXTERNAL:=""}"
: "${VERSION:="win11x64"}"

[[ "${VERSION,,}" == "11" ]] && VERSION="win11x64"
Expand Down Expand Up @@ -48,78 +47,104 @@ fi

MSG="Windows is being started, please wait..."

BASE="custom.iso"
if [ ! -f "$STORAGE/$BASE" ]; then

if [[ "$EXTERNAL" != [Yy1]* ]]; then
if [[ "$EXTERNAL" != [Yy1]* ]]; then

BASE="$VERSION.iso"
if [ ! -f "$STORAGE/$BASE" ]; then
MSG="Windows is being downloaded, please wait..."
fi
BASE="$VERSION.iso"

else
if [ ! -f "$STORAGE/$BASE" ]; then
MSG="Windows is being downloaded, please wait..."
fi

BASE=$(basename "${VERSION%%\?*}")
: "${BASE//+/ }"; printf -v BASE '%b' "${_//%/\\x}"
BASE=$(echo "$BASE" | sed -e 's/[^A-Za-z0-9._-]/_/g')
else

if [ ! -f "$STORAGE/$BASE" ]; then
MSG="Image '$BASE' is being downloaded, please wait..."
fi
BASE=$(basename "${VERSION%%\?*}")
: "${BASE//+/ }"; printf -v BASE '%b' "${_//%/\\x}"
BASE=$(echo "$BASE" | sed -e 's/[^A-Za-z0-9._-]/_/g')

if [ ! -f "$STORAGE/$BASE" ]; then
MSG="Image '$BASE' is being downloaded, please wait..."
fi

fi

[[ "${BASE,,}" == "custom."* ]] && BASE="target.iso"

html "$MSG"
TMP="$STORAGE/tmp"

[ -f "$STORAGE/$BASE" ] && return 0
if [ -f "$STORAGE/$BASE" ]; then
rm -rf "$TMP"
return 0
fi

TMP="$STORAGE/tmp"
rm -rf "$TMP"
mkdir -p "$TMP"

ISO="$TMP/$BASE"
rm -f "$ISO"

if [[ "$EXTERNAL" != [Yy1]* ]]; then

SCRIPT="$TMP/mido.sh"
CUSTOM="custom.iso"

rm -f "$SCRIPT"
cp /run/mido.sh "$SCRIPT"
chmod +x "$SCRIPT"
cd "$TMP"
bash "$SCRIPT" "$VERSION"
rm -f "$SCRIPT"
cd /run
[ ! -f "$STORAGE/$CUSTOM" ] && CUSTOM="custom.img"
[ ! -f "$STORAGE/$CUSTOM" ] && CUSTOM="Custom.iso"
[ ! -f "$STORAGE/$CUSTOM" ] && CUSTOM="Custom.img"
[ ! -f "$STORAGE/$CUSTOM" ] && CUSTOM="custom.ISO"
[ ! -f "$STORAGE/$CUSTOM" ] && CUSTOM="custom.IMG"
[ ! -f "$STORAGE/$CUSTOM" ] && CUSTOM="CUSTOM.ISO"
[ ! -f "$STORAGE/$CUSTOM" ] && CUSTOM="CUSTOM.IMG"

if [ ! -f "$STORAGE/$CUSTOM" ]; then
CUSTOM=""
else
ISO="$STORAGE/$CUSTOM"
fi

info "Downloading $BASE as boot image..."
if [ ! -f "$ISO" ]; then
if [[ "$EXTERNAL" != [Yy1]* ]]; then

cd "$TMP"
/run/mido.sh "$VERSION"
cd /run

# Check if running with interactive TTY or redirected to docker log
if [ -t 1 ]; then
PROGRESS="--progress=bar:noscroll"
else
PROGRESS="--progress=dot:giga"
fi

{ wget "$VERSION" -O "$ISO" -q --no-check-certificate --show-progress "$PROGRESS"; rc=$?; } || :
info "Downloading $BASE as boot image..."

(( rc != 0 )) && echo && error "Failed to download $VERSION, reason: $rc" && exit 60
# Check if running with interactive TTY or redirected to docker log
if [ -t 1 ]; then
PROGRESS="--progress=bar:noscroll"
else
PROGRESS="--progress=dot:giga"
fi

fi
{ wget "$VERSION" -O "$ISO" -q --no-check-certificate --show-progress "$PROGRESS"; rc=$?; } || :

[ ! -f "$ISO" ] && echo && error "Failed to download $VERSION" && exit 61
(( rc != 0 )) && echo && error "Failed to download $VERSION, reason: $rc" && exit 60

fi

[ ! -f "$ISO" ] && echo && error "Failed to download $VERSION" && exit 61
fi

SIZE=$(stat -c%s "$ISO")
SIZE_GB=$(( (SIZE + 1073741823)/1073741824 ))

if ((SIZE<10000000)); then
echo && error "Invalid ISO file: Size is smaller than 10 MB" && exit 62
fi

MSG="Extracting downloaded ISO image..."
SPACE=$(df --output=avail -B 1 "$TMP" | tail -n 1)
SPACE_GB=$(( (SPACE + 1073741823)/1073741824 ))

if (( SIZE > SPACE )); then
error "Not enough free space in $STORAGE, have $SPACE_GB GB available but need at least $SIZE_GB GB." && exit 63
fi

if [ -n "$CUSTOM" ]; then
MSG="Extracting custom ISO image..."
else
MSG="Extracting downloaded ISO image..."
fi

echo && info "$MSG" && html "$MSG"

DIR="$TMP/unpack"
Expand All @@ -138,11 +163,13 @@ if [ ! -f "$DIR/$ETFS" ] || [ ! -f "$DIR/$EFISYS" ]; then
else
warn "failed to locate file 'efisys_noprompt.bin' in ISO image, $FB"
fi
mv "$ISO" "$STORAGE/$BASE"
mv -f "$ISO" "$STORAGE/$BASE"
rm -rf "$TMP"
echo && return 0
fi

[ -z "$CUSTOM" ] && rm -f "$ISO"

if [ -z "$MANUAL" ]; then

MANUAL="N"
Expand All @@ -156,11 +183,10 @@ fi
XML=""

if [[ "$MANUAL" != [Yy1]* ]]; then
if [[ "$EXTERNAL" != [Yy1]* ]]; then

XML="$VERSION.xml"
[[ "$EXTERNAL" != [Yy1]* ]] && XML="$VERSION.xml"

else
if [ ! -f "/run/assets/$XML" ]; then

MSG="Detecting Windows version from ISO image..."
info "$MSG" && html "$MSG"
Expand Down Expand Up @@ -190,7 +216,12 @@ if [[ "$MANUAL" != [Yy1]* ]]; then
if [ -n "$DETECTED" ]; then

XML="$DETECTED.xml"
echo "Detected image of type '$DETECTED', will apply autounattend.xml file."

if [ -f "/run/assets/$XML" ]; then
echo "Detected image of type '$DETECTED', will apply an autounattend.xml file."
else
warn "detected image of type '$DETECTED', but no matching .xml file exists, $FB."
fi

else
if [ -z "$NAME" ]; then
Expand Down Expand Up @@ -255,25 +286,30 @@ if [ -f "$ASSET" ]; then

echo

else
if [ -n "$XML" ]; then
warn "XML file '$XML' does not exist, $FB" && echo
fi
fi

CAT="BOOT.CAT"
LABEL="${BASE%.*}"
LABEL="${LABEL::30}"
ISO="$TMP/$LABEL.tmp"
rm -f "$ISO"
OUT="$TMP/$LABEL.tmp"
rm -f "$OUT"

SPACE=$(df --output=avail -B 1 "$TMP" | tail -n 1)
SPACE_GB=$(( (SPACE + 1073741823)/1073741824 ))

if (( SIZE > SPACE )); then
error "Not enough free space in $STORAGE, have $SPACE_GB GB available but need at least $SIZE_GB GB." && exit 63
fi

MSG="Generating new ISO image for installation..."
info "$MSG" && html "$MSG"

genisoimage -b "$ETFS" -no-emul-boot -c "$CAT" -iso-level 4 -J -l -D -N -joliet-long -relaxed-filenames -quiet -V "$LABEL" -udf \
-boot-info-table -eltorito-alt-boot -eltorito-boot "$EFISYS" -no-emul-boot -o "$ISO" -allow-limited-size "$DIR"
-boot-info-table -eltorito-alt-boot -eltorito-boot "$EFISYS" -no-emul-boot -o "$OUT" -allow-limited-size "$DIR"

[ -n "$CUSTOM" ] && rm -f "$STORAGE/$CUSTOM"

mv "$ISO" "$STORAGE/$BASE"
mv "$OUT" "$STORAGE/$BASE"
rm -rf "$TMP"

html "Successfully prepared image for installation..."
Expand Down
Loading