新增 Setup.ps1(13 段 post-install);FirstLogonCommands 改從 Ventoy USB 拷腳本
把分散在 unattend.xml inline 的網路相依步驟(OpenSSH/Telegram/RemoveAI)和 新加入的 10 個 post-install 動作整合進獨立的 Setup.ps1,由 FirstLogonCommands Order 4 從 Ventoy USB(/ventoy/script/Setup.ps1)掃磁碟複製到 C:\Scripts\, Order 5 執行。腳本分兩 phase: Phase 1(不需網路):SSH 22 防火牆、RDP+3389、ICMP Echo、WinRM TrustedHosts=*、 移 OneDrive、關 Cortana/WebSearch、套 UI/IME 預設到 Default profile、user→User 改名 + 從登入畫面隱藏 Admin。 Phase 2(要網路,wait-network 後):OpenSSH Server FoD、KMS 啟用(先試 $InternalKmsServers 後 fallback 公開 KMS)、winget Chrome、RemoveWindowsAI、 Win11Debloat、22 個 UWP 移除、Telegram、刪 Panther 殘留。 每段以 Section 包裝寫獨立 START/DONE/ERR 到 C:\Windows\Temp\setup.log,方便逐段 重跑與排查。 文件全部同步:DEPLOY/QUICKSTART/SUMMARY/README/CLAUDE 都加上 Setup.ps1 的 USB 部署、cp 步驟、Order 表、排查指引。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
142
DEPLOY.md
142
DEPLOY.md
@@ -26,9 +26,12 @@ USB 根目錄兩個 ISO:
|
||||
└── ventoy/
|
||||
├── ventoy.json ← 對應兩個 ISO,都指向同一份 template
|
||||
└── script/
|
||||
└── unattend.xml ← 與 repo 根目錄的 unattend.xml 相同
|
||||
├── 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`
|
||||
@@ -80,6 +83,7 @@ USB 根目錄兩個 ISO:
|
||||
# 從 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 檔名完全一致
|
||||
@@ -93,17 +97,20 @@ 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`,除非要改 Windows 版本特有設定。
|
||||
4. 若 repo 裡的 `unattend.xml` 有更新,重跑一次 `cp` 與 `dot_clean` 即可。
|
||||
3. **不用**動 `/Volumes/Ventoy/ventoy/script/unattend.xml` 與 `Setup.ps1`,除非要改 Windows 版本特有設定。
|
||||
4. 若 repo 裡的 `unattend.xml` 或 `Setup.ps1` 有更新,重跑一次 `cp` 與 `dot_clean` 即可。
|
||||
|
||||
---
|
||||
|
||||
@@ -113,53 +120,97 @@ cat /Volumes/Ventoy/ventoy/ventoy.json
|
||||
|
||||
| Order | 動作 | 需要網路? |
|
||||
|---|---|---|
|
||||
| 1 | `powershell -File C:\Scripts\Setup.ps1` | 看腳本內容 |
|
||||
| 2 | `net accounts /maxpwage:unlimited`(密碼永不過期) | 否 |
|
||||
| 3 | `Rename-Computer` 把主機名改成 `PC-XXXXX`(重開後生效) | 否 |
|
||||
| 4 | `net user user 1234 /add`+`/logonpasswordchg:yes`(建立一般使用者 `user`,首次登入強制改密) | 否 |
|
||||
| 5 | 等網路→`Add-WindowsCapability OpenSSH.Server`+`Set-Service sshd Automatic`+`Start-Service sshd`(log: `firstlogon-sshd.log`) | **是** |
|
||||
| 6 | 等網路→下載 `https://telegram.org/dl/desktop/win64` → 靜默安裝(`/VERYSILENT /SUPPRESSMSGBOXES /NORESTART`,log: `firstlogon-telegram.log`) | **是** |
|
||||
| 7 | `shutdown /r /t 5` 重開機 | 否 |
|
||||
| 1 | `net accounts /maxpwage:unlimited`(密碼永不過期) | 否 |
|
||||
| 2 | `Rename-Computer` 把主機名改成 `PC-XXXXX`(重開後生效) | 否 |
|
||||
| 3 | `net user user 1234 /add`+`/logonpasswordchg:yes`(建立一般使用者 `user`,首次登入強制改密;之後 Setup.ps1 會把它改名成 `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` 重開機 | 否 |
|
||||
|
||||
### 新加入的 `user` 帳號
|
||||
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 |
|
||||
| `rename-hide-accounts` | `Rename-LocalUser user → User`、`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` → `User` 帳號
|
||||
|
||||
- **用途**:給使用者日常使用,和部署用的管理員 `Admin` 分開。
|
||||
- **權限**:一般 `Users` 群組(非 Administrators)。需要管理員權限時走 UAC。
|
||||
- **建立**:`unattend.xml` Order 3 用 `net user user 1234 /add`(首字小寫)。
|
||||
- **改名**:`Setup.ps1` 的 `rename-hide-accounts` 段把 `user` 改成 `User`(首字大寫)。要先建小寫再改名是因為 `Rename-LocalUser` 必須對既有帳號操作;如果 `Setup.ps1` 沒跑完,最差情況是有個 `user` 還能登入。
|
||||
- **權限**:一般 `Users` 群組(非 Administrators)。需要管理員權限時走 UAC(用 `Admin/P@ssw0rd!`)。
|
||||
- **首次登入強制改密**:`/logonpasswordchg:yes` 會在下次登入時跳「密碼必須變更」。可以改成複雜密碼。
|
||||
- **如果 `net user` 因為 Windows 密碼政策拒絕 `1234`**:整條 Order 4 會失敗但不會擋後面,手動於 PowerShell 以 `New-LocalUser`+更寬的密碼重跑。
|
||||
- **如果 `net user` 因為 Windows 密碼政策拒絕 `1234`**:Order 3 會失敗但不會擋後面,手動於 PowerShell 以 `New-LocalUser`+更寬的密碼重跑,再讓 `Setup.ps1` 改名。
|
||||
|
||||
### OpenSSH Server(Order 5)
|
||||
### Order 4 的磁碟掃描沒找到 Setup.ps1 怎麼辦
|
||||
|
||||
- 走 Windows 內建 Feature on Demand,**會從 Windows Update 下載** `OpenSSH.Server~~~~0.0.1.0`。需要外網。
|
||||
- 完成後 `sshd` 服務設成 `Automatic`(每次開機自動啟動),防火牆規則由 FoD 自動建立(TCP 22 inbound allow)。
|
||||
- 驗證:`Get-Service sshd` 應該 `Running`;`Get-NetFirewallRule -Name OpenSSH-Server-In-TCP` 應該 `Enabled=True`。
|
||||
- 用來遠端登入:`ssh Admin@<機器 IP>` 或 `ssh user@<機器 IP>`。初次使用要先在 `%ProgramData%\ssh\administrators_authorized_keys` 加公鑰(Windows OpenSSH 對 Administrators 群組的授權金鑰路徑特殊,不走 `~/.ssh/authorized_keys`)。
|
||||
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` 然後跳過。原因通常是:
|
||||
|
||||
### Telegram(Order 6)的注意事項
|
||||
|
||||
- **要有網路**:OOBE 裡 `SkipMachineOOBE=true` 跳過了網路設定精靈,所以目標機必須有 Ethernet+DHCP,或本身已記住 Wi-Fi。這次有 log 可以驗證—`C:\Windows\Temp\firstlogon-telegram.log` 會寫 `NetWait=?s`、`Downloaded ?B`、`Exit ?`。
|
||||
- **網路等待上限 60 秒**:Order 5 和 Order 6 都各跑一次 `Test-Connection 8.8.8.8` 迴圈,最多等 30 回合×2 秒;ICMP 被擋住的環境會等完整 60 秒但 HTTPS 其實可用,也能跑下去。
|
||||
- **per-user 安裝**:Telegram 安裝程式預設裝到 Admin 這個帳號底下,**新建的 `user` 看不到**。要全機安裝就在 `ArgumentList` 加 `'/ALLUSERS'`。
|
||||
- **抓的是 latest 版**:每次部署抓當下最新版。要鎖版本改用 `https://updates.tdesktop.com/tsetup/tsetup-x64.X.Y.Z.exe` 直鏈。
|
||||
- **順序不能搬到 reboot 後**:`shutdown /r /t 5` 只是排程重開機、立即回傳,若放在 Telegram 前面,下載安裝會被 5 秒後的關機砍掉。
|
||||
|
||||
### 上次部署 Telegram 無聲失敗如何排查
|
||||
|
||||
這次每一條都有 log:登入 `Admin` 後看
|
||||
|
||||
```
|
||||
notepad C:\Windows\Temp\firstlogon-telegram.log
|
||||
notepad C:\Windows\Temp\firstlogon-sshd.log
|
||||
```
|
||||
|
||||
常見會看到的值:
|
||||
|
||||
| Log 內容 | 代表 | 對策 |
|
||||
| 現象 | 原因 | 對策 |
|
||||
|---|---|---|
|
||||
| `NetWait=60s` + `ERR ...` | 60 秒內 ICMP 沒通,後面可能也失敗 | 接網路線、或在 OOBE 後手動連 Wi-Fi 後重跑指令 |
|
||||
| `Downloaded 0B` 或 `ERR` 含 `SSL/TLS` | TLS 交握失敗 | 檢查系統時間是否對;老機器可能要裝 Windows Update for TLS 1.2 |
|
||||
| `Exit 0` 但桌面沒 Telegram 捷徑 | 裝成功但 per-user 安裝、不是登入那個帳號 | 以 Admin 登入,捷徑在 `%APPDATA%\Microsoft\Windows\Start Menu\Programs\Telegram Desktop` |
|
||||
| 完全沒 log 檔 | 這條 `SynchronousCommand` 根本沒跑(通常是 `AutoLogon.Enabled=false` 或 XML 沒注入) | 查 `C:\Windows\Panther\UnattendGC\setupact.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` 直鏈。
|
||||
|
||||
---
|
||||
|
||||
@@ -168,7 +219,8 @@ notepad C:\Windows\Temp\firstlogon-sshd.log
|
||||
沿用 repo 預設值,下列情況會失敗,改用前要先處理:
|
||||
|
||||
- **目標機若是 BIOS/MBR**:`<DiskConfiguration>` 目前寫死 UEFI+GPT,分割階段會報錯。
|
||||
- **ARM64 機器**:所有 `<component>` 的 `processorArchitecture="amd64"` 要改成 `arm64`。
|
||||
- **`C:\Scripts\Setup.ps1` 未提供**:`FirstLogonCommands` 會在首次登入時報「找不到檔案」。解法:在 `FirstLogonCommands` 前段加一條從 USB 複製的指令,或另外烘進 image,或乾脆刪掉 `Order=1` 那條 `SynchronousCommand`。
|
||||
- **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。
|
||||
- **Telegram 安裝需要外網**:目標機沒網路的話,Order 4 會失敗但不影響整個流程走完。
|
||||
- **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 主機就好。
|
||||
|
||||
Reference in New Issue
Block a user