把 Order 3 的 net user 命令直接寫成 net user User,省掉「先建小寫 user 再 Rename-LocalUser 改成大寫 User」這個迂迴。Setup.ps1 的 rename-hide-accounts 段同時改名為 hide-admin-account,內容只剩設 SpecialAccounts\\UserList\\Admin=0 這一行——隱藏 Admin 仍然由 Setup.ps1 負責。 文件全部同步:DEPLOY/QUICKSTART/SUMMARY/README/CLAUDE 把「先建小寫再改名」的 bulletproof 解釋與相關段名都拿掉。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
226 lines
14 KiB
Markdown
226 lines
14 KiB
Markdown
# DEPLOY — 本機 Ventoy USB 部署紀錄
|
||
|
||
這份文件記錄本機 Ventoy USB(`/Volumes/Ventoy`)上 `unattend.xml` 與 `ventoy.json` 的實際部署方式,供下次換機、換 ISO、或刷新 USB 內容時照著做。
|
||
|
||
概念與疑難排解請看 `QUICKSTART.md`;這份只寫「這顆 USB 目前的樣子」和「怎麼重建它」。
|
||
|
||
---
|
||
|
||
## 目前 USB 內容
|
||
|
||
掛載點:`/Volumes/Ventoy`
|
||
|
||
USB 根目錄兩個 ISO:
|
||
|
||
| 檔名 | 用途 |
|
||
|---|---|
|
||
| `Windows 11_25H2_Chinese_Traditional_x64v1.iso` | Win11 25H2 繁中 x64 |
|
||
| `Windows 10_22H2_Chinese_Traditional_x64v1.iso` | Win10 22H2 繁中 x64 |
|
||
|
||
注入檔案佈局:
|
||
|
||
```
|
||
/Volumes/Ventoy/
|
||
├── Windows 11_25H2_Chinese_Traditional_x64v1.iso
|
||
├── Windows 10_22H2_Chinese_Traditional_x64v1.iso
|
||
└── ventoy/
|
||
├── ventoy.json ← 對應兩個 ISO,都指向同一份 template
|
||
└── script/
|
||
├── unattend.xml ← 與 repo 根目錄的 unattend.xml 相同
|
||
└── Setup.ps1 ← 與 repo 根目錄的 Setup.ps1 相同(首次登入自動複製到 C:\Scripts\)
|
||
```
|
||
|
||
`Setup.ps1` **必須跟 unattend.xml 放在同一個 `/ventoy/script/` 目錄下**。`unattend.xml` 的 `FirstLogonCommands` Order 4 會掃所有掛載的磁碟,找到第一個有 `\ventoy\script\Setup.ps1` 的就複製到 `C:\Scripts\Setup.ps1`,所以這個路徑寫死,不能搬。
|
||
|
||
---
|
||
|
||
## USB 上的 `ventoy.json`
|
||
|
||
**與 repo 根目錄的 `ventoy.json` 不同** —— repo 版本保留通用示範路徑 `/Win11.iso`,USB 版本則綁定本機這兩個 ISO 的實際檔名,並帶了 `menu_tip` 讓 Ventoy 選單上顯示每個 ISO 會做什麼:
|
||
|
||
```json
|
||
{
|
||
"auto_install": [
|
||
{
|
||
"image": "/Windows 11_25H2_Chinese_Traditional_x64v1.iso",
|
||
"template": "/ventoy/script/unattend.xml"
|
||
},
|
||
{
|
||
"image": "/Windows 10_22H2_Chinese_Traditional_x64v1.iso",
|
||
"template": "/ventoy/script/unattend.xml"
|
||
}
|
||
],
|
||
"menu_tip": {
|
||
"left": "10%",
|
||
"top": "81%",
|
||
"color": "white",
|
||
"tips": [
|
||
{
|
||
"image": "/Windows 11_25H2_Chinese_Traditional_x64v1.iso",
|
||
"tip": "Win11 25H2 自動安裝|清碟→Admin/P@ssw0rd!→裝 Telegram→重開(UEFI+GPT,會清空目標碟)"
|
||
},
|
||
{
|
||
"image": "/Windows 10_22H2_Chinese_Traditional_x64v1.iso",
|
||
"tip": "Win10 22H2 自動安裝|清碟→Admin/P@ssw0rd!→裝 Telegram→重開(UEFI+GPT,會清空目標碟)"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
- `image` 路徑以 `/` 開頭,相對 USB 根目錄,**完整檔名必須跟 USB 上一字不差**(含空格、底線、版本號)。`menu_tip.tips[].image` 也要跟著同步,否則光標移到 ISO 上不會跳 tip。
|
||
- 兩個 ISO 共用同一份 `unattend.xml`;該 XML 目前以 UEFI+GPT 全碟清除方式部署,兩個版本皆適用。
|
||
- 若日後只想其中一個 ISO 走自動安裝、另一個保留互動安裝,刪掉 `auto_install` 對應的物件即可;Ventoy 找不到對應 `image` 時會走一般安裝流程(`menu_tip` 那條保留沒關係,不跳 auto install)。
|
||
- `menu_tip.tip` 是**單行**的;[Ventoy 文件](https://www.ventoy.net/en/plugin_menutip.html)明確說不支援 `\n`,換行會被一律忽略。要多行提示只能靠縮寫或另加 plugin(如 `menu_alias`)。
|
||
|
||
---
|
||
|
||
## 重新部署步驟(macOS)
|
||
|
||
插入 Ventoy USB 後:
|
||
|
||
```bash
|
||
# 從 repo 根目錄執行
|
||
mkdir -p /Volumes/Ventoy/ventoy/script
|
||
cp unattend.xml /Volumes/Ventoy/ventoy/script/unattend.xml
|
||
cp Setup.ps1 /Volumes/Ventoy/ventoy/script/Setup.ps1
|
||
|
||
# 寫 ventoy.json(見上一節內容,或直接手編)
|
||
# 注意:image 檔名必須跟 USB 上的 ISO 檔名完全一致
|
||
|
||
# 清掉 macOS 複製過程產生的 ._ AppleDouble metadata
|
||
dot_clean /Volumes/Ventoy/ventoy
|
||
```
|
||
|
||
驗證:
|
||
|
||
```bash
|
||
ls /Volumes/Ventoy/ventoy/ /Volumes/Ventoy/ventoy/script/
|
||
diff unattend.xml /Volumes/Ventoy/ventoy/script/unattend.xml # 應無輸出
|
||
diff Setup.ps1 /Volumes/Ventoy/ventoy/script/Setup.ps1 # 應無輸出
|
||
cat /Volumes/Ventoy/ventoy/ventoy.json
|
||
```
|
||
|
||
**改 `Setup.ps1` 後沒重新 `cp` 是部署最常見的失誤**:FirstLogonCommands 從 USB 讀的是 `/ventoy/script/Setup.ps1` 那份,repo 裡改了不會自己同步上去。每次調 Setup.ps1 都要記得跑 `cp Setup.ps1 /Volumes/Ventoy/ventoy/script/Setup.ps1` 再 `dot_clean`。
|
||
|
||
---
|
||
|
||
## 換 ISO 時要改什麼
|
||
|
||
1. 把新 ISO 丟到 USB 根目錄。
|
||
2. 編輯 `/Volumes/Ventoy/ventoy/ventoy.json`,把對應條目的 `image` 換成新檔名(或新增一條)。
|
||
3. **不用**動 `/Volumes/Ventoy/ventoy/script/unattend.xml` 與 `Setup.ps1`,除非要改 Windows 版本特有設定。
|
||
4. 若 repo 裡的 `unattend.xml` 或 `Setup.ps1` 有更新,重跑一次 `cp` 與 `dot_clean` 即可。
|
||
|
||
---
|
||
|
||
## 部署後動作(FirstLogonCommands 做了什麼)
|
||
|
||
目標機首次登入 `Admin` 帳號時,下列動作會按 `Order` 依序執行(全部跑完才 reboot):
|
||
|
||
| Order | 動作 | 需要網路? |
|
||
|---|---|---|
|
||
| 1 | `net accounts /maxpwage:unlimited`(密碼永不過期) | 否 |
|
||
| 2 | `Rename-Computer` 把主機名改成 `PC-XXXXX`(重開後生效) | 否 |
|
||
| 3 | `net user User 1234 /add`+`/logonpasswordchg:yes`(建立一般使用者 `User`,首次登入強制改密) | 否 |
|
||
| 4 | 掃磁碟找 `\ventoy\script\Setup.ps1` 並複製到 `C:\Scripts\Setup.ps1`(log: `firstlogon-copysetup.log`) | 否(從 Ventoy USB 讀) |
|
||
| 5 | `powershell -File C:\Scripts\Setup.ps1`(13 段 post-install,見下節,log: `setup.log`) | 大部分 **是** |
|
||
| 6 | `shutdown /r /t 5` 重開機 | 否 |
|
||
|
||
Order 4/5 是改版重點:把原本散在 `FirstLogonCommands` 裡的 OpenSSH / Telegram / RemoveWindowsAI 三條搬進 `Setup.ps1`,並補上 10 個新動作。
|
||
|
||
### `Setup.ps1` 做了什麼(13 段,按執行順序)
|
||
|
||
每段都用 `Section` 包裝,會把 `=== <name> START/DONE/ERR ===` 寫到 `C:\Windows\Temp\setup.log`,可以照名字逐段排查。
|
||
|
||
**Phase 1(不需網路、本機設定):**
|
||
|
||
| 段名 | 在做什麼 |
|
||
|---|---|
|
||
| `firewall-ssh-22` | 建 `SSH TCP 22 (Allow Inbound)` 防火牆規則,三個 profile 都啟用 |
|
||
| `rdp-enable-3389` | `fDenyTSConnections=0`、`UserAuthentication=1`、啟用 `Remote Desktop` 防火牆群組 |
|
||
| `icmp-echo-allow` | 允許 ICMPv4 Echo Request inbound(讓外部 ping 得到) |
|
||
| `winrm-enable` | `Enable-PSRemoting`+`winrm quickconfig`+`Basic`/`AllowUnencrypted=true`+`TrustedHosts=*` |
|
||
| `onedrive-remove` | 殺 OneDrive process、跑兩處 `OneDriveSetup.exe /uninstall`、清啟動鍵與 CLSID、刪殘留資料夾 |
|
||
| `cortana-websearch-off` | `AllowCortana=0`、`DisableWebSearch=1`、`ConnectedSearchUseWeb=0`、`DisableSearchBoxSuggestions=1` |
|
||
| `apply-ui-ime-default-profile` | `reg load` Default profile NTUSER.DAT,寫入:顯示副檔名/隱藏檔、工作列靠左、Dark mode、隱藏搜尋框、停 Spotlight、英數鍵盤排第一+注音排第二、CHT 預設英數模式、停切換 Hotkey |
|
||
| `hide-admin-account` | `SpecialAccounts\UserList\Admin=0`(從登入畫面隱藏 Admin;帳號仍存在仍可登入) |
|
||
|
||
**Phase 2(需網路、最多等 60 秒):**
|
||
|
||
| 段名 | 在做什麼 |
|
||
|---|---|
|
||
| `wait-network` | 最多 30 回合×2 秒等 ICMP 通到 8.8.8.8 |
|
||
| `openssh-server-install` | `Add-WindowsCapability OpenSSH.Server`+`Set-Service sshd Automatic`+`Start-Service sshd` |
|
||
| `kms-activate` | 依序試 `$InternalKmsServers` → `$PublicKmsServers`(kms.digiboy.ir 等),跑 `slmgr /skms`+`/ato`,遇到第一個 `successful/成功` 就跳出 |
|
||
| `winget-install-chrome` | `winget install Google.Chrome --silent --scope machine`(Win10 沒裝 App Installer 會 skip) |
|
||
| `remove-windows-ai` | `irm https://raw.githubusercontent.com/zoicware/RemoveWindowsAI/main/RemoveWindowsAi.ps1` 後 `& -nonInteractive -AllOptions -EnableLogging` |
|
||
| `win11debloat` | 下載 [Raphire/Win11Debloat](https://github.com/Raphire/Win11Debloat) `master.zip`、解壓、寫出 `unattend-config.json`(清單與 `windows-remote-toolkit/config/win11debloat-config.json` 同步)、跑 `Win11Debloat.ps1 -Silent -Config ... -NoRestartExplorer` |
|
||
| `remove-uwp-apps` | 依 `$UwpRemoveList`(22 個 AppxPackage:BingNews/BingWeather/Xbox*/MSTeams/Photos/...)逐個 `Remove-AppxPackage -AllUsers` 與 `Remove-AppxProvisionedPackage` |
|
||
| `install-telegram` | 下載 `https://telegram.org/dl/desktop/win64` 跑 `/VERYSILENT /SUPPRESSMSGBOXES /NORESTART` |
|
||
| `cleanup-unattend-files` | 刪掉 `C:\Windows\Panther\unattend.xml` 與 `C:\Windows\Panther\Unattend\unattend.xml`(含明碼密碼) |
|
||
|
||
### `User` 帳號
|
||
|
||
- **用途**:給使用者日常使用,和部署用的管理員 `Admin` 分開。
|
||
- **建立**:`unattend.xml` Order 3 直接 `net user User 1234 /add`(首字大寫一次到位,不在 Setup.ps1 改名)。
|
||
- **權限**:一般 `Users` 群組(非 Administrators)。需要管理員權限時走 UAC(用 `Admin/P@ssw0rd!`)。
|
||
- **首次登入強制改密**:`/logonpasswordchg:yes` 會在下次登入時跳「密碼必須變更」。可以改成複雜密碼。
|
||
- **如果 `net user` 因為 Windows 密碼政策拒絕 `1234`**:Order 3 會失敗但不會擋後面,手動於 PowerShell 以 `New-LocalUser`+更寬的密碼重跑。
|
||
|
||
### Order 4 的磁碟掃描沒找到 Setup.ps1 怎麼辦
|
||
|
||
Order 4 會逐個檢查所有掛載中的 FileSystem PSDrive,找 `\ventoy\script\Setup.ps1`。沒找到就寫 `NOT FOUND` 到 `C:\Windows\Temp\firstlogon-copysetup.log`,Order 5 接著用 `if exist` 判斷,找不到就寫 `SETUP_NOT_FOUND` 到 `firstlogon-runsetup.log` 然後跳過。原因通常是:
|
||
|
||
| 現象 | 原因 | 對策 |
|
||
|---|---|---|
|
||
| `NOT FOUND` | Ventoy USB 在 OOBE 完成前被拔掉 | 別拔,等 reboot 後再拔 |
|
||
| `NOT FOUND` | `Setup.ps1` 沒 cp 到 `/Volumes/Ventoy/ventoy/script/` | 重新 `cp` + `dot_clean` 後再插上重裝 |
|
||
| 找到但 Order 5 報 `Cannot run script ... not digitally signed` | 機器 ExecutionPolicy 是 Restricted | 不會發生,Order 5 用 `-ExecutionPolicy Bypass` 強蓋 |
|
||
| 找到了但 Setup.ps1 早早 ERR | 看 `C:\Windows\Temp\setup.log` 的 `=== <name> ERR ===` 行 | 對照上面的段名表逐段重跑 |
|
||
|
||
### 排查 Setup.ps1 失敗
|
||
|
||
```powershell
|
||
notepad C:\Windows\Temp\firstlogon-copysetup.log # Order 4:USB 掃描結果
|
||
notepad C:\Windows\Temp\firstlogon-runsetup.log # Order 5:找不到 Setup.ps1 才會有
|
||
notepad C:\Windows\Temp\setup.log # Setup.ps1 主 log
|
||
```
|
||
|
||
`setup.log` 每段都有 `=== <name> START === ... === <name> DONE === ` 或 `=== <name> ERR: <msg> ===`。失敗段可以登入 `Admin` 後手動:
|
||
|
||
```powershell
|
||
powershell -ExecutionPolicy Bypass -File C:\Scripts\Setup.ps1
|
||
```
|
||
|
||
整支重跑(每段都是冪等的);或只挑某段:把 `Setup.ps1` 開起來,把那段 `Section '...'` 區塊的內容貼進 PowerShell 視窗即可。
|
||
|
||
### RemoveWindowsAI 補充
|
||
|
||
- **在做什麼**:跑 [zoicware/RemoveWindowsAI](https://github.com/zoicware/RemoveWindowsAI) 的 `RemoveWindowsAi.ps1`,一次把 Copilot(系統+Edge+Office)、Recall+排程任務、Input Insights、AI Fabric、Click to Do、Paint 實驗、Voice Access、Gaming Copilot、Notepad Rewrite、Photos AI 等 AI 元件全數關掉或移除(AppX、CBS、Registry、Group Policy 都會動)。
|
||
- **參數**:`-nonInteractive`(不跳互動選單)+`-AllOptions`(全部選項都跑)+`-EnableLogging`(讓腳本自己也寫 log)。
|
||
- **執行時間**:視目標機速度,通常 30 秒–3 分鐘。移除 CBS package 那段最慢。
|
||
- **抓的是 `main` 分支**:每次部署可能拿到不同版本。要鎖定版本就把 `Setup.ps1` 中對應 URL 的 `/main/` 換成 commit SHA。
|
||
- **可逆性**:腳本本身有 `-revertMode` 與 `-backupMode`,要還原的話可以登入後手動以 `-revertMode` 重跑;但 `-AllOptions` 跑完有些 CBS package 已被刪,`-revertMode` 不一定救得回,需要搭配 `-RunWinUpdateRepair` 從 Windows Update 重取。
|
||
- **風險面**:移除「Nonremovable」AppX、刪 CBS package 屬於侵入性操作,可能導致未來 Windows Update 失敗或特定功能殘缺。部署前建議先在 VM 跑過一次。
|
||
|
||
### Telegram 補充
|
||
|
||
- **要有網路**:OOBE 裡 `SkipMachineOOBE=true` 跳過了網路設定精靈,所以目標機必須有 Ethernet+DHCP,或本身已記住 Wi-Fi。
|
||
- **網路等待上限 60 秒**:`Setup.ps1` 開頭的 `wait-network` 跑一次 `Test-Connection 8.8.8.8` 迴圈,最多等 30 回合×2 秒;ICMP 被擋住的環境會等完整 60 秒但 HTTPS 其實可用,也能跑下去。
|
||
- **per-user 安裝**:Telegram 安裝程式預設裝到 Admin 這個帳號底下,**新建的 `User` 看不到**。要全機安裝就在 `Setup.ps1` 的 `install-telegram` 段把 `ArgumentList` 加上 `'/ALLUSERS'`。
|
||
- **抓的是 latest 版**:每次部署抓當下最新版。要鎖版本改用 `https://updates.tdesktop.com/tsetup/tsetup-x64.X.Y.Z.exe` 直鏈。
|
||
|
||
---
|
||
|
||
## 本次部署已知限制
|
||
|
||
沿用 repo 預設值,下列情況會失敗,改用前要先處理:
|
||
|
||
- **目標機若是 BIOS/MBR**:`<DiskConfiguration>` 目前寫死 UEFI+GPT,分割階段會報錯。
|
||
- **ARM64 機器**:所有 `<component>` 的 `processorArchitecture="amd64"` 要改成 `arm64`;同時 `Setup.ps1` 內的 `OneDriveSetup.exe` SysWOW64 路徑、`winget` Chrome `--scope machine` 等部分行為要重驗。
|
||
- **Ventoy USB 在 reboot 前被拔掉**:Order 4 會找不到 `Setup.ps1`,13 段 post-install 全部 skip。請等到第二次重開機進到登入畫面後才拔。
|
||
- **密碼是明碼**(`<PlainText>true</PlainText>`):僅適合測試用途;正式部署請用 Windows SIM 產 Base64。
|
||
- **Phase 2 全部需要外網**:目標機沒網路的話,從 `wait-network` 之後 7 段都會 ERR;Phase 1 的 8 段(防火牆、RDP、ICMP、WinRM、OneDrive 移除、Cortana 關閉、Default profile UI/IME、改名隱藏帳號)仍會成功完成。
|
||
- **公開 KMS 啟用**:`Setup.ps1` 預設用 `kms.digiboy.ir` 等第三方 KMS,這對內網/正式環境不適合。把 `$InternalKmsServers` 改成你自己的 KMS 主機就好。
|