首页
/ Omarchy 内置 Windows 虚拟机实战:用 Docker + KVM 在 Linux 桌面里跑 Windows 11

Omarchy 内置 Windows 虚拟机实战:用 Docker + KVM 在 Linux 桌面里跑 Windows 11

2026-09-08 23:55:40作者:廉皓灿Ida

Omarchy 把"在 Linux 上运行 Windows"做成了一个开箱即用的功能模块:它基于 Docker 运行的特权级 Windows 虚拟机,通过一键安装脚本、应用启动器入口和全屏 RDP 连接,把传统上复杂的虚拟化配置收敛为几个交互式提问和一条命令。本文以 Windows VM 指南 为主线,结合其底层实现脚本与测试,完整讲解从安装前提、交互配置、日常使用、文件共享与安全边界,到资源调整、OEM 许可与彻底卸载的每一个环节。

读完本文,你将掌握:如何通过 Omarchy 菜单安装并启动一个 Windows 11 虚拟机、如何用 omarchy windows vm 系列命令管理它的生命周期、~/Windows~/.windows 的共享与隔离机制、以及这套方案在"零 GPU 透传"前提下的适用边界。

Windows VM 是什么:方案概览与前提条件

在 Omarchy 中,Windows 虚拟机并不是用 virt-manager 或 libvirt 搭建的,而是由脚本 bin/omarchy-windows-vm 驱动的一套 Docker + KVM 组合:一个基于 dockurr/windows 镜像的容器(容器名为 omarchy-windows),直接把宿主的 /dev/kvm/dev/net/tun 设备透传给内部的 Windows 11 客户机,再通过 FreeRDP 提供桌面访问。

整个安装流程的入口是 Omarchy 菜单(Super + Space 唤起)中的 Install > Windows。该菜单项在仓库中的定义位于 default/omarchy/omarchy-menu.jsonc,其行为是拉起一个浮动的演示终端并执行 omarchy-windows-vm install;与之对应的 Remove > Windows 菜单项则定义在同文件的 L295 行附近,且仅在检测到 Windows 已安装(存在 windows-vm.desktop)时才显示。

动手安装前,请先确认两个硬性前提:

  • KVM 虚拟化可用。绝大多数现代 CPU 都支持,但有时会在 BIOS 里被关闭。安装脚本会直接检测 /dev/kvm 是否存在:不存在时报错并提示启用虚拟化或手动加载内核模块(Intel 用 modprobe kvm-intel,AMD 用 modprobe kvm-amd),对应逻辑见 bin/omarchy-windows-vm 中的 check_prerequisites。多数情况下这只是进 BIOS 打开一个开关的事。
  • 足够的磁盘空间。你分配给 Windows 的磁盘容量之外,还需要约 10GB 用于存放 Windows 11 安装镜像与系统开销,即总需求 ≈ 分配给 Windows 的容量 + 10GB。脚本用 df 检查的是 实际存放虚拟磁盘 ~/.windows 的那个文件系统的剩余空间,而不是笼统的整个家目录所在分区(见 storage_space_path / available_storage_gb)。若 ~/.windows 已是软链接,则按其指向的真实目录所在文件系统计算,这点对"把虚拟磁盘放到大容量盘上"的用户尤其关键。

安装交互:资源分配、凭据与下载进度

运行安装后,脚本先自动安装 freerdpopenbsd-netcatgum 等依赖(用 omarchy-pkg-add),然后基于当前机器实测到的资源(总内存、CPU 核数)与可用磁盘,用 gum 弹出一系列交互式问题:

提问项 可选范围 / 校验规则 默认值
RAM 大小 {2,4,8,16,32,64}G 中不超过本机总内存的档位 4G
CPU 核数 正整数且不超过本机逻辑核数(1 起步) 2
磁盘容量 {32,64,128,256,512}G 中不超过"可用空间 − 10GB"的档位 64G(不可用时回退 32G
Windows 用户名 字母/数字/_/-,最长 20 字符 docker
Windows 密码 可打印字符,最长 64 字符 admin

从源码可以确认这些交互项的输入一律先经过正则白名单校验(valid_ram/valid_cores/valid_disk/valid_username/valid_password/valid_tz),非法输入会回退到默认值而不是透传下去。磁盘下限是 32GB,因此若可用空间不足 42GB(32G 磁盘 + 10G 镜像)安装会直接中止。配置项确认后还会展示一份摘要并二次确认,随后把时区(timedatectl 读取,失败则 UTC)一并写入配置。

真正耗时的环节是镜像下载,10–15 分钟是正常水平。脚本拉起容器后会自动用浏览器打开 http://127.0.0.1:8006,你可以在这里直观地看到 Windows 的安装进度:

Omarchy Windows VM 安装完成后,通过 Web 控制台访问的 Windows 11 桌面

上图是安装完成后在 Web 控制台里看到的 Windows 11 桌面——注意 8006 端口的控制台同样要求你输入刚才配置的 Windows 用户名和密码,这是刻意的鉴权设计(见后文"安全边界"),因此不要把两个凭据搞混。容器启动时等待客户机就绪的逻辑在 __priv_up_wait:它会锚定本次容器的启动时间轮询 Docker 日志中的 windows started successfully,每 2 秒一次,最多约 2 分钟,超时才会报错。

日常使用:从应用启动器一键进桌面

安装完成后,Omarchy 会生成一个桌面入口 ~/.local/share/applications/windows-vm.desktopName=Windows,执行 uwsm app -- omarchy-windows-vm launch,图标为 windows)。此后只需在应用启动器中搜索并启动 Windows

  • 若虚拟机尚未运行,它会先自动启动(冷启动约需 15–30 秒,期间可能有授权弹窗);
  • 就绪后自动以全屏 RDP 接入桌面,标题为 "Windows VM - Omarchy"。

RDP 会话默认携带 声音输出、麦克风输入与共享剪贴板,在 Linux 与 Windows 之间复制文本是即点即用的。分辨率会跟随窗口大小动态调整(FreeRDP 的 /dynamic-resolution),而 HiDPI 适配也做了处理:启动时会读取 Hyprland 当前聚焦显示器的缩放比例(hyprctl monitors),≥170% 时附加 /scale:180,≥130% 时附加 /scale:140,低于 130% 则不设置缩放、保持默认 100%,避免高分屏上出现模糊的界面。若你的账户名/密码不是默认值,凭据会从用户私有文件 ~/.config/windows/credentials(权限 0600,仅本人可读)读取,不会明文暴露给其他账户。

关闭 RDP 窗口的默认行为是自动关闭虚拟机——脚本在 RDP 退出后会自动执行 docker compose down。如果你有任务需要在里面继续跑、不希望窗口一关就被停机,改用保活模式启动:

omarchy windows vm launch --keep-alive
# 或短选项:omarchy-windows-vm launch -k

其余生命周期控制都集中在同一条命令上:

omarchy windows vm status    # 它现在在运行吗?
omarchy windows vm stop      # 关闭虚拟机
omarchy windows vm launch    # 启动并接入 RDP

这些是文档层面的便捷形式,其底层实现是 bin/omarchy-windows-vm 中的 omarchy-windows-vm status | stop | launch 三个子命令;脚本自带的完整子命令还包括 installremove,运行 omarchy-windows-vm help 可查看全部用法与示例。

值得注意的实现细节:compose 中 restart: "no",意味着虚拟机不会在宿主开机时自动拉起,必须由你显式启动。这既是省资源的默认策略,也被测试 windows-vm-test.sh 固化为契约(断言配置中存在 restart: "no" 且不允许 unless-stopped)。同一份测试还断言了 RDP 窗口在 Hyprland 中的视觉表现:匹配 class = "^xfreerdp$"title = "^Windows VM - Omarchy$" 的窗口会通过 default/hypr/apps/windows-vm.lua 相关的应用规则保持完全不透明(opacity = "1 1")。

生命周期与权限模型(实现侧)

由于该容器运行在特权模式(需要 KVM、/dev/net/tunNET_ADMIN 能力),对 Docker 的每次访问都默认经 polkit(pkexec)授权;若你开启了 sudoless Docker(即已加入 docker 组),则免弹窗直达。需要了解的是:omarchy-windows-vm 每次启动、停止都会触发一次独立的授权,且脚本会把特权进程的 PATH 固定为系统目录、LC_ALL 固定为 C.UTF-8,并只允许执行确认为 root 所有、非用户可写的目标二进制,从根上堵住 PATH 注入与用户态劫持(priv_target 对整条路径逐级校验属主与写权限)。这种对"谁有资格以 root 身份执行什么"的严格约束贯穿整个实现,是理解下文安全设计的前提。

文件共享与安全边界:~/Windows 之外的区域一概不可见

这套方案在文件互通与隔离上做了明确的切分:

  • ~/Windows(共享目录):自动共享给 Windows 客户机,映射为容器内的 /shared。想往 Windows 里带文件,就放进这个目录。
  • ~/.windows(磁盘目录):Windows 自己的虚拟磁盘,映射为容器内的 /storage。安装时你分配的那个 64GB(或更大)空间就落在这里。

客户机对宿主文件系统的其余部分没有任何访问能力——虚拟磁盘之外,Docker 只把上述两个目录挂进容器,因此即使 Windows 侧出了什么乱子,也波及不到你的其他文件。

一些值得展开的细节:

  • 两个目录可以是你拥有的软链接。当虚拟磁盘想放在更大容量的独立分区上时,把 ~/.windows 指过去即可;安装脚本校验可用空间时也以软链接实际指向目录所在文件系统为准。
  • 两者必须是相互独立、互不重叠的目录。删除流程尤其较真:卸载时 remove清空磁盘目录、但刻意保留共享目录,并在任何删除动作之前执行一次有界包含关系校验——从受保护的挂载锚点递归搜索两个目录树,确认谁都不在对方树内(因为 bind 别名可能让同一目录出现第二条父链,仅向上遍历是不够的)。为了避免恶意构造的目录树拖垮特权操作,遍历设有硬性超时(5 秒扫描、1 秒宽限),超时或无法证明两棵树分离时一律拒绝删除。对应测试见 windows-vm-mount-boundary-test.sh

防文件交换的挂载管线

这是整个实现里最值得读源码的部分。为了防止"另一个以你身份运行的进程在路径通过检查后、容器消费前偷换目录"(经典的 TOCTOU 攻击面),启动前的挂载流程是这样的(见 bin/omarchy-windows-vmresolve_caller/open_mount_source/bind_mount_leaf 等函数):

  1. 先把 ~/.windows~/Windows 两个源目录打开并钉住(对目录本身持有文件描述符,并在 /proc/$BASHPID/fd 上记录其 uid|设备号:inode);
  2. 将这两个确切的目录 inode bind-mount 到 root 保护的每用户私有锚点/var/lib/omarchy/windows/mounts/users/<uid>/storage.../shared,锚点树由 root 持有、逐级校验属主与写权限);
  3. Docker 容器只看到这些 root 保护的锚点路径,永远接触不到你 HOME 下的真实路径。

这个设计既保住了"磁盘目录可以是自定义位置/软链接"的灵活性,又保证了特权容器消费的永远是那个刚被校验过的确切 inode——路径名在被检查后被改名或替换,都不会影响已经打开并钉住的那个目录。迁移期间,旧有的磁盘/共享目录会被收紧为 0700 权限,其他本地账户无法浏览其中的内容。

网络与端口的默认封锁

  • 容器端口只绑定到 localhost127.0.0.1:8006(Web 控制台)、127.0.0.1:3389(RDP,TCP/UDP 均有)。因此局域网内任何其他机器都无法摸到这台 Windows。
  • Web 控制台(8006)强制要求配置的 Windows 用户名与密码(compose 中对应 PROTECT: "Y"),防止同一宿主上的其他本地账户通过该端口驱动你的虚拟机。

生成的 compose 文件内容相当直白,核心字段如下(实际文件由安装时生成于 /var/lib/omarchy/windows/docker-compose.ymlimage: dockurr/windows,容器名 omarchy-windows):

services:
  windows:
    image: dockurr/windows
    container_name: omarchy-windows
    environment:
      VERSION: "11"
      RAM_SIZE: "8G"
      CPU_CORES: "4"
      DISK_SIZE: "64G"
      USERNAME: "<你配置的用户名>"
      PASSWORD: "<写入时经过两层转义的密码>"
      PROTECT: "Y"
      TZ: "<你的时区>"
    devices: [/dev/kvm, /dev/net/tun]
    cap_add: [NET_ADMIN]
    ports:
      - 127.0.0.1:8006:8006
      - 127.0.0.1:3389:3389/tcp
      - 127.0.0.1:3389:3389/udp
    volumes:
      - /var/lib/omarchy/windows/mounts/users/<uid>/storage:/storage
      - /var/lib/omarchy/windows/mounts/users/<uid>/shared:/shared
    restart: "no"
    stop_grace_period: 2m

密码在写入前会做两层转义(先对 YAML 解析层转义反斜杠与双引号,再对 compose 变量插值层把 $ 转成 $$),因此密码里即使含 "\$ 也能原样到达客户机。compose 文件归 root 所有、模式 0640,并且只能由提升权限的、经过输入校验的写入动作修改——这一点在文件头部的注释里被强调为"曾经的 ~/.config/windows 版本存在被恶意进程改写、进而借特权 bring-up 把整个磁盘挂进容器的风险,不要移回 $HOME 下"。也就是说,任何以你身份运行的程序都无法改写该文件来请求特权容器执行超出预期的挂载。

调整资源与自定义:重跑安装或手改 compose

想改内存/CPU/磁盘等资源分配,重新运行一遍安装即可omarchy-windows-vm install 会按你的新答案重写虚拟机配置。数据不会被清除——compose 的卷路径在重装/迁移过程中被保留。

如果你需要更深层的自定义(例如把 USB 设备挂进容器),文档允许你用 sudo 手改 /var/lib/omarchy/windows/docker-compose.yml,所有可用选项参见 Dockur Windows 开源项目(本方案即基于该项目的容器方案)。改完用 omarchy windows vm launch 重启生效即可。历史版本若把 compose 放在 ~/.config/windows/ 下,脚本的 migrate_legacy_compose 会在升级后自动把配置迁入新的 root 所有位置,并通过相同的卷路径保留既有虚拟机数据,无需重新下载安装。

限制与许可:没有 GPU 透传的清醒认知

务必理解这套方案的能力边界,文档对此直言不讳:

  • 没有 GPU 透传,因此不适合游戏或视频剪辑这类强图形负载;
  • 它擅长的场景是"把 Microsoft Office 之类非跑不可的 Windows 软件跑起来",属于典型的生产力补充而非游戏方案。

软件版本方面:安装的是 Windows 11 Pro(未激活),使用受门控的功能需要自备正版授权密钥。有一个很容易被忽略的细节:如果你的电脑出厂自带 Windows,OEM 密钥仍留在固件(UEFI/ACPI)里,即使已经整体改装为 Omarchy 也不会消失。用以下命令即可把它打印出来:

omarchy windows key

该密钥与这台机器硬件绑定:它能为"在这台硬件上重装的 Windows"完成激活,但通常不能激活虚拟机——因为虚拟机呈现的硬件与原始固件并不一致。

彻底卸载:Remove > Windows

不需要虚拟机时,通过 Omarchy 菜单的 Remove > Windows(即 omarchy-windows-vm remove)整体移除。这一步会先要求确认,然后:停止并删除容器、移除镜像、删除虚拟磁盘目录 ~/.windows 及其中的数据,同时保留共享目录 ~/Windows。因此文档特别提醒:删除前务必先把任何还需要的文件从 ~/Windows 挪出来。

从实现上看,remove 是唯一会在删除前执行"递归式 bind 别名证明"的路径:它会先重建并核对两个受保护挂载、确认没有额外的或叠加的挂载层、确认容器确已停止且 Docker 状态可验证,再做包含关系校验与 find -xdev 的定向清空——-xdev 保证遍历绝不跨入其它已挂载文件系统。任何一步校验失败都会中止删除并保留数据,宁可失败也不误删。对应的防回归测试见 windows-vm-compose-test.shwindows-key-test.sh(后者守护 OEM 密钥打印功能)。

命令速查

目的 命令
首次安装 / 重新配置资源 omarchy-windows-vm install
启动并全屏 RDP 接入(关窗即停) omarchy windows vm launch
启动并保持运行 omarchy windows vm launch --keep-alive(或 -k
查询运行状态 omarchy windows vm status
手动停止 omarchy windows vm stop
打印固件中的 OEM Windows 密钥 omarchy windows key
彻底卸载(清空虚拟磁盘) omarchy-windows-vm remove(或菜单 Remove > Windows)
安装进度监控 浏览器访问 http://127.0.0.1:8006

文中所有实现层面的描述均可在仓库源码中复核:核心逻辑集中在 bin/omarchy-windows-vm,菜单入口见 default/omarchy/omarchy-menu.jsonc,行为契约则由 test/shell.d/windows-vm-test.shwindows-vm-mount-boundary-test.shwindows-vm-compose-test.shwindows-key-test.sh 共同守护。如果你正在评估"在 Linux 桌面上有没有一台够用的 Windows",Omarchy 这条 Docker + KVM + RDP 的路线以极少的配置成本换来了清晰隔离与完整生命周期管理,值得直接上手一试。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
898
5.82 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
921
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.8 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
596
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
519
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
391