在物理机 Linux 下安装 Windows server 2016 虚拟机

作者一言

已实测全流程安装Windows Server 2016, 发现不满足需求后卸载并重装为Windows Server 2019的完整过程,使用AI润色了一下文章XD,请放心食用。

  • 若想安装更高或更低的Server版本,可以自行测试,截止文章发表时间,最高可安装Server 2025版本(不推荐,卡顿。作者打算跑OpenCode,发现最低支持Windows 2019, 所以后来才重装的)

  • 个人主观测试4G内存下系统流畅程度:Windows Server 2012 = 2016 > 2019 > 2022 >> 2025(卡爆了)。 大于8G内存的机子实际上2019也很流畅了。并且2012及以下已经不支持很多软件了(如 Minecraft 基岩版服务端),甚至到目前2026年,2016也逐渐开始不兼容软件了(如OpenCode, Bun),所以2019是当前最具性价比的选择

  • 但具体选择什么系统要看业务需求,像如果只要跑 GTA SAMP 服务端,那装windows server 2008甚至2003都行哈哈哈

:rocket: Ubuntu KVM 部署 Windows Server 2016 完整实战指南 (避坑终极版)

这份指南将从零开始,手把手教您在 Ubuntu 物理机上,使用 KVM 虚拟化技术部署一台可供外部直接访问的 Windows Server 2016 虚拟机。跟着步骤执行,即可绕过所有经典陷阱,一路绿灯。


一、全新安装

阶段零:准备纯净版镜像与驱动

在开始安装之前,需要将 Windows 安装镜像和 KVM 驱动镜像准备好,并存放在 KVM 的专属目录中。

  1. 创建并进入工作目录(KVM 默认镜像存放路径):

    mkdir -p /var/lib/libvirt/images/
    cd /var/lib/libvirt/images/
    
  2. 下载 KVM 虚拟化驱动盘 (virtio-win.iso)
    直接在 Ubuntu 终端拉取 Red Hat 官方稳定版驱动。

    wget https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso -O /var/lib/libvirt/images/virtio-win.iso
    
  3. 准备 Windows Server 2016 纯净版镜像 (win2016.iso)

    • 获取镜像:推荐从 msdn.itellyou.cn 下载官方纯净版镜像(x64 架构,标准版或数据中心版均可)。

    • 上传镜像:将下载好的文件重命名为 win2016.iso,并通过 scpsftprsync 等工具上传到 Ubuntu 服务器的 /var/lib/libvirt/images/ 目录下。

    • 补充:或直接去官网下评估版:这个最快而且可以直接wget/curl下载到Linux下
      Windows Server 2016 | Microsoft Evaluation Center
      Windows Server 2019 | Microsoft Evaluation Center
      Windows Server 2022 | Microsoft Evaluation Center
      Windows Server 2025 | Microsoft Evaluation Center
      更多版本直接去必应、百度、谷歌等引擎搜,进去随便填一些信息就可以到上面这些链接的页面。然后先选简体中文版本点击下载,在chrome或者edge这些浏览器可以在下载管理右键正在下载的项复制链接。或者可以用idm、ndm、迅雷等下载工具,可以直接获链接(这种链接一般是有时效的,复制了就要尽快使用)

    • 2019版评估版转正式版命令(在最后一步完成后,管理员启动Powershell执行)。其它版本自行百度搜寻

    dism /online /set-edition:ServerDatacenter /productkey:WMDGN-G9PQG-XVVXX-R3X43-63DFG /accepteula
    

阶段一:权限处理与虚拟机创建

  1. :warning: 经典大坑 1:权限拒绝 (Permission denied)
    KVM 底层运行在 libvirt-qemu 用户下,必须确保镜像文件对此用户可读。

    # 赋予镜像文件读取权限
    chmod 644 /var/lib/libvirt/images/win2016.iso
    chmod 644 /var/lib/libvirt/images/virtio-win.iso
    
  2. 执行安装命令(以下配置为 16核/16GB内存示例,请根据实际情况调整):

    virt-install \
      --name WinServer2016 \                   # 虚拟机名称
      --ram 16384 \                             # 内存大小 (MB)
      --vcpus 16 \                               # CPU 核心数
      --cpu host-passthrough \                   # CPU 模式,直通宿主机 CPU 特性
      --os-variant win2k16 \                      # 操作系统变体,优化配置
      --disk path=/var/lib/libvirt/images/win2016.qcow2,size=200,format=qcow2,bus=virtio,cache=none,io=native \ # 系统盘
      --cdrom /var/lib/libvirt/images/win2016.iso \ # 挂载安装镜像
      --disk path=/var/lib/libvirt/images/virtio-win.iso,device=cdrom \ # 挂载驱动镜像
      --network network=default,model=virtio \     # 网络配置,使用默认 NAT 网络,virtio 模型
      --graphics vnc,listen=0.0.0.0,port=5900 \   # 开启 VNC 用于安装,监听所有接口
      --noautoconsole                              # 不自动打开控制台
    
  3. 放行 VNC 临时安装端口

    ufw allow 5900/tcp
    

阶段二:图形化安装与加载驱动

使用 RealVNC Viewer 或任何支持 VNC 协议的客户端,连接 物理机公网IP:5900 进入 Windows 安装界面。

  1. :warning: 经典大坑 2:选错版本变黑框

    • 在选择操作系统版本时,必须选择带有 “(桌面体验) / (Desktop Experience)” 字样的版本(例如:Windows Server 2016 Datacenter (Desktop Experience))。
  2. :warning: 经典大坑 3:找不到硬盘

    • 安装进行到“您想将 Windows 安装在哪里?”这一步时,列表为空是正常的,因为系统不认识虚拟硬盘。
    • 解决方法
      1. 点击左下角的 “加载驱动程序”“浏览”
      2. 展开 virtio-win 光盘,依次进入目录:viostor2k16amd64
      3. 点击“确定”,选择并安装 “Red Hat VirtIO SCSI controller”
      4. 驱动程序加载成功后,200GB 的硬盘就会自动出现,选中它,点击“下一步”继续安装。

阶段三:初始化、密码避坑与网卡修复

系统安装完成后会自动重启,进入最后的设置阶段。

重启陷阱:KVM 初次重启后自动关机

在安装进度条跑完后,Windows 安装程序会执行第一次重启。但 KVM 虚拟机有个常见特性:初次装完系统触发重启时,往往不会真正地 “重新启动” ,而是直接变成 “关机” 状态。

既然关机了,VNC 屏幕自然就断开连接了。别慌,只需两步即可解决。


第一步:查看虚拟机当前状态

在 Ubuntu 终端执行以下命令,检查虚拟机是否已变成关机状态:

virsh list --all

预期输出示例:

 Id   Name              State
---------------------------------
 -    WinServer2016     shut off

如果看到 shut off,说明正是我们预料的情况。


第二步:手动重新开机

确认状态为关机后,直接执行启动命令:

virsh start WinServer2016

成功提示:

Domain 'WinServer2016' started

此时虚拟机已成功开机,并会自动从硬盘启动,继续完成 Windows 剩余的配置流程。


验证结果

回到 RealVNC Viewer,重新连接 IP:5900,你应该能看到 Windows 正在 “准备设备” 的转圈画面了。

:white_check_mark: 故障排除完成

  1. :warning: 经典大坑 4:VNC 键盘映射错位(终极杀手)

    • 首次设置 Administrator 密码时,由于 VNC 客户端与虚拟机的键盘布局可能不一致,你输入的密码(特别是特殊符号)会被系统错误识别,导致后续无法登录。
    • 绝杀方案
      1. 进入桌面后,右键点击左下角“开始”徽标,选择 “命令提示符(管理员)”
      2. 执行以下明文重置命令(建议先设置一个纯字母数字的简单密码以便登录,之后再修改复杂密码):
        net user Administrator 你的新密码
        
  2. 安装网卡驱动(修复网络红叉)

    1. 右键点击左下角“开始”徽标,选择 “设备管理器”
    2. 找到带有黄色感叹号的 “以太网控制器”,右键点击并选择 “更新驱动程序”
    3. 选择 “浏览我的计算机以查找驱动程序”
    4. 选择浏览位置为 virtio-win 光盘(或者精确到 NetKVM\2k16\amd64 目录),点击“下一步”完成安装。
    5. 安装完成后,任务栏右下角的网络红叉就会消失,网络成功接通。

阶段四:网络配置与 Socat 端口转发

虚拟机默认使用 NAT 网络,拥有一个内网 IP(如 192.168.122.x)。我们需要通过端口转发,让外部网络能够直接访问虚拟机内的服务。

  1. 配置 Windows 虚拟机内部

    • 获取内网 IP:按 Win + R 键,输入 cmd 打开命令行,运行 ipconfig,记录下 IPv4 地址(假设为 192.168.122.103)。
    • 更改计算机名(可选):按 Win + R 键,输入 sysdm.cpl 打开系统属性。在“计算机名”选项卡中,将随机名称改为易记的名称(如 WIN-SERVER)。
    • 开启远程桌面:在“远程”选项卡中,勾选 “允许远程连接到此计算机”,并务必取消勾选下方的 “仅允许运行使用网络级别身份验证的远程桌面的计算机连接(建议)”
    • 重启虚拟机使设置生效。
  2. 配置 Ubuntu 物理机(转发端)

    • 安装 Socat 工具

      apt update
      apt install socat -y
      
    • 打通 RDP 远程桌面通道(将宿主机的 33899 端口转发到虚拟机的 3389 端口):

      # 放行宿主机防火墙端口
      ufw allow 33899/tcp
      
      # 使用 nohup 启动 socat 转发,使其在后台持久运行
      # 格式:socat TCP4-LISTEN:宿主机端口,reuseaddr,fork TCP4:虚拟机IP:虚拟机端口
      nohup socat TCP4-LISTEN:33899,reuseaddr,fork TCP4:192.168.122.103:3389 >/dev/null 2>&1 &
      

      后续连接:在本地电脑打开远程桌面连接 (mstsc),输入 物理机公网IP:33899,账号填 计算机名\Administrator 和之前重置的密码,即可丝滑连入。

    • 打通业务端口(以 TCP 27015 和 UDP 7777 为例):

      # 转发 TCP 业务端口
      ufw allow 27015/tcp
      nohup socat TCP4-LISTEN:27015,reuseaddr,fork TCP4:192.168.122.103:27015 >/dev/null 2>&1 &
      
      # 转发 UDP 业务端口
      ufw allow 7777/udp
      nohup socat UDP4-LISTEN:7777,reuseaddr,fork UDP4:192.168.122.103:7777 >/dev/null 2>&1 &
      
  3. :warning: 经典大坑 5:别忘了 Windows 内部防火墙
    完成物理机的端口转发后,必须进入 Windows Server 虚拟机内部:

    1. 打开 “高级安全 Windows Defender 防火墙”
    2. 点击左侧的 “入站规则”,然后点击右侧的 “新建规则”
    3. 根据向导,手动放行对应的业务端口(如 27015/7777)。否则,外部流量即使到达了虚拟机,也会被 Windows 系统防火墙拦截。

至此,您的 Windows Server 2016 虚拟机已在 Ubuntu KVM 上完美运行,并且可以通过网络畅通无阻地访问了。

二、卸载重装

KVM 虚拟化部署手记:Windows Server 2019 从零到一

阶段零:破而后立 —— 彻底销毁旧虚拟机

在创建新环境前,必须将占用的硬盘空间和后台端口彻底释放,做到斩草除根

# 1. 拔掉电源并销毁档案
virsh destroy WinServer2016   # 强制关机
virsh undefine WinServer2016   # 删除虚拟机配置档案

# 2. 粉碎虚拟硬盘文件(释放空间的核心)
rm -f /var/lib/libvirt/images/win2016.qcow2

# 3. 清理残留的后台转发进程
pkill socat   # 一键杀掉之前挂载的所有 socat 端口转发进程

(如果你还有其他不能杀的 socat 进程,可以先用 ps aux | grep socat 查出 PID,然后再用 kill -9 PID 单独杀)


阶段一:运筹帷幄 —— 硬件分配的底层哲学

在合租服务器上分配资源,既要保证 Windows 编译时的极致性能,又要守住物理机不崩溃的底线。

资源类型 分配方案 底层原理
内存 (RAM) 24 GB(甜点配置) VirtIO Balloon(内存气球)机制:闲置时底层 Ubuntu 回收内存,编译时瞬间膨胀到 24 GB 上限
硬盘 (Disk) 300 GB(动态上限) QCOW2 精简制备 (Thin Provisioning):按实际使用量占用物理空间,用多少占多少
核心 (vCPU) 16 核(黄金比例) 必须预留保命空间:给底层 Ubuntu 留至少 4 个核心处理网络和 I/O 调度,避免满载死锁

阶段二:粮草先行 —— 准备纯净镜像

将核心镜像放到 KVM 公用目录下,并务必赋予读取权限,否则会报 Permission denied

# 1. 拉取 KVM 官方驱动盘
wget https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso -O /var/lib/libvirt/images/virtio-win.iso

# 2. 准备系统盘与赋权
# 从 msdn.itellyou.cn 下载 Windows Server 2019 纯净版镜像
# 重命名为 win2019.iso 并通过 SFTP 上传到同一目录

chmod 644 /var/lib/libvirt/images/win2019.iso
chmod 644 /var/lib/libvirt/images/virtio-win.iso

阶段三:开天辟地 —— 一键创建虚拟机

在 Ubuntu 终端执行以下命令,启动 2019 安装向导,并临时放行 VNC 端口:

virt-install \
  --name WinServer2019 \
  --ram 24576 \
  --vcpus 16 \
  --cpu host-passthrough \
  --os-variant win2k19 \
  --disk path=/var/lib/libvirt/images/win2019.qcow2,size=300,format=qcow2,bus=virtio,cache=none,io=native \
  --cdrom /var/lib/libvirt/images/win2019.iso \
  --disk path=/var/lib/libvirt/images/virtio-win.iso,device=cdrom \
  --network network=default,model=virtio \
  --graphics vnc,listen=0.0.0.0,port=5900 \
  --noautoconsole

# 放行防火墙
ufw allow 5900/tcp

阶段四:步步惊心 —— 图形化安装的三大“天坑”

使用 RealVNC Viewer 连接 物理机公网IP:5900 进入安装画面。请务必躲开以下三个雷区:

:hole: 黑框天坑

选择版本时,必须选择带有 “(桌面体验) / (Desktop Experience)” 字样的版本。

:hole: 硬盘失踪坑

到选择安装位置时列表为空。

  • 点击 “加载驱动程序”“浏览”
  • 展开 virtio-win 光驱 → 依次进入 viostor \ 2k19 \ amd64
  • 加载 Red Hat 驱动后即可看到 300 GB 硬盘

:hole: VNC 键盘错位坑(终极杀手)

首次开机设置密码时,VNC 极易把特殊符号打错(如 # 打成 3)。

破局方法:

  1. 首次设置:使用绝对不带特殊符号的纯字母数字密码
  2. 双保险:进桌面后,右键开始菜单打开 “命令提示符(管理员)”,敲入:
    net user Administrator 新密码
    
    明文强制重置一次!

:bulb: 小贴士:进桌面后别忘了去 “设备管理器”,右键带有黄色感叹号的 “以太网控制器”,浏览光驱目录更新网卡驱动,接通网络。


阶段五:暗渡陈仓 —— 突破内网打通 RDP 与业务端口

虚拟机拿到 192.168.122.x 的内网 IP,需要在内部开门,在外部修路。

第一步:Windows 内部配置(被控端)

  1. 改名顺应习惯
    Win + R 输入 sysdm.cpl“计算机名” 改成易记名前缀 → 重启

  2. 解除 NLA 封印
    “远程” 选项卡 → 勾选 “允许远程连接”
    :warning: 绝对取消勾选 “仅允许运行使用网络级别身份验证(NLA)…”
    这样后续可用 你的易记名\Administrator 直接丝滑登录

第二步:Ubuntu 物理机转发(转发端)

回到物理机终端,使用 socat 把物理机的端口映射给虚拟机(假设虚拟机 IP 为 192.168.122.103):

:one: 打通 RDP 远程桌面通道(TCP 3389)

# 放行防火墙
ufw allow 33899/tcp

# 启动转发(后台运行)
nohup socat TCP4-LISTEN:33899,reuseaddr,fork TCP4:192.168.122.103:3389 >/dev/null 2>&1 &

此时,可用本地电脑的 mstsc 连接 物理机IP:33899,享受极致高清的远程桌面,并可以关掉 VNC 了。

:two: 打通后续业务端口(示例)

# 转发 TCP 端口(如 27015)
ufw allow 27015/tcp
nohup socat TCP4-LISTEN:27015,reuseaddr,fork TCP4:192.168.122.103:27015 >/dev/null 2>&1 &

# 转发 UDP 端口(如 7777)
ufw allow 7777/udp
nohup socat UDP4-LISTEN:7777,reuseaddr,fork UDP4:192.168.122.103:7777 >/dev/null 2>&1 &

:warning: 终极提醒

外部端口打通后,千万别忘了进入 Windows 内部的 “高级安全 Windows Defender 防火墙”,新建入站规则把这些端口放行,否则一切白搭