Compare commits
No commits in common. "master" and "v4.09" have entirely different histories.
20 changed files with 670 additions and 539 deletions
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"name": "windows",
|
||||
"service": "windows",
|
||||
"forwardPorts": [8006],
|
||||
"dockerComposeFile": "compose.yml"
|
||||
}
|
2
.github/ISSUE_TEMPLATE/1-issue.yml
vendored
2
.github/ISSUE_TEMPLATE/1-issue.yml
vendored
|
@ -21,7 +21,6 @@ body:
|
|||
attributes:
|
||||
label: Docker compose
|
||||
description: The compose file (or otherwise the `docker run` command used).
|
||||
render: yaml
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
|
@ -29,7 +28,6 @@ body:
|
|||
attributes:
|
||||
label: Docker log
|
||||
description: The logfile of the container (as shown by `docker logs windows`).
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
|
|
2
.github/ISSUE_TEMPLATE/3-bug.yml
vendored
2
.github/ISSUE_TEMPLATE/3-bug.yml
vendored
|
@ -23,7 +23,6 @@ body:
|
|||
attributes:
|
||||
label: Docker compose
|
||||
description: The compose file (or otherwise the `docker run` command used).
|
||||
render: yaml
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
|
@ -31,7 +30,6 @@ body:
|
|||
attributes:
|
||||
label: Docker log
|
||||
description: The logfile of the container (as shown by `docker logs windows`).
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
|
|
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
|
@ -50,7 +50,7 @@ jobs:
|
|||
labels: |
|
||||
org.opencontainers.image.title=${{ vars.NAME }}
|
||||
env:
|
||||
DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index
|
||||
DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
@ -74,7 +74,7 @@ jobs:
|
|||
context: .
|
||||
push: true
|
||||
provenance: false
|
||||
platforms: linux/amd64,linux/arm64
|
||||
platforms: linux/arm64
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
annotations: ${{ steps.meta.outputs.annotations }}
|
||||
|
|
15
Dockerfile
15
Dockerfile
|
@ -1,5 +1,5 @@
|
|||
FROM scratch
|
||||
COPY --from=qemux/qemu-arm:7.12 / /
|
||||
COPY --from=qemux/qemu-arm:2.25 / /
|
||||
|
||||
ARG VERSION_ARG="0.00"
|
||||
ARG DEBCONF_NOWARNINGS="yes"
|
||||
|
@ -9,14 +9,19 @@ ARG DEBCONF_NONINTERACTIVE_SEEN="true"
|
|||
RUN set -eu && \
|
||||
apt-get update && \
|
||||
apt-get --no-install-recommends -y install \
|
||||
bc \
|
||||
jq \
|
||||
curl \
|
||||
7zip \
|
||||
wsdd \
|
||||
samba \
|
||||
xz-utils \
|
||||
wimtools \
|
||||
dos2unix \
|
||||
cabextract \
|
||||
genisoimage \
|
||||
libxml2-utils \
|
||||
libarchive-tools \
|
||||
netcat-openbsd && \
|
||||
libarchive-tools && \
|
||||
apt-get clean && \
|
||||
echo "$VERSION_ARG" > /run/version && \
|
||||
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
@ -24,10 +29,10 @@ RUN set -eu && \
|
|||
COPY --chmod=755 ./src /run/
|
||||
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
|
||||
EXPOSE 3389 8006
|
||||
EXPOSE 8006 3389
|
||||
|
||||
ENV VERSION="11"
|
||||
ENV RAM_SIZE="4G"
|
||||
|
|
|
@ -326,6 +326,11 @@
|
|||
<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>
|
||||
</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">
|
||||
<Order>3</Order>
|
||||
<CommandLine>reg.exe add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\PasswordLess\Device" /v "DevicePasswordLessBuildVersion" /t REG_DWORD /d 0 /f</CommandLine>
|
||||
|
@ -413,11 +418,6 @@
|
|||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<Order>20</Order>
|
||||
<CommandLine>cmd /C echo 20.20.20.1 host.lan >> %WINDIR%\system32\drivers\etc\hosts</CommandLine>
|
||||
<Description>Add entry in hosts file</Description>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<Order>21</Order>
|
||||
<CommandLine>cmd /C if exist "C:\OEM\install.bat" start "Install" "cmd /C C:\OEM\install.bat"</CommandLine>
|
||||
<Description>Execute custom script from the OEM folder if exists</Description>
|
||||
</SynchronousCommand>
|
||||
|
|
|
@ -329,6 +329,11 @@
|
|||
<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>
|
||||
</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">
|
||||
<Order>3</Order>
|
||||
<CommandLine>reg.exe add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\PasswordLess\Device" /v "DevicePasswordLessBuildVersion" /t REG_DWORD /d 0 /f</CommandLine>
|
||||
|
@ -416,11 +421,6 @@
|
|||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<Order>20</Order>
|
||||
<CommandLine>cmd /C echo 20.20.20.1 host.lan >> %WINDIR%\system32\drivers\etc\hosts</CommandLine>
|
||||
<Description>Add entry in hosts file</Description>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<Order>21</Order>
|
||||
<CommandLine>cmd /C if exist "C:\OEM\install.bat" start "Install" "cmd /C C:\OEM\install.bat"</CommandLine>
|
||||
<Description>Execute custom script from the OEM folder if exists</Description>
|
||||
</SynchronousCommand>
|
||||
|
|
|
@ -326,6 +326,11 @@
|
|||
<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>
|
||||
</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">
|
||||
<Order>3</Order>
|
||||
<CommandLine>reg.exe add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\PasswordLess\Device" /v "DevicePasswordLessBuildVersion" /t REG_DWORD /d 0 /f</CommandLine>
|
||||
|
@ -413,11 +418,6 @@
|
|||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<Order>20</Order>
|
||||
<CommandLine>cmd /C echo 20.20.20.1 host.lan >> %WINDIR%\system32\drivers\etc\hosts</CommandLine>
|
||||
<Description>Add entry in hosts file</Description>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<Order>21</Order>
|
||||
<CommandLine>cmd /C if exist "C:\OEM\install.bat" start "Install" "cmd /C C:\OEM\install.bat"</CommandLine>
|
||||
<Description>Execute custom script from the OEM folder if exists</Description>
|
||||
</SynchronousCommand>
|
||||
|
|
|
@ -268,11 +268,6 @@
|
|||
<Path>reg.exe add "HKLM\SOFTWARE\Policies\Microsoft\Windows NT\CurrentVersion\NetworkList\Signatures\FirstNetwork" /v Category /t REG_DWORD /d 1 /f</Path>
|
||||
<Description>Set Network Location to Home</Description>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>26</Order>
|
||||
<Path>pnputil -i -a C:\Windows\Drivers\viogpudo\viogpudo.inf</Path>
|
||||
<Description>Install VirtIO display driver</Description>
|
||||
</RunSynchronousCommand>
|
||||
</RunSynchronous>
|
||||
</component>
|
||||
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="arm64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||
|
@ -355,6 +350,11 @@
|
|||
<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>
|
||||
</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">
|
||||
<Order>4</Order>
|
||||
<CommandLine>reg.exe add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\PasswordLess\Device" /v "DevicePasswordLessBuildVersion" /t REG_DWORD /d 0 /f</CommandLine>
|
||||
|
@ -447,13 +447,13 @@
|
|||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<Order>22</Order>
|
||||
<CommandLine>cmd /C rd /q C:\Windows.old</CommandLine>
|
||||
<Description>Remove empty Windows.old folder</Description>
|
||||
<CommandLine>pnputil -i -a C:\Windows\Drivers\viogpudo\viogpudo.inf</CommandLine>
|
||||
<Description>Install VirtIO display driver</Description>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<Order>23</Order>
|
||||
<CommandLine>cmd /C echo 20.20.20.1 host.lan >> %WINDIR%\system32\drivers\etc\hosts</CommandLine>
|
||||
<Description>Add entry in hosts file</Description>
|
||||
<CommandLine>cmd /C rd /q C:\Windows.old</CommandLine>
|
||||
<Description>Remove empty Windows.old folder</Description>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<Order>24</Order>
|
||||
|
|
|
@ -267,11 +267,6 @@
|
|||
<Path>reg.exe add "HKLM\SOFTWARE\Policies\Microsoft\Windows NT\CurrentVersion\NetworkList\Signatures\FirstNetwork" /v Category /t REG_DWORD /d 1 /f</Path>
|
||||
<Description>Set Network Location to Home</Description>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>26</Order>
|
||||
<Path>pnputil -i -a C:\Windows\Drivers\viogpudo\viogpudo.inf</Path>
|
||||
<Description>Install VirtIO display driver</Description>
|
||||
</RunSynchronousCommand>
|
||||
</RunSynchronous>
|
||||
</component>
|
||||
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="arm64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||
|
@ -354,6 +349,11 @@
|
|||
<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>
|
||||
</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">
|
||||
<Order>4</Order>
|
||||
<CommandLine>reg.exe add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\PasswordLess\Device" /v "DevicePasswordLessBuildVersion" /t REG_DWORD /d 0 /f</CommandLine>
|
||||
|
@ -446,13 +446,13 @@
|
|||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<Order>22</Order>
|
||||
<CommandLine>cmd /C rd /q C:\Windows.old</CommandLine>
|
||||
<Description>Remove empty Windows.old folder</Description>
|
||||
<CommandLine>pnputil -i -a C:\Windows\Drivers\viogpudo\viogpudo.inf</CommandLine>
|
||||
<Description>Install VirtIO display driver</Description>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<Order>23</Order>
|
||||
<CommandLine>cmd /C echo 20.20.20.1 host.lan >> %WINDIR%\system32\drivers\etc\hosts</CommandLine>
|
||||
<Description>Add entry in hosts file</Description>
|
||||
<CommandLine>cmd /C rd /q C:\Windows.old</CommandLine>
|
||||
<Description>Remove empty Windows.old folder</Description>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<Order>24</Order>
|
||||
|
|
|
@ -268,11 +268,6 @@
|
|||
<Path>reg.exe add "HKLM\SOFTWARE\Policies\Microsoft\Windows NT\CurrentVersion\NetworkList\Signatures\FirstNetwork" /v Category /t REG_DWORD /d 1 /f</Path>
|
||||
<Description>Set Network Location to Home</Description>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>26</Order>
|
||||
<Path>pnputil -i -a C:\Windows\Drivers\viogpudo\viogpudo.inf</Path>
|
||||
<Description>Install VirtIO display driver</Description>
|
||||
</RunSynchronousCommand>
|
||||
</RunSynchronous>
|
||||
</component>
|
||||
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="arm64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||
|
@ -355,6 +350,11 @@
|
|||
<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>
|
||||
</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">
|
||||
<Order>4</Order>
|
||||
<CommandLine>reg.exe add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\PasswordLess\Device" /v "DevicePasswordLessBuildVersion" /t REG_DWORD /d 0 /f</CommandLine>
|
||||
|
@ -447,13 +447,13 @@
|
|||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<Order>22</Order>
|
||||
<CommandLine>cmd /C rd /q C:\Windows.old</CommandLine>
|
||||
<Description>Remove empty Windows.old folder</Description>
|
||||
<CommandLine>pnputil -i -a C:\Windows\Drivers\viogpudo\viogpudo.inf</CommandLine>
|
||||
<Description>Install VirtIO display driver</Description>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<Order>23</Order>
|
||||
<CommandLine>cmd /C echo 20.20.20.1 host.lan >> %WINDIR%\system32\drivers\etc\hosts</CommandLine>
|
||||
<Description>Add entry in hosts file</Description>
|
||||
<CommandLine>cmd /C rd /q C:\Windows.old</CommandLine>
|
||||
<Description>Remove empty Windows.old folder</Description>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<Order>24</Order>
|
||||
|
|
|
@ -13,7 +13,4 @@ services:
|
|||
- 8006:8006
|
||||
- 3389:3389/tcp
|
||||
- 3389:3389/udp
|
||||
volumes:
|
||||
- ./windows:/storage
|
||||
restart: always
|
||||
stop_grace_period: 2m
|
||||
|
|
127
kubernetes.yml
127
kubernetes.yml
|
@ -10,91 +10,68 @@ spec:
|
|||
requests:
|
||||
storage: 64Gi
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: windows
|
||||
labels:
|
||||
name: windows
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: windows
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: windows
|
||||
spec:
|
||||
containers:
|
||||
- name: windows
|
||||
image: dockurr/windows
|
||||
env:
|
||||
- name: VERSION
|
||||
value: "11"
|
||||
- name: DISK_SIZE
|
||||
value: "64G"
|
||||
ports:
|
||||
- containerPort: 8006
|
||||
name: http
|
||||
protocol: TCP
|
||||
- containerPort: 3389
|
||||
name: rdp
|
||||
protocol: TCP
|
||||
- containerPort: 3389
|
||||
name: udp
|
||||
protocol: UDP
|
||||
- containerPort: 5900
|
||||
name: vnc
|
||||
protocol: TCP
|
||||
securityContext:
|
||||
capabilities:
|
||||
add:
|
||||
- NET_ADMIN
|
||||
privileged: true
|
||||
volumeMounts:
|
||||
- mountPath: /storage
|
||||
name: storage
|
||||
- mountPath: /dev/kvm
|
||||
name: dev-kvm
|
||||
- mountPath: /dev/net/tun
|
||||
name: dev-tun
|
||||
terminationGracePeriodSeconds: 120
|
||||
volumes:
|
||||
- name: storage
|
||||
persistentVolumeClaim:
|
||||
claimName: windows-pvc
|
||||
- hostPath:
|
||||
path: /dev/kvm
|
||||
name: dev-kvm
|
||||
- hostPath:
|
||||
path: /dev/net/tun
|
||||
type: CharDevice
|
||||
name: dev-tun
|
||||
containers:
|
||||
- name: windows
|
||||
image: dockurr/windows
|
||||
env:
|
||||
- name: VERSION
|
||||
value: "11"
|
||||
- name: RAM_SIZE
|
||||
value: "4G"
|
||||
- name: CPU_CORES
|
||||
value: "2"
|
||||
- name: DISK_SIZE
|
||||
value: "64G"
|
||||
ports:
|
||||
- containerPort: 8006
|
||||
- containerPort: 3389
|
||||
- containerPort: 3389
|
||||
protocol: UDP
|
||||
securityContext:
|
||||
capabilities:
|
||||
add:
|
||||
- NET_ADMIN
|
||||
privileged: true
|
||||
volumeMounts:
|
||||
- mountPath: /storage
|
||||
name: storage
|
||||
- mountPath: /dev/kvm
|
||||
name: dev-kvm
|
||||
- mountPath: /dev/net/tun
|
||||
name: dev-tun
|
||||
terminationGracePeriodSeconds: 120
|
||||
volumes:
|
||||
- name: storage
|
||||
persistentVolumeClaim:
|
||||
claimName: windows-pvc
|
||||
- hostPath:
|
||||
path: /dev/kvm
|
||||
name: dev-kvm
|
||||
- hostPath:
|
||||
path: /dev/net/tun
|
||||
type: CharDevice
|
||||
name: dev-tun
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: windows
|
||||
spec:
|
||||
internalTrafficPolicy: Cluster
|
||||
ports:
|
||||
- name: http
|
||||
port: 8006
|
||||
protocol: TCP
|
||||
targetPort: 8006
|
||||
- name: rdp
|
||||
port: 3389
|
||||
protocol: TCP
|
||||
targetPort: 3389
|
||||
- name: udp
|
||||
port: 3389
|
||||
protocol: UDP
|
||||
targetPort: 3389
|
||||
- name: vnc
|
||||
port: 5900
|
||||
protocol: TCP
|
||||
targetPort: 5900
|
||||
- name: tcp-8006
|
||||
port: 8006
|
||||
- name: tcp-3389
|
||||
port: 3389
|
||||
- name: udp-3389
|
||||
port: 3389
|
||||
protocol: UDP
|
||||
selector:
|
||||
app: windows
|
||||
type: ClusterIP
|
||||
name: windows
|
||||
type: NodePort
|
||||
|
|
191
readme.md
191
readme.md
|
@ -26,7 +26,7 @@ Windows for ARM in a Docker container, for devices like the Raspberry Pi 5 and m
|
|||
|
||||
## Usage 🐳
|
||||
|
||||
##### Via Docker Compose:
|
||||
Via Docker Compose:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
|
@ -44,27 +44,28 @@ services:
|
|||
- 8006:8006
|
||||
- 3389:3389/tcp
|
||||
- 3389:3389/udp
|
||||
volumes:
|
||||
- ./windows:/storage
|
||||
restart: always
|
||||
stop_grace_period: 2m
|
||||
```
|
||||
|
||||
##### Via Docker CLI:
|
||||
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 -p 8006:8006 --device=/dev/kvm --device=/dev/net/tun --cap-add NET_ADMIN --stop-timeout 120 dockurr/windows
|
||||
```
|
||||
|
||||
##### Via Kubernetes:
|
||||
Via Kubernetes:
|
||||
|
||||
```shell
|
||||
kubectl apply -f https://raw.githubusercontent.com/dockur/windows/refs/heads/master/kubernetes.yml
|
||||
kubectl apply -f https://raw.githubusercontent.com/dockur/windows-arm/refs/heads/master/kubernetes.yml
|
||||
```
|
||||
|
||||
##### Via Github Codespaces:
|
||||
## Compatibility ⚙️
|
||||
|
||||
[](https://codespaces.new/dockur/windows-arm)
|
||||
| **Product** | **Platform** | |
|
||||
|---|---|---|
|
||||
| Docker Engine | Linux| ✅ |
|
||||
| Docker Desktop | Linux | ❌ |
|
||||
| Docker Desktop | macOS | ❌ |
|
||||
|
||||
## FAQ 💬
|
||||
|
||||
|
@ -72,7 +73,7 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/windows/refs/heads/mas
|
|||
|
||||
Very simple! These are the steps:
|
||||
|
||||
- Start the container and connect to [port 8006](http://127.0.0.1:8006/) using your web browser.
|
||||
- Start the container and connect to [port 8006](http://localhost:8006) using your web browser.
|
||||
|
||||
- Sit back and relax while the magic happens, the whole installation will be performed fully automatic.
|
||||
|
||||
|
@ -91,15 +92,15 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/windows/refs/heads/mas
|
|||
|
||||
Select from the values below:
|
||||
|
||||
| **Value** | **Version** | **Size** |
|
||||
|---|---|---|
|
||||
| `11` | Windows 11 Pro | 4.8 GB |
|
||||
| `11l` | Windows 11 LTSC | 4.7 GB |
|
||||
| `11e` | Windows 11 Enterprise | 4.8 GB |
|
||||
||||
|
||||
| `10` | Windows 10 Pro | 3.5 GB |
|
||||
| `10l` | Windows 10 LTSC | 4.1 GB |
|
||||
| `10e` | Windows 10 Enterprise | 3.4 GB |
|
||||
| **Value** | **Version** | **Platform** | **Size** |
|
||||
|---|---|---|---|
|
||||
| `11` | Windows 11 Pro | ARM64 | 5.0 GB |
|
||||
| `11l` | Windows 11 LTSC | ARM64 | 3.9 GB |
|
||||
| `11e` | Windows 11 Enterprise | ARM64 | 4.8 GB |
|
||||
|||||
|
||||
| `10` | Windows 10 Pro | ARM64 | 3.5 GB |
|
||||
| `10l` | Windows 10 LTSC | ARM64 | 4.1 GB |
|
||||
| `10e` | Windows 10 Enterprise | ARM64 | 3.4 GB |
|
||||
|
||||
> [!TIP]
|
||||
> To install x64 versions of Windows, use [dockur/windows](https://github.com/dockur/windows/).
|
||||
|
@ -110,10 +111,10 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/windows/refs/heads/mas
|
|||
|
||||
```yaml
|
||||
volumes:
|
||||
- ./windows:/storage
|
||||
- /var/win:/storage
|
||||
```
|
||||
|
||||
Replace the example path `./windows` with the desired storage folder or named volume.
|
||||
Replace the example path `/var/win` with the desired storage folder.
|
||||
|
||||
### How do I change the size of the disk?
|
||||
|
||||
|
@ -131,29 +132,71 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/windows/refs/heads/mas
|
|||
|
||||
The display output is a simple framebuffer, just so that the screen can be visible during installation as it doesn't require any drivers.
|
||||
|
||||
To add a virtual graphics cards to your machine that allows for higher resolutions, you can add the following to your compose file after Windows is fully installed:
|
||||
After Windows is fully installed, you can add the following to your compose file:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
VGA: "virtio-gpu"
|
||||
```
|
||||
|
||||
to add a virtual graphics cards to your machine that allows for higher resolutions.
|
||||
|
||||
### How do I share files with the host?
|
||||
|
||||
Open 'File Explorer' and click on the 'Network' section, you will see a computer called `host.lan`.
|
||||
|
||||
Double-click it and it will show a folder called `Data`, which can be bound to any folder on your host via the compose file:
|
||||
Open 'File Explorer' and click on the 'Network' section, you will see a computer called `host.lan`. Double-click it and it will show a folder called `Data`, which can be bound to any folder on your host via the compose file:
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
- ./example:/data
|
||||
- /home/user/example:/data
|
||||
```
|
||||
|
||||
The example folder `./example` will be available as ` \\host.lan\Data`.
|
||||
The example folder `/home/user/example` will be available as ` \\host.lan\Data`.
|
||||
|
||||
> [!TIP]
|
||||
> You can map this path to a drive letter in Windows, for easier access.
|
||||
|
||||
### How do I install a custom image?
|
||||
|
||||
In order to download an unsupported ISO image that is not selectable from the list above, specify the URL of that ISO in the `VERSION` environment variable, for example:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
VERSION: "https://example.com/win.iso"
|
||||
```
|
||||
|
||||
Alternatively, you can also skip the download and use a local file instead, by binding it in your compose file in this way:
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
- /home/user/example.iso:/custom.iso
|
||||
```
|
||||
|
||||
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 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 any additional files it needs (software to be installed for example).
|
||||
|
||||
Then bind that folder in your compose file like this:
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
- /home/user/example:/oem
|
||||
```
|
||||
|
||||
The example folder `/home/user/example` will be copied to `C:\OEM` during installation and the containing `install.bat` will be executed during the last step.
|
||||
|
||||
### How do I perform a manual installation?
|
||||
|
||||
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:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
MANUAL: "Y"
|
||||
```
|
||||
|
||||
### How do I change the amount of CPU or RAM?
|
||||
|
||||
By default, the container will be allowed to use a maximum of 2 CPU cores and 4 GB of RAM.
|
||||
|
@ -168,9 +211,9 @@ The example folder `./example` will be available as ` \\host.lan\Data`.
|
|||
|
||||
### 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` is created during the installation, with an empty password.
|
||||
|
||||
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 change them in your compose file:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
|
@ -180,9 +223,7 @@ The example folder `./example` will be available as ` \\host.lan\Data`.
|
|||
|
||||
### How do I select the Windows language?
|
||||
|
||||
By default, the English version of Windows will be downloaded.
|
||||
|
||||
But before installation you can add the `LANGUAGE` environment variable to your compose file, in order to specify an alternative language:
|
||||
By default, the English version of Windows will be downloaded. But you can add the `LANGUAGE` environment variable to your compose file, in order to specify an alternative language:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
|
@ -193,7 +234,7 @@ The example folder `./example` will be available as ` \\host.lan\Data`.
|
|||
|
||||
### How do I select the keyboard layout?
|
||||
|
||||
If you want to use a keyboard layout or locale that is not the default for your selected language, you can add `KEYBOARD` and `REGION` variables like this (before installation):
|
||||
If you want to use a keyboard layout or locale that is not the default for your selected language, you can add the `KEYBOARD` and `REGION` variables with a culture code, like this:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
|
@ -201,53 +242,14 @@ The example folder `./example` will be available as ` \\host.lan\Data`.
|
|||
KEYBOARD: "en-US"
|
||||
```
|
||||
|
||||
### How do I install a custom image?
|
||||
|
||||
In order to download an unsupported ISO image, specify its URL in the `VERSION` environment variable:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
VERSION: "https://example.com/win.iso"
|
||||
```
|
||||
|
||||
Alternatively, you can also skip the download and use a local file instead, by binding it in your compose file in this way:
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
- ./example.iso:/boot.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.
|
||||
|
||||
### 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 any additional files it needs (software to be installed for example).
|
||||
|
||||
Then bind that folder in your compose file like this:
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
- ./example:/oem
|
||||
```
|
||||
|
||||
The example folder `./example` will be copied to `C:\OEM` and the containing `install.bat` will be executed during the last step of the automatic installation.
|
||||
|
||||
### How do I perform a manual installation?
|
||||
|
||||
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:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
MANUAL: "Y"
|
||||
```
|
||||
> [!NOTE]
|
||||
> Changing these values will have no effect after the installation has been performed already. Use the control panel inside Windows in that case.
|
||||
|
||||
### How do I connect using RDP?
|
||||
|
||||
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.
|
||||
|
||||
|
@ -292,7 +294,7 @@ The example folder `./example` will be available as ` \\host.lan\Data`.
|
|||
|
||||
After configuring the container for [macvlan](#how-do-i-assign-an-individual-ip-address-to-the-container), it is possible for Windows to become part of your home network by requesting an IP from your router, just like a real PC.
|
||||
|
||||
To enable this mode, in which the container and Windows will have separate IP addresses, add the following lines to your compose file:
|
||||
To enable this mode, add the following lines to your compose file:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
|
@ -303,6 +305,9 @@ The example folder `./example` will be available as ` \\host.lan\Data`.
|
|||
- 'c *:* rwm'
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> In this mode, the container and Windows will each have their own separate IPs.
|
||||
|
||||
### How do I add multiple disks?
|
||||
|
||||
To create additional disks, modify your compose file like this:
|
||||
|
@ -312,18 +317,18 @@ The example folder `./example` will be available as ` \\host.lan\Data`.
|
|||
DISK2_SIZE: "32G"
|
||||
DISK3_SIZE: "64G"
|
||||
volumes:
|
||||
- ./example2:/storage2
|
||||
- ./example3:/storage3
|
||||
- /home/example:/storage2
|
||||
- /mnt/data/example:/storage3
|
||||
```
|
||||
|
||||
### 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
|
||||
devices:
|
||||
- /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).
|
||||
|
@ -339,20 +344,14 @@ The example folder `./example` will be available as ` \\host.lan\Data`.
|
|||
- /dev/bus/usb
|
||||
```
|
||||
|
||||
If the device is a USB disk drive, please wait until after the installation is completed before connecting it. Otherwise the installation may fail, as the order of the disks can get rearranged.
|
||||
> [!IMPORTANT]
|
||||
> If the device is a USB disk drive, please wait until after the installation is completed before connecting it. Otherwise the installation may fail, as the order of the disks can get rearranged.
|
||||
|
||||
### How do I verify if my system supports KVM?
|
||||
|
||||
First check if your software is compatible using this chart:
|
||||
|
||||
| **Product** | **Linux** | **Win11** | **Win10** | **macOS** |
|
||||
|---|---|---|---|---|
|
||||
| Docker CLI | ✅ | ✅ | ❌ | ❌ |
|
||||
| Docker Desktop | ❌ | ✅ | ❌ | ❌ |
|
||||
| Podman CLI | ✅ | ✅ | ❌ | ❌ |
|
||||
| Podman Desktop | ✅ | ✅ | ❌ | ❌ |
|
||||
|
||||
After that you can run the following commands in Linux to check your system:
|
||||
Only Linux and Windows 11 support KVM virtualization, macOS and Windows 10 do not unfortunately.
|
||||
|
||||
You can run the following commands in Linux to check your system:
|
||||
|
||||
```bash
|
||||
sudo apt install cpu-checker
|
||||
|
@ -367,11 +366,11 @@ The example folder `./example` will be available as ` \\host.lan\Data`.
|
|||
|
||||
- you are not using a cloud provider, as most of them do not allow nested virtualization for their VPS's.
|
||||
|
||||
If you did not receive any error from `kvm-ok` but the container still complains about a missing KVM device, it could help to add `privileged: true` to your compose file (or `sudo` to your `docker` command) to rule out any permission issue.
|
||||
If you do not receive any error from `kvm-ok` but the container still complains about KVM, please check whether:
|
||||
|
||||
### How do I run a Linux desktop in a container?
|
||||
|
||||
You can use [qemus/qemu-arm](https://github.com/qemus/qemu-arm) in that case.
|
||||
- you are not using "Docker Desktop for Linux" as it does not support KVM, instead make use of Docker Engine directly.
|
||||
|
||||
- it could help to add `privileged: true` to your compose file (or `sudo` to your `docker run` command), to rule out any permission issue.
|
||||
|
||||
### Is this project legal?
|
||||
|
||||
|
|
106
src/define.sh
106
src/define.sh
|
@ -1,12 +1,10 @@
|
|||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
: "${KEY:=""}"
|
||||
: "${WIDTH:=""}"
|
||||
: "${HEIGHT:=""}"
|
||||
: "${VERIFY:=""}"
|
||||
: "${REGION:=""}"
|
||||
: "${EDITION:=""}"
|
||||
: "${MANUAL:=""}"
|
||||
: "${REMOVE:=""}"
|
||||
: "${VERSION:=""}"
|
||||
|
@ -17,6 +15,7 @@ set -Eeuo pipefail
|
|||
: "${PASSWORD:=""}"
|
||||
|
||||
MIRRORS=2
|
||||
PLATFORM="ARM64"
|
||||
|
||||
parseVersion() {
|
||||
|
||||
|
@ -61,23 +60,20 @@ parseVersion() {
|
|||
"8e" | "81e" | "8.1e" | "win8e" | "win81e" | "windows 8e" )
|
||||
error "Windows 8 $msg" && return 1
|
||||
;;
|
||||
"7" | "win7" | "windows7" | "windows 7" | "7u" | "win7u" | "windows7u" | "windows 7u" | "7e" | \
|
||||
"win7e" | "windows7e" | "windows 7e" | "7x86" | "win7x86" | "win732" | "windows7x86" | "7ux86" | \
|
||||
"7u32" | "win7x86-ultimate" | "7ex86" | "7e32" | "win7x86-enterprise" )
|
||||
"7" | "7e" | "win7" | "win7e" | "windows7" | "windows 7" | \
|
||||
"7u" | "win7u" | "windows7u" | "windows 7u" | \
|
||||
"7x86" | "win7x86" | "windows7x86" | "win7x86-enterprise" )
|
||||
error "Windows 7 $msg" && return 1
|
||||
;;
|
||||
"vista" | "vs" | "6" | "winvista" | "windowsvista" | "windows vista" | "vistu" | "vu" | "6u" | "winvistu" | \
|
||||
"viste" | "ve" | "6e" | "winviste" | "vistax86" | "vista32" | "6x86" | "winvistax86" | "windowsvistax86" | \
|
||||
"vux86" | "vu32" | "winvistax86-ultimate" | "vex86" | "ve32" | "winvistax86-enterprise" )
|
||||
"vista" | "ve" | "6" | "winvista" | "windowsvista" | "windows vista" | \
|
||||
"vistu" | "vu" | "6u" | "winvistu" | "windowsvistu" | "windows vistu" | \
|
||||
"vistax86" | "vex86" | "6x86" | "winvistax86" | "windowsvistax86" | "winvistax86-enterprise" )
|
||||
error "Windows Vista $msg" && return 1
|
||||
;;
|
||||
"xp" | "xp32" | "xpx86" | "5" | "5x86" | "winxp" | "winxp86" | "windowsxp" | "windows xp" | \
|
||||
"xp64" | "xpx64" | "5x64" | "winxp64" | "winxpx64" | "windowsxp64" | "windowsxpx64" )
|
||||
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" )
|
||||
error "Windows Server 2025 $msg" && return 1
|
||||
;;
|
||||
|
@ -90,9 +86,6 @@ parseVersion() {
|
|||
"16" | "2016" | "win16" | "win2016" | "windows2016" | "windows 2016" )
|
||||
error "Windows Server 2016 $msg" && return 1
|
||||
;;
|
||||
"hv" | "hyperv" | "hyper v" | "hyper-v" | "19hv" | "2019hv" | "win2019hv" )
|
||||
error "Hyper-V Server 2019 $msg" && return 1
|
||||
;;
|
||||
"2012" | "2012r2" | "win2012" | "win2012r2" | "windows2012" | "windows 2012" )
|
||||
error "Windows Server 2012 $msg" && return 1
|
||||
;;
|
||||
|
@ -450,10 +443,10 @@ fromFile() {
|
|||
local desc="$1"
|
||||
local file="${1,,}"
|
||||
local arch="${PLATFORM,,}"
|
||||
|
||||
|
||||
file="${file//-/_}"
|
||||
file="${file// /_}"
|
||||
|
||||
|
||||
case "$file" in
|
||||
*"_x64_"* | *"_x64."*)
|
||||
arch="x64"
|
||||
|
@ -497,9 +490,7 @@ fromName() {
|
|||
|
||||
case "${name,,}" in
|
||||
*"windows 10"* ) id="win10${arch}" ;;
|
||||
*"optimum 10"* ) id="win10${arch}" ;;
|
||||
*"windows 11"* ) id="win11${arch}" ;;
|
||||
*"optimum 11"* ) id="win11${arch}" ;;
|
||||
esac
|
||||
|
||||
echo "$id"
|
||||
|
@ -550,7 +541,6 @@ getMido() {
|
|||
local id="$1"
|
||||
local lang="$2"
|
||||
local ret="$3"
|
||||
local url=""
|
||||
local sum=""
|
||||
local size=""
|
||||
|
||||
|
@ -562,15 +552,15 @@ getMido() {
|
|||
sum="57d1dfb2c6690a99fe99226540333c6c97d3fd2b557a50dfe3d68c3f675ef2b0"
|
||||
;;
|
||||
"win11arm64-enterprise-ltsc-eval" )
|
||||
size=5042194432
|
||||
sum="3dcdba9c9c0aa0430d4332b60c9afcb3cd613d648a49cbba2d4ef7b5978f32e8"
|
||||
size=4252764160
|
||||
sum="ccec358a760c3c581249f091ed42d04f37b2b99c347b7a58257c3cc272d7982c"
|
||||
;;
|
||||
esac
|
||||
|
||||
case "${ret,,}" in
|
||||
"sum" ) echo "$sum" ;;
|
||||
"size" ) echo "$size" ;;
|
||||
*) echo "$url";;
|
||||
*) echo "";;
|
||||
esac
|
||||
|
||||
return 0
|
||||
|
@ -592,18 +582,19 @@ getLink1() {
|
|||
|
||||
case "${id,,}" in
|
||||
"win11arm64" | "win11arm64-enterprise" | "win11arm64-enterprise-eval" )
|
||||
size=5219411968
|
||||
sum="dbd54452c3c20b4625f511dae3c3e057270448fb661232d4fa66279f59a63157"
|
||||
url="11/en-us_windows_11_24h2_arm64.iso"
|
||||
size=6326812672
|
||||
sum="464c75909b9c37864e144886445a2faa67ac86f0845a68cca3f017b97f810e8d"
|
||||
url="11/en-us_windows_11_23h2_arm64.iso"
|
||||
;;
|
||||
"win11arm64-ltsc" | "win11arm64-enterprise-ltsc-eval" )
|
||||
[[ "${lang,,}" != "en" ]] && [[ "${lang,,}" != "en-us" ]] && return 0
|
||||
size=5121449984
|
||||
sum="f8f068cdc90c894a55d8c8530db7c193234ba57bb11d33b71383839ac41246b4"
|
||||
url="11/X23-81950_26100.1742.240906-0331.ge_release_svc_refresh_CLIENT_ENTERPRISES_OEM_A64FRE_en-us.iso"
|
||||
;;
|
||||
"win10arm64" | "win10arm64-enterprise" | "win10arm64-enterprise-eval" )
|
||||
size=4689637376
|
||||
sum="7b43e64f4e3b961a83f9b70efa4b9d863bc5c348fe86d75917ac974116d17227"
|
||||
size=4846794752
|
||||
sum="6d2688f95fa1d359d68ed0c38c3f38de7b3713c893410e15be9d1e706a4a58c7"
|
||||
url="10/en-us_windows_10_22h2_arm64.iso"
|
||||
;;
|
||||
"win10arm64-ltsc" | "win10arm64-enterprise-ltsc-eval" )
|
||||
|
@ -645,31 +636,6 @@ getLink2() {
|
|||
sum="812dae6b5bf5215db63b61ae10d8f0ffd3aa8529a18d96e9ced53341e2c676ec"
|
||||
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
|
||||
|
||||
case "${ret,,}" in
|
||||
|
@ -756,12 +722,42 @@ isESD() {
|
|||
return 1
|
||||
}
|
||||
|
||||
isMG() {
|
||||
|
||||
local id="$1"
|
||||
local lang="$2"
|
||||
|
||||
case "${id,,}" in
|
||||
"win11${PLATFORM,,}" )
|
||||
return 0
|
||||
;;
|
||||
"win11${PLATFORM,,}-enterprise" | "win11${PLATFORM,,}-enterprise-eval" )
|
||||
return 0
|
||||
;;
|
||||
"win11${PLATFORM,,}-ltsc" | "win11${PLATFORM,,}-enterprise-ltsc-eval" )
|
||||
return 0
|
||||
;;
|
||||
"win10${PLATFORM,,}" )
|
||||
return 0
|
||||
;;
|
||||
"win10${PLATFORM,,}-enterprise" | "win10${PLATFORM,,}-enterprise-eval" )
|
||||
return 0
|
||||
;;
|
||||
"win10${PLATFORM,,}-ltsc" | "win10${PLATFORM,,}-enterprise-ltsc-eval" )
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
validVersion() {
|
||||
|
||||
local id="$1"
|
||||
local lang="$2"
|
||||
local url
|
||||
|
||||
isMG "$id" "$lang" && return 0
|
||||
isESD "$id" "$lang" && return 0
|
||||
isMido "$id" "$lang" && return 0
|
||||
|
||||
|
@ -793,12 +789,16 @@ addFolder() {
|
|||
cp -Lr "$folder/." "$dest" || return 1
|
||||
|
||||
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"
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
migrateFiles() {
|
||||
return 0
|
||||
}
|
||||
|
||||
detectLegacy() {
|
||||
return 1
|
||||
}
|
||||
|
|
16
src/entry.sh
16
src/entry.sh
|
@ -1,18 +1,16 @@
|
|||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
: "${APP:="Windows"}"
|
||||
: "${MACHINE:="virt"}"
|
||||
: "${PLATFORM:="arm64"}"
|
||||
: "${BOOT_MODE:="windows"}"
|
||||
: "${SUPPORT:="https://github.com/dockur/windows-arm"}"
|
||||
|
||||
APP="Windows"
|
||||
SUPPORT="https://github.com/dockur/windows-arm"
|
||||
|
||||
cd /run
|
||||
|
||||
. utils.sh # Load functions
|
||||
. reset.sh # Initialize system
|
||||
. define.sh # Define versions
|
||||
. mido.sh # Download Windows
|
||||
. mido.sh # Download code
|
||||
. install.sh # Run installation
|
||||
. disk.sh # Initialize disks
|
||||
. display.sh # Initialize graphics
|
||||
|
@ -39,10 +37,8 @@ fi
|
|||
terminal
|
||||
( sleep 30; boot ) &
|
||||
tail -fn +0 "$QEMU_LOG" 2>/dev/null &
|
||||
cat "$QEMU_TERM" 2> /dev/null | tee "$QEMU_PTY" | \
|
||||
sed -u -e 's/\x1B\[[=0-9;]*[a-z]//gi' \
|
||||
-e 's/failed to load Boot/skipped Boot/g' \
|
||||
-e 's/0): Not Found/0)/g' & wait $! || :
|
||||
cat "$QEMU_TERM" 2> /dev/null | tee "$QEMU_PTY" &
|
||||
wait $! || :
|
||||
|
||||
sleep 1 & wait $!
|
||||
[ ! -f "$QEMU_END" ] && finish 0
|
||||
|
|
260
src/install.sh
260
src/install.sh
|
@ -10,31 +10,21 @@ EFISYS="efi/microsoft/boot/efisys_noprompt.bin"
|
|||
skipInstall() {
|
||||
|
||||
local iso="$1"
|
||||
local method=""
|
||||
local magic byte
|
||||
local boot="$STORAGE/windows.boot"
|
||||
local previous="$STORAGE/windows.base"
|
||||
|
||||
if [ -f "$previous" ]; then
|
||||
previous=$(<"$previous")
|
||||
previous="${previous//[![:print:]]/}"
|
||||
if [ -n "$previous" ]; then
|
||||
if [[ "${STORAGE,,}/${previous,,}" != "${iso,,}" ]]; then
|
||||
previous="$STORAGE/$previous"
|
||||
if [[ "${previous,,}" != "${iso,,}" ]]; then
|
||||
if [ -f "$boot" ] && hasDisk; then
|
||||
if [[ "${iso,,}" == "${STORAGE,,}/windows."* ]]; then
|
||||
method="your custom .iso file"
|
||||
else
|
||||
if [[ "${previous,,}" != "windows."* ]]; then
|
||||
method="the VERSION variable"
|
||||
fi
|
||||
fi
|
||||
if [ -n "$method" ]; then
|
||||
info "Detected that $method was changed, but ignoring this because Windows is already installed."
|
||||
info "Please start with an empty /storage folder, if you want to install a different version of Windows."
|
||||
fi
|
||||
info "Detected that the version was changed, but ignoring this because Windows is already installed."
|
||||
info "Please start with an empty /storage folder, if you want to install a different version of Windows."
|
||||
return 0
|
||||
fi
|
||||
rm -f "$STORAGE/$previous"
|
||||
[ -f "$previous" ] && rm -f "$previous"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
@ -86,6 +76,8 @@ startInstall() {
|
|||
|
||||
BOOT="$STORAGE/$file"
|
||||
|
||||
! migrateFiles "$BOOT" "$VERSION" && error "Migration failed!" && exit 57
|
||||
|
||||
fi
|
||||
|
||||
skipInstall "$BOOT" && return 1
|
||||
|
@ -128,8 +120,6 @@ finishInstall() {
|
|||
|
||||
rm -f "$STORAGE/windows.old"
|
||||
rm -f "$STORAGE/windows.vga"
|
||||
rm -f "$STORAGE/windows.net"
|
||||
rm -f "$STORAGE/windows.usb"
|
||||
rm -f "$STORAGE/windows.args"
|
||||
rm -f "$STORAGE/windows.base"
|
||||
rm -f "$STORAGE/windows.boot"
|
||||
|
@ -172,22 +162,10 @@ finishInstall() {
|
|||
echo "$ARGS" > "$STORAGE/windows.args"
|
||||
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
|
||||
echo "$DISK_TYPE" > "$STORAGE/windows.type"
|
||||
fi
|
||||
|
||||
if [ -n "${ADAPTER:-}" ] && [[ "${ADAPTER:-}" != "virtio-net-pci" ]]; then
|
||||
echo "$ADAPTER" > "$STORAGE/windows.net"
|
||||
fi
|
||||
|
||||
rm -rf "$TMP"
|
||||
return 0
|
||||
}
|
||||
|
@ -199,9 +177,8 @@ abortInstall() {
|
|||
local efi
|
||||
|
||||
[[ "${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
|
||||
[[ "${PLATFORM,,}" == "x64" ]] && BOOT_MODE="windows_legacy"
|
||||
|
@ -222,23 +199,13 @@ abortInstall() {
|
|||
return 1
|
||||
}
|
||||
|
||||
findFile() {
|
||||
detectCustom() {
|
||||
|
||||
local dir file base
|
||||
local fname="$1"
|
||||
local boot="$STORAGE/windows.boot"
|
||||
local file base
|
||||
CUSTOM=""
|
||||
|
||||
dir=$(find / -maxdepth 1 -type d -iname "$fname" -print -quit)
|
||||
[ ! -d "$dir" ] && dir=$(find "$STORAGE" -maxdepth 1 -type d -iname "$fname" -print -quit)
|
||||
|
||||
if [ -d "$dir" ]; then
|
||||
if ! hasDisk || [ ! -f "$boot" ]; then
|
||||
error "The bind $dir maps to a file that does not exist!" && return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
file=$(find / -maxdepth 1 -type f -iname "$fname" -print -quit)
|
||||
[ ! -s "$file" ] && file=$(find "$STORAGE" -maxdepth 1 -type f -iname "$fname" -print -quit)
|
||||
file=$(find / -maxdepth 1 -type f -iname custom.iso | head -n 1)
|
||||
[ ! -s "$file" ] && file=$(find "$STORAGE" -maxdepth 1 -type f -iname custom.iso | head -n 1)
|
||||
|
||||
if [ ! -s "$file" ] && [[ "${VERSION,,}" != "http"* ]]; then
|
||||
base=$(basename "$VERSION")
|
||||
|
@ -254,25 +221,12 @@ findFile() {
|
|||
[ -z "$size" ] || [[ "$size" == "0" ]] && return 0
|
||||
|
||||
ISO="$file"
|
||||
CUSTOM="$file"
|
||||
CUSTOM="$ISO"
|
||||
BOOT="$STORAGE/windows.$size.iso"
|
||||
|
||||
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() {
|
||||
|
||||
local iso="$1"
|
||||
|
@ -292,12 +246,12 @@ extractESD() {
|
|||
mkdir -p "$dir"
|
||||
|
||||
size=16106127360
|
||||
size_gb=$(formatBytes "$size")
|
||||
size_gb=$(( (size + 1073741823)/1073741824 ))
|
||||
space=$(df --output=avail -B 1 "$dir" | tail -n 1)
|
||||
space_gb=$(formatBytes "$space")
|
||||
space_gb=$(( (space + 1073741823)/1073741824 ))
|
||||
|
||||
if (( size > space )); then
|
||||
error "Not enough free space in $STORAGE, have $space_gb available but need at least $size_gb." && return 1
|
||||
error "Not enough free space in $STORAGE, have $space_gb GB available but need at least $size_gb GB." && return 1
|
||||
fi
|
||||
|
||||
local esdImageCount
|
||||
|
@ -362,7 +316,7 @@ extractImage() {
|
|||
local dir="$2"
|
||||
local version="$3"
|
||||
local desc="local ISO"
|
||||
local file size size_gb space space_gb
|
||||
local size size_gb space space_gb
|
||||
|
||||
if [ -z "$CUSTOM" ]; then
|
||||
desc="downloaded ISO"
|
||||
|
@ -383,16 +337,16 @@ extractImage() {
|
|||
mkdir -p "$dir"
|
||||
|
||||
size=$(stat -c%s "$iso")
|
||||
size_gb=$(formatBytes "$size")
|
||||
size_gb=$(( (size + 1073741823)/1073741824 ))
|
||||
space=$(df --output=avail -B 1 "$dir" | tail -n 1)
|
||||
space_gb=$(formatBytes "$space")
|
||||
space_gb=$(( (space + 1073741823)/1073741824 ))
|
||||
|
||||
if ((size<100000000)); then
|
||||
error "Invalid ISO file: Size is smaller than 100 MB" && return 1
|
||||
fi
|
||||
|
||||
if (( size > space )); then
|
||||
error "Not enough free space in $STORAGE, have $space_gb available but need at least $size_gb." && return 1
|
||||
error "Not enough free space in $STORAGE, have $space_gb GB available but need at least $size_gb GB." && return 1
|
||||
fi
|
||||
|
||||
rm -rf "$dir"
|
||||
|
@ -401,26 +355,7 @@ extractImage() {
|
|||
error "Failed to extract ISO file: $iso" && return 1
|
||||
fi
|
||||
|
||||
if [[ "${UNPACK:-}" != [Yy1]* ]]; then
|
||||
|
||||
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
|
||||
LABEL=$(isoinfo -d -i "$iso" | sed -n 's/Volume id: //p')
|
||||
|
||||
return 0
|
||||
}
|
||||
|
@ -554,10 +489,6 @@ setXML() {
|
|||
|
||||
local file="/custom.xml"
|
||||
|
||||
if [ -d "$file" ]; then
|
||||
error "The bind $file maps to a file that does not exist!" && exit 67
|
||||
fi
|
||||
|
||||
[ ! -f "$file" ] || [ ! -s "$file" ] && file="$STORAGE/custom.xml"
|
||||
[ ! -f "$file" ] || [ ! -s "$file" ] && file="/run/assets/custom.xml"
|
||||
[ ! -f "$file" ] || [ ! -s "$file" ] && file="$1"
|
||||
|
@ -602,14 +533,14 @@ detectImage() {
|
|||
fi
|
||||
|
||||
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
|
||||
warn "failed to locate 'sources' folder in ISO image, $FB" && return 1
|
||||
fi
|
||||
|
||||
wim=$(find "$src" -maxdepth 1 -type f -iname install.wim -print -quit)
|
||||
[ ! -f "$wim" ] && wim=$(find "$src" -maxdepth 1 -type f -iname install.esd -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 | head -n 1)
|
||||
|
||||
if [ ! -f "$wim" ]; then
|
||||
warn "failed to locate 'install.wim' or 'install.esd' in ISO image, $FB" && return 1
|
||||
|
@ -642,10 +573,6 @@ detectImage() {
|
|||
info "Detected: $desc"
|
||||
setXML "" && return 0
|
||||
|
||||
if [[ "$DETECTED" == "win81x86"* ]] || [[ "$DETECTED" == "win10x86"* ]]; then
|
||||
error "The 32-bit version of $desc is not supported!" && return 1
|
||||
fi
|
||||
|
||||
msg="the answer file for $desc was not found ($DETECTED.xml)"
|
||||
local fallback="/run/assets/${DETECTED%%-*}.xml"
|
||||
|
||||
|
@ -693,10 +620,6 @@ updateXML() {
|
|||
local language="$2"
|
||||
local culture region user admin pass keyboard
|
||||
|
||||
if [ -n "${VM_NET_IP:-}" ]; then
|
||||
sed -i "s/ 20.20.20.1 / ${VM_NET_IP%.*}.1 /g" "$asset"
|
||||
fi
|
||||
|
||||
[ -z "$HEIGHT" ] && HEIGHT="720"
|
||||
[ -z "$WIDTH" ] && WIDTH="1280"
|
||||
|
||||
|
@ -734,26 +657,15 @@ updateXML() {
|
|||
sed -i "s/<Username>Docker<\/Username>/<Username>$user<\/Username>/g" "$asset"
|
||||
fi
|
||||
|
||||
[ -n "$PASSWORD" ] && pass="$PASSWORD" || pass="admin"
|
||||
|
||||
pw=$(printf '%s' "${pass}Password" | 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/<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>$pw<\/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"
|
||||
|
||||
if [ -n "$EDITION" ]; then
|
||||
[[ "${EDITION^^}" == "CORE" ]] && EDITION="STANDARDCORE"
|
||||
sed -i "s/SERVERSTANDARD<\/Value>/SERVER${EDITION^^}<\/Value>/g" "$asset"
|
||||
fi
|
||||
|
||||
if [ -n "$KEY" ]; then
|
||||
sed -i '/<ProductKey>/,/<\/ProductKey>/d' "$asset"
|
||||
sed -i "s/<\/UserData>/ <ProductKey>\n <Key>${KEY}<\/Key>\n <WillShowUI>OnError<\/WillShowUI>\n <\/ProductKey>\n <\/UserData>/g" "$asset"
|
||||
if [ -n "$PASSWORD" ]; then
|
||||
pass=$(printf '%s' "${PASSWORD}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)
|
||||
sed -i "s/<Value>password<\/Value>/<Value>$admin<\/Value>/g" "$asset"
|
||||
sed -i "s/<PlainText>true<\/PlainText>/<PlainText>false<\/PlainText>/g" "$asset"
|
||||
sed -z "s/<Password>...........<Value \/>/<Password>\n <Value>$pass<\/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"
|
||||
fi
|
||||
|
||||
return 0
|
||||
|
@ -765,13 +677,8 @@ addDriver() {
|
|||
local path="$2"
|
||||
local target="$3"
|
||||
local driver="$4"
|
||||
local desc=""
|
||||
local folder=""
|
||||
|
||||
if [ -z "$id" ]; then
|
||||
warn "no Windows version specified for \"$driver\" driver!" && return 0
|
||||
fi
|
||||
|
||||
case "${id,,}" in
|
||||
"win7x86"* ) folder="w7/x86" ;;
|
||||
"win7x64"* ) folder="w7/amd64" ;;
|
||||
|
@ -791,12 +698,7 @@ addDriver() {
|
|||
esac
|
||||
|
||||
if [ -z "$folder" ]; then
|
||||
desc=$(printVersion "$id" "$id")
|
||||
if [[ "${id,,}" != *"x86"* ]]; then
|
||||
warn "no \"$driver\" driver available for \"$desc\" !" && return 0
|
||||
else
|
||||
warn "no \"$driver\" driver available for the 32-bit version of \"$desc\" !" && return 0
|
||||
fi
|
||||
warn "no \"$driver\" driver found for \"$DETECTED\" !" && return 0
|
||||
fi
|
||||
|
||||
[ ! -d "$path/$driver/$folder" ] && return 0
|
||||
|
@ -829,12 +731,7 @@ addDrivers() {
|
|||
local msg="Adding drivers to image..."
|
||||
info "$msg" && html "$msg"
|
||||
|
||||
if [ -z "$version" ]; then
|
||||
version="win11x64"
|
||||
warn "Windows version unknown, falling back to Windows 11 drivers..."
|
||||
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
|
||||
fi
|
||||
|
||||
|
@ -847,7 +744,7 @@ addDrivers() {
|
|||
addDriver "$version" "$drivers" "$target" "qxl" || return 1
|
||||
addDriver "$version" "$drivers" "$target" "viofs" || 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" "viorng" || return 1
|
||||
addDriver "$version" "$drivers" "$target" "viostor" || return 1
|
||||
|
@ -855,7 +752,7 @@ addDrivers() {
|
|||
addDriver "$version" "$drivers" "$target" "NetKVM" || return 1
|
||||
addDriver "$version" "$drivers" "$target" "Balloon" || 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" "viogpudo" || return 1
|
||||
addDriver "$version" "$drivers" "$target" "vioserial" || return 1
|
||||
|
@ -903,14 +800,14 @@ updateImage() {
|
|||
rm -rf "$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
|
||||
error "failed to locate 'sources' folder in ISO image, $FB" && return 1
|
||||
fi
|
||||
|
||||
wim=$(find "$src" -maxdepth 1 -type f -iname boot.wim -print -quit)
|
||||
[ ! -f "$wim" ] && wim=$(find "$src" -maxdepth 1 -type f -iname boot.esd -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 | head -n 1)
|
||||
|
||||
if [ ! -f "$wim" ]; then
|
||||
error "failed to locate 'boot.wim' or 'boot.esd' in ISO image, $FB" && return 1
|
||||
|
@ -973,7 +870,7 @@ updateImage() {
|
|||
|
||||
local find="$file"
|
||||
[[ "$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 [[ "$MANUAL" != [Yy1]* ]]; then
|
||||
|
@ -1027,12 +924,12 @@ buildImage() {
|
|||
fi
|
||||
|
||||
size=$(du -h -b --max-depth=0 "$dir" | cut -f1)
|
||||
size_gb=$(formatBytes "$size")
|
||||
size_gb=$(( (size + 1073741823)/1073741824 ))
|
||||
space=$(df --output=avail -B 1 "$TMP" | tail -n 1)
|
||||
space_gb=$(formatBytes "$space")
|
||||
space_gb=$(( (space + 1073741823)/1073741824 ))
|
||||
|
||||
if (( size > space )); then
|
||||
error "Not enough free space in $STORAGE, have $space_gb available but need at least $size_gb." && return 1
|
||||
error "Not enough free space in $STORAGE, have $space_gb GB available but need at least $size_gb GB." && return 1
|
||||
fi
|
||||
|
||||
if [[ "${BOOT_MODE,,}" != "windows_legacy" ]]; then
|
||||
|
@ -1076,47 +973,52 @@ bootWindows() {
|
|||
|
||||
if [ -f "$STORAGE/windows.args" ]; then
|
||||
ARGS=$(<"$STORAGE/windows.args")
|
||||
ARGS="${ARGS//[![:print:]]/}"
|
||||
ARGUMENTS="$ARGS ${ARGUMENTS:-}"
|
||||
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 [ -z "${DISK_TYPE:-}" ]; then
|
||||
DISK_TYPE=$(<"$STORAGE/windows.type")
|
||||
DISK_TYPE="${DISK_TYPE//[![:print:]]/}"
|
||||
fi
|
||||
[ -z "${DISK_TYPE:-}" ] && DISK_TYPE=$(<"$STORAGE/windows.type")
|
||||
fi
|
||||
|
||||
if [ -s "$STORAGE/windows.mode" ] && [ -f "$STORAGE/windows.mode" ]; then
|
||||
BOOT_MODE=$(<"$STORAGE/windows.mode")
|
||||
BOOT_MODE="${BOOT_MODE//[![:print:]]/}"
|
||||
if [ -s "$STORAGE/windows.old" ] && [ -f "$STORAGE/windows.old" ]; then
|
||||
[[ "${PLATFORM,,}" == "x64" ]] && MACHINE=$(<"$STORAGE/windows.old")
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ -s "$STORAGE/windows.old" ] && [ -f "$STORAGE/windows.old" ]; then
|
||||
if [[ "${PLATFORM,,}" == "x64" ]]; then
|
||||
MACHINE=$(<"$STORAGE/windows.old")
|
||||
MACHINE="${MACHINE//[![:print:]]/}"
|
||||
# Migrations
|
||||
|
||||
[[ "${PLATFORM,,}" != "x64" ]] && return 0
|
||||
|
||||
if [ -f "$STORAGE/windows.old" ]; then
|
||||
MACHINE=$(<"$STORAGE/windows.old")
|
||||
[ -z "$MACHINE" ] && MACHINE="q35"
|
||||
BOOT_MODE="windows_legacy"
|
||||
echo "$BOOT_MODE" > "$STORAGE/windows.mode"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local creation="1.10"
|
||||
local minimal="2.14"
|
||||
|
||||
if [ -f "$STORAGE/windows.ver" ]; then
|
||||
creation=$(<"$STORAGE/windows.ver")
|
||||
[[ "${creation}" != *"."* ]] && creation="$minimal"
|
||||
fi
|
||||
|
||||
# Force secure boot on installs created prior to v2.14
|
||||
if (( $(echo "$creation < $minimal" | bc -l) )); then
|
||||
if [[ "${BOOT_MODE,,}" == "windows" ]]; then
|
||||
BOOT_MODE="windows_secure"
|
||||
echo "$BOOT_MODE" > "$STORAGE/windows.mode"
|
||||
if [ -f "$STORAGE/windows.rom" ] && [ ! -f "$STORAGE/$BOOT_MODE.rom" ]; then
|
||||
mv -f "$STORAGE/windows.rom" "$STORAGE/$BOOT_MODE.rom"
|
||||
fi
|
||||
if [ -f "$STORAGE/windows.vars" ] && [ ! -f "$STORAGE/$BOOT_MODE.vars" ]; then
|
||||
mv -f "$STORAGE/windows.vars" "$STORAGE/$BOOT_MODE.vars"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
|
|
365
src/mido.sh
365
src/mido.sh
|
@ -93,7 +93,6 @@ download_windows() {
|
|||
|
||||
# uuidgen: For MacOS (installed by default) and other systems (e.g. with no /proc) that don't have a kernel interface for generating random UUIDs
|
||||
session_id=$(cat /proc/sys/kernel/random/uuid 2> /dev/null || uuidgen --random)
|
||||
session_id="${session_id//[![:print:]]/}"
|
||||
|
||||
# Get product edition ID for latest release of given Windows version
|
||||
# Product edition ID: This specifies both the Windows release (e.g. 22H2) and edition ("multi-edition" is default, either Home/Pro/Edu/etc., we select "Pro" in the answer files) in one number
|
||||
|
@ -209,9 +208,6 @@ download_windows_eval() {
|
|||
"win2022-eval" )
|
||||
enterprise_type="server"
|
||||
windows_version="windows-server-2022" ;;
|
||||
"win2019-hv" )
|
||||
enterprise_type="server"
|
||||
windows_version="hyper-v-server-2019" ;;
|
||||
"win2019-eval" )
|
||||
enterprise_type="server"
|
||||
windows_version="windows-server-2019" ;;
|
||||
|
@ -246,10 +242,10 @@ download_windows_eval() {
|
|||
|
||||
[[ "$DEBUG" == [Yy1]* ]] && echo "Getting download link.."
|
||||
|
||||
filter="https://go.microsoft.com/fwlink/?linkid=[0-9]\+&clcid=0x[0-9a-z]\+&culture=${culture,,}&country=${country,,}"
|
||||
|
||||
if ! echo "$iso_download_page_html" | grep -io "$filter" > /dev/null; then
|
||||
filter="https://go.microsoft.com/fwlink/p/?linkid=[0-9]\+&clcid=0x[0-9a-z]\+&culture=${culture,,}&country=${country,,}"
|
||||
if [[ "$enterprise_type" == "iot" ]]; then
|
||||
filter="https://go.microsoft.com/fwlink/?linkid=[0-9]\+&clcid=0x[0-9a-z]\+&culture=${culture,,}&country=${country^^}"
|
||||
else
|
||||
filter="https://go.microsoft.com/fwlink/p/?LinkID=[0-9]\+&clcid=0x[0-9a-z]\+&culture=${culture,,}&country=${country^^}"
|
||||
fi
|
||||
|
||||
iso_download_links=$(echo "$iso_download_page_html" | grep -io "$filter") || {
|
||||
|
@ -314,7 +310,7 @@ getWindows() {
|
|||
info "$msg" && html "$msg"
|
||||
|
||||
case "${version,,}" in
|
||||
"win2008r2" | "win81${PLATFORM,,}"* | "win11${PLATFORM,,}-enterprise-iot"* | "win11${PLATFORM,,}-enterprise-ltsc"* )
|
||||
"win2008r2" | "win81${PLATFORM,,}-enterprise"* | "win11${PLATFORM,,}-enterprise-iot"* | "win11${PLATFORM,,}-enterprise-ltsc"* )
|
||||
if [[ "${lang,,}" != "en" ]] && [[ "${lang,,}" != "en-"* ]]; then
|
||||
error "No download in the $language language available for $edition!"
|
||||
MIDO_URL="" && return 1
|
||||
|
@ -339,7 +335,7 @@ getWindows() {
|
|||
"win11${PLATFORM,,}-enterprise"* | "win10${PLATFORM,,}-enterprise"* )
|
||||
download_windows_eval "$version" "$lang" "$edition" && return 0
|
||||
;;
|
||||
"win2025-eval" | "win2022-eval" | "win2019-eval" | "win2019-hv" | "win2016-eval" | "win2012r2-eval" )
|
||||
"win2025-eval" | "win2022-eval" | "win2019-eval" | "win2016-eval" | "win2012r2-eval" )
|
||||
download_windows_eval "$version" "$lang" "$edition" && return 0
|
||||
;;
|
||||
"win81${PLATFORM,,}-enterprise"* | "win2008r2" )
|
||||
|
@ -347,10 +343,53 @@ getWindows() {
|
|||
* ) error "Invalid VERSION specified, value \"$version\" is not recognized!" ;;
|
||||
esac
|
||||
|
||||
MIDO_URL=$(getMido "$version" "$lang" "")
|
||||
[ -z "$MIDO_URL" ] && return 1
|
||||
if [[ "${PLATFORM,,}" != "x64" ]]; then
|
||||
MIDO_URL=""
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
if [[ "${lang,,}" != "en" ]] && [[ "${lang,,}" != "en-"* ]]; then
|
||||
MIDO_URL=""
|
||||
return 1
|
||||
fi
|
||||
|
||||
case "${version,,}" in
|
||||
"win81${PLATFORM,,}-enterprise"* )
|
||||
MIDO_URL="https://download.microsoft.com/download/B/9/9/B999286E-0A47-406D-8B3D-5B5AD7373A4A/9600.17050.WINBLUE_REFRESH.140317-1640_X64FRE_ENTERPRISE_EVAL_EN-US-IR3_CENA_X64FREE_EN-US_DV9.ISO"
|
||||
return 0
|
||||
;;
|
||||
"win11${PLATFORM,,}-enterprise-iot"* | "win11${PLATFORM,,}-enterprise-ltsc"* )
|
||||
MIDO_URL="https://software-static.download.prss.microsoft.com/dbazure/888969d5-f34g-4e03-ac9d-1f9786c66749/26100.1.240331-1435.ge_release_CLIENT_IOT_LTSC_EVAL_x64FRE_en-us.iso"
|
||||
return 0
|
||||
;;
|
||||
"win2025-eval" )
|
||||
MIDO_URL="https://software-static.download.prss.microsoft.com/dbazure/888969d5-f34g-4e03-ac9d-1f9786c66749/26100.1.240331-1435.ge_release_SERVER_EVAL_x64FRE_en-us.iso"
|
||||
return 0
|
||||
;;
|
||||
"win2022-eval" )
|
||||
MIDO_URL="https://software-static.download.prss.microsoft.com/sg/download/888969d5-f34g-4e03-ac9d-1f9786c66749/SERVER_EVAL_x64FRE_en-us.iso"
|
||||
return 0
|
||||
;;
|
||||
"win2019-eval" )
|
||||
MIDO_URL="https://software-download.microsoft.com/download/pr/17763.737.190906-2324.rs5_release_svc_refresh_SERVER_EVAL_x64FRE_en-us_1.iso"
|
||||
return 0
|
||||
;;
|
||||
"win2016-eval" )
|
||||
MIDO_URL="https://software-download.microsoft.com/download/pr/Windows_Server_2016_Datacenter_EVAL_en-us_14393_refresh.ISO"
|
||||
return 0
|
||||
;;
|
||||
"win2012r2-eval" )
|
||||
MIDO_URL="https://download.microsoft.com/download/6/2/A/62A76ABB-9990-4EFC-A4FE-C7D698DAEB96/9600.17050.WINBLUE_REFRESH.140317-1640_X64FRE_SERVER_EVAL_EN-US-IR3_SSS_X64FREE_EN-US_DV9.ISO"
|
||||
return 0
|
||||
;;
|
||||
"win2008r2" )
|
||||
MIDO_URL="https://download.microsoft.com/download/4/1/D/41DEA7E0-B30D-4012-A1E3-F24DC03BA1BB/7601.17514.101119-1850_x64fre_server_eval_en-us-GRMSXEVAL_EN_DVD.iso"
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
|
||||
MIDO_URL=""
|
||||
return 1
|
||||
}
|
||||
|
||||
getCatalog() {
|
||||
|
@ -390,6 +429,243 @@ getCatalog() {
|
|||
return 0
|
||||
}
|
||||
|
||||
getMG() {
|
||||
|
||||
local version="$1"
|
||||
local lang="$2"
|
||||
local desc="$3"
|
||||
|
||||
local locale=""
|
||||
local culture=""
|
||||
local language=""
|
||||
local user_agent=""
|
||||
|
||||
user_agent=$(get_agent)
|
||||
language=$(getLanguage "$lang" "desc")
|
||||
culture=$(getLanguage "$lang" "culture")
|
||||
|
||||
local msg="Requesting download link from massgrave.dev..."
|
||||
info "$msg" && html "$msg"
|
||||
|
||||
local pattern=""
|
||||
local locale="${culture,,}"
|
||||
local platform="${PLATFORM,,}"
|
||||
local url="https://massgrave.dev/"
|
||||
|
||||
if [[ "${PLATFORM,,}" != "arm64" ]]; then
|
||||
|
||||
case "${version,,}" in
|
||||
"win11${PLATFORM,,}" )
|
||||
url+="windows_11_links"
|
||||
pattern="consumer"
|
||||
;;
|
||||
"win11${PLATFORM,,}-enterprise" | "win11${PLATFORM,,}-enterprise-eval" )
|
||||
url+="windows_11_links"
|
||||
pattern="business"
|
||||
;;
|
||||
"win11${PLATFORM,,}-ltsc" | "win11${PLATFORM,,}-enterprise-ltsc-eval" )
|
||||
url+="windows_ltsc_links"
|
||||
pattern="11_enterprise_ltsc"
|
||||
;;
|
||||
"win11${PLATFORM,,}-iot" | "win11${PLATFORM,,}-enterprise-iot-eval" )
|
||||
url+="windows_ltsc_links"
|
||||
pattern="11_iot"
|
||||
;;
|
||||
"win10${PLATFORM,,}" )
|
||||
url+="windows_10_links"
|
||||
pattern="consumer"
|
||||
;;
|
||||
"win10${PLATFORM,,}-enterprise" | "win10${PLATFORM,,}-enterprise-eval" )
|
||||
url+="windows_10_links"
|
||||
pattern="business"
|
||||
;;
|
||||
"win10${PLATFORM,,}-ltsc" | "win10${PLATFORM,,}-enterprise-ltsc-eval" )
|
||||
url+="windows_ltsc_links"
|
||||
pattern="10_enterprise_ltsc"
|
||||
;;
|
||||
"win10${PLATFORM,,}-iot" | "win10${PLATFORM,,}-enterprise-iot-eval" )
|
||||
url+="windows_ltsc_links"
|
||||
pattern="10_iot"
|
||||
;;
|
||||
"win81${PLATFORM,,}-enterprise" | "win81${PLATFORM,,}-enterprise-eval" )
|
||||
url+="windows_8.1_links"
|
||||
pattern="8.1_enterprise"
|
||||
locale=$(getLanguage "$lang" "code")
|
||||
[[ "$locale" == "sr" ]] && locale="sr-latn"
|
||||
;;
|
||||
"win2025" | "win2025-eval" )
|
||||
url+="windows_server_links"
|
||||
pattern="server_2025"
|
||||
;;
|
||||
"win2022" | "win2022-eval" )
|
||||
url+="windows_server_links"
|
||||
pattern="server_2022"
|
||||
;;
|
||||
"win2019" | "win2019-eval" )
|
||||
url+="windows_server_links"
|
||||
pattern="server_2019"
|
||||
;;
|
||||
"win2016" | "win2016-eval" )
|
||||
url+="windows_server_links"
|
||||
pattern="server_2016"
|
||||
locale=$(getLanguage "$lang" "code")
|
||||
[[ "$locale" == "hk" ]] && locale="ct"
|
||||
[[ "$locale" == "tw" ]] && locale="ct"
|
||||
;;
|
||||
"win2012r2" | "win2012r2-eval" )
|
||||
url+="windows_server_links"
|
||||
pattern="server_2012_r2"
|
||||
locale=$(getLanguage "$lang" "code")
|
||||
;;
|
||||
"win2008r2" | "win2008r2-eval" )
|
||||
url+="windows_server_links"
|
||||
pattern="server_2008_r2"
|
||||
locale=$(getLanguage "$lang" "code")
|
||||
;;
|
||||
"win7x64" | "win7x64-enterprise" )
|
||||
url+="windows_7_links"
|
||||
pattern="enterprise"
|
||||
locale=$(getLanguage "$lang" "code")
|
||||
;;
|
||||
"win7x64-ultimate" )
|
||||
url+="windows_7_links"
|
||||
pattern="ultimate"
|
||||
locale=$(getLanguage "$lang" "code")
|
||||
;;
|
||||
"win7x86" | "win7x86-enterprise" )
|
||||
platform="x86"
|
||||
url+="windows_7_links"
|
||||
pattern="enterprise"
|
||||
locale=$(getLanguage "$lang" "code")
|
||||
;;
|
||||
"win7x86-ultimate" )
|
||||
platform="x86"
|
||||
url+="windows_7_links"
|
||||
pattern="ultimate"
|
||||
locale=$(getLanguage "$lang" "code")
|
||||
;;
|
||||
"winvistax64" | "winvistax64-enterprise" )
|
||||
url+="windows_vista_links"
|
||||
pattern="enterprise"
|
||||
locale=$(getLanguage "$lang" "code")
|
||||
;;
|
||||
"winvistax64-ultimate" )
|
||||
url+="windows_vista_links"
|
||||
pattern="sp2"
|
||||
locale=$(getLanguage "$lang" "code")
|
||||
;;
|
||||
"winvistax86" | "winvistax86-enterprise" )
|
||||
platform="x86"
|
||||
url+="windows_vista_links"
|
||||
pattern="enterprise"
|
||||
locale=$(getLanguage "$lang" "code")
|
||||
;;
|
||||
"winvistax86-ultimate" )
|
||||
platform="x86"
|
||||
url+="windows_vista_links"
|
||||
pattern="sp2"
|
||||
locale=$(getLanguage "$lang" "code")
|
||||
;;
|
||||
"winxpx86" )
|
||||
platform="x86"
|
||||
url+="windows_xp_links"
|
||||
pattern="xp"
|
||||
locale=$(getLanguage "$lang" "code")
|
||||
[[ "$locale" == "pt" ]] && locale="pt-br"
|
||||
[[ "$locale" == "pp" ]] && locale="pt-pt"
|
||||
[[ "$locale" == "cn" ]] && locale="zh-hans"
|
||||
[[ "$locale" == "hk" ]] && locale="zh-hk"
|
||||
[[ "$locale" == "tw" ]] && locale="zh-tw"
|
||||
;;
|
||||
"winxpx64" )
|
||||
url+="windows_xp_links"
|
||||
pattern="xp"
|
||||
locale=$(getLanguage "$lang" "code")
|
||||
;;
|
||||
esac
|
||||
|
||||
else
|
||||
|
||||
case "${version,,}" in
|
||||
"win11${PLATFORM,,}" | "win11${PLATFORM,,}-enterprise" | "win11${PLATFORM,,}-enterprise-eval" )
|
||||
url+="windows_arm_links"
|
||||
pattern="11_business"
|
||||
;;
|
||||
"win11${PLATFORM,,}-ltsc" | "win11${PLATFORM,,}-enterprise-ltsc-eval" )
|
||||
url+="windows_arm_links"
|
||||
pattern="11_iot_enterprise_ltsc"
|
||||
;;
|
||||
"win10${PLATFORM,,}" | "win10${PLATFORM,,}-enterprise" | "win10${PLATFORM,,}-enterprise-eval" )
|
||||
url+="windows_arm_links"
|
||||
pattern="Pro_10"
|
||||
locale="$language"
|
||||
[[ "$locale" == "Chinese" ]] && locale="ChnSimp"
|
||||
[[ "$locale" == "Chinese HK" ]] && locale="ChnTrad"
|
||||
[[ "$locale" == "Chinese TW" ]] && locale="ChnTrad"
|
||||
;;
|
||||
"win10${PLATFORM,,}-ltsc" | "win10${PLATFORM,,}-enterprise-ltsc-eval" )
|
||||
url+="windows_arm_links"
|
||||
pattern="10_iot_enterprise_ltsc"
|
||||
;;
|
||||
esac
|
||||
|
||||
fi
|
||||
|
||||
local body=""
|
||||
|
||||
[[ "$DEBUG" == [Yy1]* ]] && echo "Parsing product page: ${url}"
|
||||
body=$(curl --silent --max-time 30 --user-agent "$user_agent" --location --max-filesize 1M --fail --proto =https --tlsv1.2 --http1.1 -- "$url") || {
|
||||
handle_curl_error "$?" "Massgrave"
|
||||
return $?
|
||||
}
|
||||
|
||||
local list=""
|
||||
list=$(echo "$body" | xmllint --html --nonet --xpath "//a[contains(text(), '.iso')]" - 2>/dev/null)
|
||||
|
||||
local result=""
|
||||
result=$(echo "$list" | grep -i "${platform}" | grep "${pattern}" | grep -i -m 1 "${locale,,}_")
|
||||
result=$(echo "$result" | sed -r 's/.*href="([^"]+).*/\1/g')
|
||||
local page="$result"
|
||||
|
||||
if [ -z "$page" ]; then
|
||||
if [[ "${lang,,}" != "en" ]] && [[ "${lang,,}" != "en-"* ]]; then
|
||||
error "No download in the $language language available for $desc!"
|
||||
else
|
||||
error "Failed to parse download link for $desc! Please report this at $SUPPORT/issues."
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
|
||||
[[ "$DEBUG" == [Yy1]* ]] && echo "Parsing download page: ${page}"
|
||||
result=$(curl --silent --max-time 30 --request GET --user-agent "$user_agent" --referer "$url" --head --proto =https --tlsv1.2 --http1.1 -- "$page") || {
|
||||
handle_curl_error "$?" "Massgrave"
|
||||
return $?
|
||||
}
|
||||
|
||||
if [[ "${result,,}" == *"content-type: text"* ]]; then
|
||||
body=$(curl --silent --max-time 30 --user-agent "$user_agent" --referer "$url" --location --max-filesize 1M --fail --proto =https --tlsv1.2 --http1.1 -- "$page") || {
|
||||
handle_curl_error "$?" "Massgrave"
|
||||
return $?
|
||||
}
|
||||
|
||||
list=$(echo "$body" | xmllint --html --nonet --xpath "//a[contains(@href, '.iso')]" - 2>/dev/null)
|
||||
list=$(echo "$list" | sed -r 's/.*href="([^"]+).*/\1/g')
|
||||
page=$(echo "$list" | sed 's/&/\&/g;')
|
||||
|
||||
if [ -z "$page" ]; then
|
||||
if [[ "${lang,,}" != "en" ]] && [[ "${lang,,}" != "en-"* ]]; then
|
||||
error "No download in the $language language available for $desc!"
|
||||
else
|
||||
error "Failed to parse download link for $desc! Please report this at $SUPPORT/issues."
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
MG_URL="$page"
|
||||
return 0
|
||||
}
|
||||
|
||||
getESD() {
|
||||
|
||||
local dir="$1"
|
||||
|
@ -472,18 +748,6 @@ getESD() {
|
|||
return 0
|
||||
}
|
||||
|
||||
isCompressed() {
|
||||
|
||||
local file="$1"
|
||||
|
||||
case "${file,,}" in
|
||||
*".7z" | *".zip" | *".rar" | *".lzma" | *".bz" | *".bz2" )
|
||||
return 0 ;;
|
||||
esac
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
verifyFile() {
|
||||
|
||||
local iso="$1"
|
||||
|
@ -492,9 +756,7 @@ verifyFile() {
|
|||
local check="$4"
|
||||
|
||||
if [ -n "$size" ] && [[ "$total" != "$size" ]] && [[ "$size" != "0" ]]; then
|
||||
if [[ "$VERIFY" == [Yy1]* ]] || [[ "$DEBUG" == [Yy1]* ]]; then
|
||||
warn "The downloaded file has a different size ( $total bytes) than expected ( $size bytes). Please report this at $SUPPORT/issues"
|
||||
fi
|
||||
warn "The downloaded file has an unexpected size: $total bytes, while expected value was: $size bytes. Please report this at $SUPPORT/issues"
|
||||
fi
|
||||
|
||||
local hash=""
|
||||
|
@ -517,7 +779,7 @@ verifyFile() {
|
|||
info "Succesfully verified ISO!" && return 0
|
||||
fi
|
||||
|
||||
error "The downloaded file has an unknown $algo checksum: $hash , as the expected value was: $check. Please report this at $SUPPORT/issues"
|
||||
error "The downloaded file has an invalid $algo checksum: $hash , while expected value was: $check. Please report this at $SUPPORT/issues"
|
||||
return 1
|
||||
}
|
||||
|
||||
|
@ -529,17 +791,14 @@ downloadFile() {
|
|||
local size="$4"
|
||||
local lang="$5"
|
||||
local desc="$6"
|
||||
local msg="Downloading $desc"
|
||||
local rc total total_gb progress domain dots agent space folder
|
||||
local rc total progress domain dots space folder
|
||||
|
||||
rm -f "$iso"
|
||||
agent=$(get_agent)
|
||||
|
||||
if [ -n "$size" ] && [[ "$size" != "0" ]]; then
|
||||
folder=$(dirname -- "$iso")
|
||||
space=$(df --output=avail -B 1 "$folder" | tail -n 1)
|
||||
total_gb=$(formatBytes "$space")
|
||||
(( size > space )) && error "Not enough free space to download file, only $total_gb left!" && return 1
|
||||
(( size > space )) && error "Not enough free space left to download file!" && return 1
|
||||
fi
|
||||
|
||||
# Check if running with interactive TTY or redirected to docker log
|
||||
|
@ -549,8 +808,8 @@ downloadFile() {
|
|||
progress="--progress=dot:giga"
|
||||
fi
|
||||
|
||||
local msg="Downloading $desc"
|
||||
html "$msg..."
|
||||
/run/progress.sh "$iso" "$size" "$msg ([P])..." &
|
||||
|
||||
domain=$(echo "$url" | awk -F/ '{print $3}')
|
||||
dots=$(echo "$domain" | tr -cd '.' | wc -c)
|
||||
|
@ -561,26 +820,25 @@ downloadFile() {
|
|||
fi
|
||||
|
||||
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"
|
||||
|
||||
if (( rc == 0 )) && [ -f "$iso" ]; then
|
||||
total=$(stat -c%s "$iso")
|
||||
total_gb=$(formatBytes "$total")
|
||||
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 bytes?). Please report this at $SUPPORT/issues." && return 1
|
||||
fi
|
||||
verifyFile "$iso" "$size" "$total" "$sum" || return 1
|
||||
isCompressed "$url" && UNPACK="Y"
|
||||
html "Download finished successfully..." && return 0
|
||||
fi
|
||||
|
||||
msg="Failed to download $url"
|
||||
(( rc == 3 )) && error "$msg , cannot write file (disk full?)" && 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!" && return 1
|
||||
|
||||
error "$msg , reason: $rc"
|
||||
return 1
|
||||
|
@ -598,14 +856,12 @@ downloadImage() {
|
|||
local msg="Will retry after $delay seconds..."
|
||||
|
||||
if [[ "${version,,}" == "http"* ]]; then
|
||||
|
||||
base=$(basename "$iso")
|
||||
desc=$(fromFile "$base")
|
||||
downloadFile "$iso" "$version" "" "" "" "$desc" && return 0
|
||||
info "$msg" && html "$msg" && sleep "$delay"
|
||||
downloadFile "$iso" "$version" "" "" "" "$desc" && return 0
|
||||
rm -f "$iso"
|
||||
|
||||
return 1
|
||||
fi
|
||||
|
||||
|
@ -694,6 +950,31 @@ downloadImage() {
|
|||
|
||||
done
|
||||
|
||||
if isMG "$version" "$lang"; then
|
||||
|
||||
if [[ "$tried" != "n" ]]; then
|
||||
info "Failed to download $desc, will try a diferent method now..."
|
||||
fi
|
||||
|
||||
tried="y"
|
||||
success="n"
|
||||
|
||||
if getMG "$version" "$lang" "$desc"; then
|
||||
success="y"
|
||||
else
|
||||
info "$msg" && html "$msg" && sleep "$delay"
|
||||
getMG "$version" "$lang" "$desc" && success="y"
|
||||
fi
|
||||
|
||||
if [[ "$success" == "y" ]]; then
|
||||
downloadFile "$iso" "$MG_URL" "" "" "$lang" "$desc" && return 0
|
||||
info "$msg" && html "$msg" && sleep "$delay"
|
||||
downloadFile "$iso" "$MG_URL" "" "" "$lang" "$desc" && return 0
|
||||
rm -f "$iso"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ boot() {
|
|||
|
||||
if [ -s "$QEMU_PTY" ]; then
|
||||
if [ "$(stat -c%s "$QEMU_PTY")" -gt 7 ]; then
|
||||
info "Windows started succesfully, visit http://127.0.0.1:8006/ to view the screen..."
|
||||
info "Windows started succesfully, visit http://localhost:8006/ to view the screen..."
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
|
26
src/samba.sh
26
src/samba.sh
|
@ -14,21 +14,16 @@ if [[ "$DHCP" == [Yy1]* ]]; then
|
|||
interface="$VM_NET_DEV"
|
||||
fi
|
||||
|
||||
if [[ "${NETWORK,,}" == "user"* ]]; then
|
||||
interface="127.0.0.1"
|
||||
fi
|
||||
|
||||
addShare() {
|
||||
local dir="$1"
|
||||
local name="$2"
|
||||
local comment="$3"
|
||||
|
||||
mkdir -p "$dir" || return 1
|
||||
ls -A "$dir" >/dev/null 2>&1 || return 1
|
||||
|
||||
if [ -z "$(ls -A "$dir")" ]; then
|
||||
|
||||
chmod 777 "$dir" || return 1
|
||||
chmod 777 "$dir"
|
||||
|
||||
{ echo "--------------------------------------------------------"
|
||||
echo " $APP for Docker v$(</run/version)..."
|
||||
|
@ -92,17 +87,10 @@ share="/data"
|
|||
[ ! -d "$share" ] && [ -d "/shared" ] && share="/shared"
|
||||
[ ! -d "$share" ] && [ -d "$STORAGE/shared" ] && share="$STORAGE/shared"
|
||||
|
||||
if ! addShare "$share" "Data" "Shared"; then
|
||||
error "Failed to add shared folder '$share'. Please check its permissions." && return 0
|
||||
fi
|
||||
addShare "$share" "Data" "Shared" || error "Failed to create shared folder!"
|
||||
|
||||
if [ -d "/data2" ]; then
|
||||
addShare "/data2" "Data2" "Shared" || error "Failed to add shared folder '/data2'. Please check its permissions."
|
||||
fi
|
||||
|
||||
if [ -d "/data3" ]; then
|
||||
addShare "/data3" "Data3" "Shared" || error "Failed to add shared folder '/data3'. Please check its permissions."
|
||||
fi
|
||||
[ -d "/data2" ] && addShare "/data2" "Data2" "Shared"
|
||||
[ -d "/data3" ] && addShare "/data3" "Data3" "Shared"
|
||||
|
||||
IFS=',' read -r -a dirs <<< "${SHARES:-}"
|
||||
for dir in "${dirs[@]}"; do
|
||||
|
@ -111,16 +99,12 @@ for dir in "${dirs[@]}"; do
|
|||
addShare "$dir" "$dir_name" "Shared $dir_name" || error "Failed to create shared folder for $dir!"
|
||||
done
|
||||
|
||||
# Fix Samba permissions
|
||||
[ -d /run/samba/msg.lock ] && chmod -R 0755 /run/samba/msg.lock
|
||||
[ -d /var/log/samba/cores ] && chmod -R 0700 /var/log/samba/cores
|
||||
[ -d /var/cache/samba/msg.lock ] && chmod -R 0755 /var/cache/samba/msg.lock
|
||||
|
||||
if ! smbd; then
|
||||
error "Samba daemon failed to start!"
|
||||
smbd -i --debug-stdout || true
|
||||
fi
|
||||
|
||||
# Enable Web Service Discovery
|
||||
wsdd -i "$interface" -p -n "$hostname" &
|
||||
echo "$!" > /var/run/wsdd.pid
|
||||
|
||||
|
|
Loading…
Reference in a new issue