PVE 自带的 Cloud-Init 仅对 Linux 友好,Windows 需要安装 Cloudbase-Init 才能消费 PVE 注入的 ConfigDrive。本文用一个一键脚本完成 Cloudbase-Init 配置和 sysprep,做出可重复克隆的 Windows 模板。
整体流程
PVE 上正常装好 Windows,做一次快照(出问题方便回滚)
在 VM 中安装 Cloudbase-Init ,安装结尾不要勾选 Run Sysprep
在 VM 中以管理员身份打开 PowerShell,一键执行:
1Set-ExecutionPolicy Bypass -Scope Process -Force; iex (irm 'https://x.csz.net/scripts/Setup-CloudbaseInit.ps1')看到提示输入
YES,脚本会自动跑 sysprep 并关机在 PVE 把这台 VM 转模板:
1qm set <id> --ide2 local-lvm:cloudinit 2qm template <id>克隆出新 VM,在 Cloud-Init 标签页把 User 填
cloudadmin、密码自定,点击 Regenerate Image启动 VM,等约 1 分钟,用
cloudadmin+ 设置的密码登录
改密码
PVE 控制台改 Password → Regenerate Image → 重启 VM → 新密码生效。注意一定要点 Regenerate Image,否则 ConfigDrive 还是旧的。
脚本说明
脚本做了几件事:
- 备份
C:\Program Files\Cloudbase Solutions\Cloudbase-Init\conf下原配置 - 写入三个 base64 编码的配置文件(避免引号/编码被转码工具破坏):
cloudbase-init.conf:主配置,启用 ConfigDrive、用户cloudadmin、加载完整插件链cloudbase-init-unattend.conf:sysprep specialize 阶段使用,仅做磁盘扩展Unattend.xml:sysprep 应答文件,跳过 OOBE、开启 RDP、设置时区为 China Standard Time
- 设置
cloudbase-init服务为自动启动 - 清理用户安装但未 provisioned 的 AppX 包(最常见的 sysprep 阻塞原因)
- 清空 Cloudbase-Init 的运行历史注册表,确保下次启动重新执行
- 执行
sysprep /generalize /oobe /shutdown
可选参数:
-SkipSysprep:只写配置不跑 sysprep-SkipAppxCleanup:跳过 AppX 清理(确认环境干净时才用)
iex 不方便传参,需要带参数运行时改用:
1Set-ExecutionPolicy Bypass -Scope Process -Force
2$src = irm 'https://x.csz.net/scripts/Setup-CloudbaseInit.ps1'
3& ([scriptblock]::Create($src)) -SkipSysprep
常见坑
- sysprep 报错退出:99% 是 AppX 阻塞,看
C:\Windows\System32\Sysprep\Panther\setupact.log找到具体包名,加到清理逻辑或手动Remove-AppxPackage - 克隆后登录失败:检查 PVE Cloud-Init 标签页是否点了 Regenerate Image,以及 ConfigDrive 设备是否挂上(
qm config <id>应能看到ide2: ...,media=cdrom) - 改密码不生效:同上,必须 Regenerate Image 后重启,Cloudbase-Init 默认每次开机都会读 ConfigDrive 重设密码
- 想保留首次登录改密:脚本里
first_logon_behaviour=no关闭了首次登录强制改密,需要的话改成always