PVE制作Windows11镜像模板

这篇文章给出一套可复现流程:在 Proxmox VE(PVE)上把 Windows 11 做成可克隆、可在 PVE 面板注入用户名/密码/静态 IP/主机名、并且宿主机能读取 IP / 优雅关机的基础通用模板。适用对象是需要批量交付 Windows VM 的运维/平台/研发同学;你会得到一套从建 VM、安装驱动与 Guest Agent、接入 Cloud-Init(ConfigDrive + Cloudbase-Init)、到 Sysprep 泛化封模和常见故障定位的完整 SOP。

1)环境与版本(含适用边界)

1.1 环境信息(示例)

项目
虚拟化平台Proxmox VE(PVE)
Guest OSWindows 11 25H2(示例)
Cloud-Init 注入PVE CloudInit Drive(ConfigDrive2) + Cloudbase-Init
宿主管理QEMU Guest Agent(PVE 启用 + Windows 内安装)
VirtIO 驱动virtio-win ISO

1.2 目标(模板交付标准)

  • PVE 可读到 VM IP、可优雅关机:PVE 勾选 QEMU Agent + Windows 内 QEMU Guest Agent 正常运行
  • PVE Cloud-Init 页面可注入:user / password / static IP / hostname
  • 克隆后不冲突:Sysprep /generalize + 清理 Cloudbase-Init 执行状态(避免克隆后不再执行注入)

1.3 合规/安全提醒(建议读完再选)

  • 绕过 TPM / Secure Boot 检查属于“非标准安装路径”,可能不符合企业基线与微软支持边界;生产模板更建议用 OVMF + vTPM 2.0 + Secure Boot(PVE 原生支持)。
  • 本文会给出“绕过安装门槛”的可复现步骤,但更推荐你在交付标准中明确:生产=不绕过;实验/临时=可绕过。

2)方案概述(一句话结论 + 关键点)

**结论:**模板采用 VirtIO 驱动 + QEMU Guest Agent + PVE CloudInit Drive(ConfigDrive2)+ Cloudbase-Init + Sysprep 组合:

  • PVE CloudInit Drive 负责把“用户/密码/网络/主机名”写进 ConfigDrive;
  • Cloudbase-Init 在 Windows 内读取 ConfigDrive 并落地配置;
  • QEMU Guest Agent 提供宿主机读取 IP / 关机等管理能力;
  • Sysprep 做 Windows 正规泛化,避免克隆冲突。

关键点(高频踩坑):

  • PVE Cloud-Init 注入生效要两端满足:VM 已挂 CloudInit Drive + Windows 已安装并能运行 Cloudbase-Init
  • QEMU Guest Agent 生效要两端满足:PVE Options 启用 Agent + Windows 内安装 virtio-serial/guest-tools + QEMU-GA 服务 running
  • Cloudbase-Init 配置文件需注意编码:在中文系统里容易遇到 GBK 解码失败;建议配置文件保持 纯 ASCII(无中文注释/特殊字符)

3)落地步骤(建机 → 安装 → 配置 → 验证)

3.1 准备材料(PVE 侧)

3)落地步骤(可复现流程)

3.1 PVE 创建虚拟机

Win11 / Server 2022/2025 强烈建议按 Proxmox 的 Win11 最佳实践走:创建 VM 时选择对应 Windows Guest OS,并在 System 里启用 QEMU Agent;磁盘走 SCSI + “VirtIO SCSI single”。https://pve.proxmox.com/wiki/Windows_11_guest_best_practices?utm_source=chatgpt.com

3.2 PVE 创建 VM(建议参数)

建议用(性能/兼容性/可运维)默认组合:

  • Machine:q35
  • BIOS:OVMF (UEFI);添加 EFI Disk
  • Disk:SCSI + Controller 选 VirtIO SCSI single
  • NIC:VirtIO
  • System:勾选 QEMU Agent = Enabled
  • 安装介质:挂 Windows ISO;同时挂 virtio-win.iso(或勾选“添加额外驱动器”)

客户机操作系统类别为:Microsoft Windows。选择版本11/2022/2025,勾选为VirtIO驱动程序添加额外驱动器,选择刚才下载的virtio-win.iso

BIOS选择OVMF,勾选Qemu代理,勾选添加EFI磁盘,我这里不建议勾选TPM。

3.3 安装 Windows(含绕过 TPM / SecureBoot / 无网络 OOBE)

3.3.1(可选)绕过 TPM / SecureBoot 检查

安装界面按 Shift + F10 打开 CMD,执行:

Bash
REG ADD HKLM\SYSTEM\Setup\LabConfig /v BypassTPMCheck /t REG_DWORD /d 1
REG ADD HKLM\SYSTEM\Setup\LabConfig /v BypassSecureBootCheck /t REG_DWORD /d 1

或用 regeditHKEY_LOCAL_MACHINE\SYSTEM\Setup 下创建 LabConfig,并创建两个 DWORD:

Bash
BypassSecureBootCheck = 1
BypassTPMCheck = 1

3.3.2 加载 VirtIO 存储驱动(否则看不到磁盘)

在选择磁盘页面点“加载驱动程序”,选 virtio ISO 中类似目录:

Bash
vioscsi\win11\amd64

3.3.3(可选)绕过“必须联网”OOBE

若 OOBE 阶段提示无网络、无法继续,可在 Shift + F10 打开 CMD 后执行:

Bash
oobe\BypassNRO.cmd

重启后选择“我没有 Internet 连接”继续。

3.4 安装 VirtIO Guest Tools + 启动 QEMU Guest Agent

进入桌面后,从 virtio-win 光驱执行:

  • virtio-win-gt-x64.msi
  • virtio-win-guest-tools.exe

安装完成后,拉起 QEMU Guest Agent(服务名可能不同,先查再启):

装完后用 PowerShell 把 QEMU GA 服务拉起并设为自启动(不同包服务名略有差异;下列是常见写法):

Bash
Start-Service -Name 'QEMU-GA'
Set-Service -Name 'QEMU-GA' -StartupType Automatic

验证点:

  • PVE → VM Summary 能显示 IP(或 Agent 信息开始出现)
  • Windows:Get-Service QEMU-GA

建议此时开启RDP远程桌面服务方便后续配置。

3.5 安装CloudInit

3.5.1 PVE WebUI

  • 关机 VM
  • VM → Hardware → Add → CloudInit Drive
  • Storage 选系统盘存储(如 local-lvm
  • VM → Cloud-Init:填写 ciuser / cipassword / ipconfig0 / DNSRegenerate Image → 开机

3.6 安装 Cloudbase-Init(Windows 侧)并配置 ConfigDrive

安装 Cloudbase-Init 时勾选:

  • Run Cloudbase-Init service as LocalSystem

安装完成后不要点这个勾选框。

安装完成后修改配置文件:C:\Program Files\Cloudbase Solutions\Cloudbase-Init\conf\cloudbase-init.conf
首先修改cloudbase-init.conf文件编辑权限,右键文件——属性,赋予Users完整权限。

3.6.1 推荐配置(PVE ConfigDrive2 + 静态 IP)

配置文件建议保持 纯 ASCII(避免中文系统默认 GBK 解码报错)。

Conf
[DEFAULT]
; --- Account ---
username=Admin
groups=Administrators
rename_admin_user=true

; --- Password injection ---
inject_user_password=true
first_logon_behaviour=no

; --- Datasource: PVE uses ConfigDrive (configdrive2 for Windows) ---
metadata_services=cloudbaseinit.metadata.services.configdrive.ConfigDriveService

; --- Logging ---
verbose=true
debug=true
log_dir=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\log\
log_file=cloudbase-init.log
default_log_levels=comtypes=INFO,suds=INFO,iso8601=WARN,requests=WARN
logging_serial_port_settings=

; --- Network helpers ---
mtu_use_dhcp_config=false
ntp_use_dhcp_config=false

; --- Local scripts (optional) ---
local_scripts_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\LocalScripts\

; --- Hostname ---
netbios_host_name_compatibility=false

; --- Execution ---
allow_reboot=true
stop_service_on_exit=true
check_latest_version=false

; --- Plugins order matters ---
plugins=cloudbaseinit.plugins.common.networkconfig.NetworkConfigPlugin,cloudbaseinit.plugins.common.sethostname.SetHostNamePlugin,cloudbaseinit.plugins.windows.createuser.CreateUserPlugin,cloudbaseinit.plugins.common.setuserpassword.SetUserPasswordPlugin,cloudbaseinit.plugins.windows.extendvolumes.ExtendVolumesPlugin,cloudbaseinit.plugins.common.userdata.UserDataPlugin,cloudbaseinit.plugins.common.localscripts.LocalScriptsPlugin

; --- Tools path (keep yours) ---
bsdtar_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\bin\bsdtar.exe
mtools_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\bin\

[config_drive]
types=iso
locations=cdrom

记得给Admin账户启用

重启后就可以在PVE的Cloud-init配置中修改IP了

3.6.2 快速验证(注入是否执行)

Bash
# 1) 服务状态(按你的配置 stop_service_on_exit=true,执行完会自动停)
Get-Service cloudbase-init

# 2) 看日志(关键:Config Drive found / Metadata service loaded / NetworkConfigPlugin)
Get-Content "C:\Program Files\Cloudbase Solutions\Cloudbase-Init\log\cloudbase-init.log" -Tail 200

# 3) 验证 IP
Get-NetIPAddress -AddressFamily IPv4 | Format-Table -Aut

4)可选实践(按需启用:OpenSSH / 精简 App / 更新策略)

4.1 安装OpenSSH-Server

https://github.com/PowerShell/Win32-OpenSSH/releases

下载并解压到C:\Program Files\

先放行PowerShell 执行策略

Bash
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass -Force

启动与开机自启 + 防火墙

Bash
.\install-sshd.ps1
# 设置开机自动启动
Start-Service sshd
Set-Service sshd -StartupType Automatic

Start-Service ssh-agent
Set-Service ssh-agent -StartupType Automatic

Get-Service sshd,ssh-agent | Format-Table Name,Status,StartType
# 放行 Windows 防火墙 22 端口
if (-not (Get-NetFirewallRule -Name "OpenSSH-Server-In-TCP" -ErrorAction SilentlyContinue)) {
  New-NetFirewallRule -Name "OpenSSH-Server-In-TCP" `
    -DisplayName "OpenSSH Server (sshd)" `
    -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
}
Get-NetFirewallRule -Name "OpenSSH-Server-In-TCP" | Format-Table -Auto

# 本机监听检查
netstat -ano | findstr ":22"

# 看 sshd 配置语法(可选)
& "C:\Program Files\OpenSSH-Win64\sshd.exe" -t

然后开机就可以通过SSH端口远程连接了

4.2 禁用Windows Defender

参考代码,下载执行即可:https://github.com/ionuttbara/windows-defender-remover
关闭安全防护会显著提高风险,并让后续补丁/排障成本上升。

4.3 禁用Windows自动更新

参考代码,下载执行即可:https://github.com/tsgrgo/windows-update-disabler
关闭系统更新会显著提高风险,并让后续补丁/排障成本上升。

4.4 去除垃圾应用

卸载服务器上不需要的Xbox、GameBar等插件

O&O AppBuster(推荐给“点点就完事”)

  • 便携、免费,专门用来卸载 Windows 10/11 预装/隐藏应用,并且通常支持恢复。
    适合:你做模板时想手工删掉一批 Xbox/广告/游戏类 App,但又不想写脚本。

Chris Titus Tech WinUtil(一个命令打开工具箱)

Bash
irm "https://christitus.com/win" | iex

5)封装为模板(Sysprep + 清理注入状态 + 克隆验收)

5.1 封模前检查清单(PVE)

  • Options → QEMU Guest Agent:Enabled
  • Hardware → 已挂 CloudInit Drive
  • Cloud-Init 页面可正常 Regenerate

5.2 封模前清理(Windows)

目的:确保克隆后 Cloudbase-Init 会再次执行注入,且 SSH host key 不复用。

Bash
# 1) 清 Cloudbase-Init 执行状态(用于“测试反复注入”或“封模确保克隆会跑”)
# 注意:这会让 Cloudbase-Init 下次启动重新跑插件
Remove-Item -Recurse "HKLM:\Software\Cloudbase Solutions" -Force -ErrorAction SilentlyContinue

# 2) 清 Cloudbase-Init 日志(可选)
Remove-Item "C:\Program Files\Cloudbase Solutions\Cloudbase-Init\log\*" -Force -ErrorAction SilentlyContinue

# 3) 如果安装了 OpenSSH,清理 host keys(避免克隆复用)
Remove-Item "C:\ProgramData\ssh\ssh_host_*" -Force -ErrorAction SilentlyContinue

OpenSSH host key 的再生成策略与版本有关;如果你希望“开机必生成”,可以在 Cloudbase-Init LocalScripts 里加 ssh-keygen -A(前提 PATH 可用或写全路径)。

5.3 Sysprep(泛化关机)

运行:

  • C:\Windows\System32\Sysprep\Sysprep.exe
  • 选择 OOBE
  • 勾选 Generalize(通用)
  • 选择 Shutdown(关机)

关机后在 PVE:Convert to template

5.4 克隆验收(必须做一次)

克隆一台新 VM 后检查:

  • PVE:Summary 可显示 IP;Shutdown 工作正常
  • Windows:
    • Get-NetIPAddress 与 PVE 注入一致
    • cloudbase-init.log 能看到新一次执行
    • 若启用 OpenSSH:sshd running,C:\ProgramData\ssh\ssh_host_* 已重新生成(或按你的策略生成)

结尾(总结 / 边界 / 下一步)

  • 总结
    • 注入闭环:PVE CloudInit Drive(ConfigDrive2) + Windows Cloudbase-Init
    • 宿主管理闭环:PVE 启用 Agent + Windows QEMU Guest Agent running
    • 克隆不冲突:Sysprep /generalize + 清 Cloudbase-Init 状态 +(可选)清 SSH host keys
  • 边界提醒
    • 绕过 TPM / Secure Boot 属于非标准路径;生产模板建议用 vTPM2.0 + Secure Boot。
  • 下一步
    • 把“OpenSSH 安装 / host key 生成 / 业务基线工具安装”下沉到 Cloudbase-Init LocalScripts,形成一次性首启脚本
    • 制作“模板验收脚本”:IP/hostname/agent/sshd 状态一键检查
    • 引入更新策略(WSUS/窗口期),避免用“禁用更新”来换稳定

References(原文链接集合)

PVE Windows 11 best practices:
https://pve.proxmox.com/wiki/Windows_11_guest_best_practices

VirtIO ISO:
https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.285-1/

Cloudbase-Init:
https://github.com/cloudbase/cloudbase-init/releases
https://pve.proxmox.com/wiki/Cloud-Init_Support

Win32-OpenSSH:
https://github.com/PowerShell/Win32-OpenSSH/releases

.NET Framework:
https://dotnet.microsoft.com/zh-cn/download/dotnet-framework

PVE安装Windows11小记
https://willxup.top/archives/pve-install-win11

附录)

下载 .NET Framework 运行时大全

https://dotnet.microsoft.com/zh-cn/download/dotnet-framework

K8s 常用命令手记 跨语言任务队列代码实战:Spring Boot + RabbitMQ + Celery 全链路打通 使用 Docker 快速搭建 Redis 数据库
View Comments
There are currently no comments.