File: README.md
Run Windows applications (including Microsoft 365 and Adobe Creative Cloud) on GNU/Linux with KDE Plasma, GNOME or XFCE, integrated seamlessly as if they were native to the OS.
Underlying Mechanism
WinApps works by:
- Running Windows in a
Docker,Podmanorlibvirtvirtual machine. - Querying Windows for all installed applications.
- Creating shortcuts to selected Windows applications on the host GNU/Linux OS.
- Using
FreeRDPas a backend to seamlessly render Windows applications alongside GNU/Linux applications.
Additional Features
- The GNU/Linux
/homedirectory is accessible within Windows via the\\tsclient\homemount. - Integration with
Nautilus, allowing you to right-click files to open them with specific Windows applications based on the file MIME type. - The official taskbar widget enables seamless administration of the Windows subsystem and offers an easy way to launch Windows applications.
- Microsoft Office links (e.g. ms-word://) from the host system are automatically opened in the Windows subsystem. (Note: You may need to use a User Agent Switcher browser extension and set the User-Agent to Windows, as the Office webapps typically hide the "Open in Desktop App" option for Linux users.)
Supported Applications
WinApps supports ALL Windows applications. Support does not, however, extend to kernel-level anti-cheat systems (e.g. Riot Vanguard).
Universal application support is achieved by:
- Scanning Windows for any community tested applications (list below).
- Scanning Windows for any other
.exefiles listed within the Windows Registry.
Community tested applications benefit from high-resolution icons and pre-populated MIME types. This enables file managers to determine which Windows applications should open files based on file extensions. Icons for other detected applications are pulled from .exe files.
Contributing to the list of supported applications is encouraged through submission of pull requests! Please help us grow the WinApps community.
Please note that the provided list of community tested applications is community-driven. As such, some applications may not be tested and verified by the WinApps team.
Community Tested Applications
| | Adobe Acrobat Pro
(X)
Icon in the Public Domain. | | Adobe After Effects
(CC)
Icon in the Public Domain. | | | | |
| --- | --- | --- | --- | --- | --- | --- | --- |
| | Adobe Audition
(CC)
Icon in the Public Domain. | | Adobe Bridge
(CS6, CC)
Icon in the Public Domain. | | | | |
| | Adobe Creative Cloud
(CC)
Icon under MIT license. | | Adobe Illustrator
(CC)
Icon in the Public Domain. | | | | |
| | Adobe InDesign
(CC)
Icon in the Public Domain. | | Adobe Lightroom
(CC)
Icon in the Public Domain. | | | | |
| | Adobe Photoshop
(CS6, CC, 2022)
Icon in the Public Domain. | | Affinity Designer 2
Icon under CC-BY-SA 4.0 via Serif Ltd. | | | | |
| | Affinity Photo 2
Icon under CC-BY-SA 4.0 via Serif Ltd. | | Affinity Publisher 2
Icon under CC-BY-SA 4.0 via Serif Ltd. | | Affinity by Canva (v3)
Icon in the Public Domain. | | Command Prompt
(cmd.exe)
Icon under MIT license. |
| | File Explorer
(Windows Explorer)
Icon in the Public Domain. | | Internet Explorer
(11)
Icon in the Public Domain. | | | | |
| | Microsoft Access
(2016, 2019, o365)
Icon in the Public Domain. | | Microsoft Excel
(2016, 2019, o365)
Icon in the Public Domain. | | | | |
| | Microsoft Word
(2016, 2019, o365)
Icon in the Public Domain. | | Microsoft OneNote
(2016, 2019, o365)
Icon in the Public Domain. | | | | |
| | Microsoft Outlook
(2016, 2019, o365)
Icon in the Public Domain. | | Microsoft PowerPoint
(2016, 2019, o365)
Icon in the Public Domain. | | | | |
| | Microsoft Publisher
(2016, 2019, o365)
Icon in the Public Domain. | | Microsoft Visio
(Standard/Pro. 2021, Plan 2)
Icon in the Public Domain. | | | | |
| | Microsoft Project
(Standard/Pro. 2021, Plan 3/5)
Icon in the Public Domain. | | Microsoft Visual Studio
(Comm./Pro./Ent. 2022)
Icon in the Public Domain. | | | | |
| | Autodesk Fusion 360
Icon in the Public Domain. | | mIRC
Icon in the Public Domain. | | | | |
| | PowerShell
Icon under MIT license. | | Windows
(Full RDP Session)
Icon in the Public Domain. | | | | |
Installation
Step 1: Configure a Windows VM
Both Docker and Podman are recommended backends for running the Windows virtual machine, as they facilitate an automated Windows installation process. WinApps is also compatible with libvirt. While this method requires considerably more manual configuration, it also provides greater virtual machine customisation options. All three methods leverage the KVM hypervisor, ensuring excellent virtual machine performance. Ultimately, the choice of backend depends on your specific use case.
The following guides are available:
If you already have a Windows VM or server you wish to use with WinApps, you will still have to follow the final steps described in the libvirt documentation.
Step 2: Install Dependencies
Install the required dependencies.
- Debian/Ubuntu:bash
sudo apt install -y curl dialog freerdp3-x11 git iproute2 libnotify-bin netcat-openbsd
[!NOTE]
On Debian 12 ("bookworm"), you need to enable thebackportsrepository for thefreerdp3-x11package to become available.
For instructions, see https://backports.debian.org/Instructions.
- Fedora/RHEL:bash
sudo dnf install -y curl dialog freerdp git iproute libnotify nmap-ncat - Arch Linux:bash
sudo pacman -Syu --needed -y curl dialog freerdp git iproute2 libnotify openbsd-netcat - openSUSE:bash
sudo zypper install -y curl dialog freerdp git iproute2 libnotify-tools netcat-openbsd - Gentoo Linux:bash
sudo emerge --ask=n net-misc/curl dev-util/dialog net-misc/freerdp:3 dev-vcs/git sys-apps/iproute2 x11-libs/libnotify net-analyzer/openbsd-netcat
[!NOTE]
WinApps requiresFreeRDPversion 3 or later, the newer, the better. If it is not available in your distribution's packages, try compiling from source according to this guide or grab the package from a third party package manager like Homebrew or Nix.
Alternatively, you can try using the Flatpak. However, this is not recommended as it can cause sandboxing-related issues. If you use Flatpak, run the following command once to allow the use of+home-drive:bashsudo flatpak override --filesystem=home com.freerdp.FreeRDP
Step 3: Create a WinApps Configuration File
Create a configuration file at ~/.config/winapps/winapps.conf containing the following:
/* Detailed source-code truncated for AI context efficiency. */[!IMPORTANT]
To safeguard your Windows password, ensure~/.config/winapps/winapps.confis accessible only by your user account.bashchown $(whoami):$(whoami) ~/.config/winapps/winapps.conf chmod 600 ~/.config/winapps/winapps.conf
[!IMPORTANT]
RDP_USERandRDP_PASSmust correspond to a complete Windows user account and password, such as those created during Windows setup or for a domain user. User/PIN combinations are not valid for RDP access.
[!IMPORTANT]
If you wish to use an alternative WinApps backend (other thanDocker), uncomment and changeWAFLAVOR="docker"toWAFLAVOR="podman"orWAFLAVOR="libvirt".
Configuration Options Explained
- If using a pre-existing Windows RDP server on your LAN, you must use
RDP_IPto specify the location of the Windows server. You may also wish to configure a static IP address for this server. - If running a Windows VM using
libvirtwith NAT enabled, leaveRDP_IPcommented out and WinApps will auto-detect the local IP address for the VM. - For domain users, you can uncomment and change
RDP_DOMAIN. - On high-resolution (UHD) displays, you can set
RDP_SCALEto the scale you would like to use (100, 140 or 180). - To add additional flags to the FreeRDP call (e.g.
/prevent-session-lock 120), uncomment and use theRDP_FLAGSconfiguration option. - For multi-monitor setups, you can try adding
/multimontoRDP_FLAGS. A FreeRDP bug may result in a black screen however, in which case you should revert this change. - To enable non-English input and seamless language switching, you can try adding
/kbd:unicodetoRDP_FLAGS. This ensures client inputs are sent as Unicode sequences. - If you enable
DEBUG, a log will be created on each application start in~/.local/share/winapps/winapps.log. - If using a system on which the FreeRDP command is not
xfreerdporxfreerdp3, the correct command can be specified usingFREERDP_COMMAND.
Step 4: Test FreeRDP
Test establishing an RDP session by running the following command, replacing the
/u:,/p:, and/v:values with the correct values specified in~/.config/winapps/winapps.conf.bashxfreerdp3 /u:"MyWindowsUser" /p:"MyWindowsPassword" /v:127.0.0.1:3389 /cert:tofu # Or, if you are using Podman podman unshare --rootless-netns xfreerdp3 /u:"MyWindowsUser" /p:"MyWindowsPassword" /v:127.0.0.1:3389 /cert:tofu # Or, if you installed FreeRDP using Flatpak flatpak run --command=xfreerdp com.freerdp.FreeRDP /u:"MyWindowsUser" /p:"MyWindowsPassword" /v:127.0.0.1:3389 /cert:tofu- Please note that the correct
FreeRDPcommand may vary depending on your system (e.g.xfreerdp,xfreerdp3, etc.). - Ensure you use the correct IP address for your Windows instance in the above command.
- If prompted within the terminal window, choose to accept the certificate permanently.
If the Windows desktop appears in a
FreeRDPwindow, the configuration was successful and the correct RDP TLS certificate was enrolled on the Linux host. Disconnect from the RDP session and skip the following debugging step.- Please note that the correct
[DEBUGGING STEP] If an outdated or expired certificate is detected, the
FreeRDPcommand will display output resembling the following. In this case, the old certificate will need to be removed and a new RDP TLS certificate installed.text@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: CERTIFICATE NAME MISMATCH! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ The hostname used for this connection (192.168.122.2:3389) does not match the name given in the certificate: Common Name (CN): RDPWindows A valid certificate for the wrong name should NOT be trusted! The host key for 192.168.122.2:3389 has changed @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! Someone could be eavesdropping on you right now (man-in-the-middle attack)! It is also possible that a host key has just been changed. The fingerprint for the host key sent by the remote host is 8e:b4:d2:8e:4e:14:e7:4e:82:9b:07:5b:e1:68:40:18:bc:db:5f:bc:29:0d:91:83:f9:17:f9:13:e6:51:dc:36 Please contact your system administrator. Add correct host key in /home/rohanbarar/.config/freerdp/server/192.168.122.2_3389.pem to get rid of this message.If you experience the above error, delete any old or outdated RDP TLS certificates associated with Windows, as they can prevent
FreeRDPfrom establishing a connection.These certificates are located within
~/.config/freerdp/server/and follow the naming format<Windows-VM-IPv4-Address>_<RDP-Port>.pem(e.g.,192.168.122.2_3389.pem,127.0.0.1_3389.pem, etc.).If you use FreeRDP for purposes other than WinApps, ensure you only remove certificates related to the relevant Windows VM. If no relevant certificates are found, no action is needed.
Following deletion, re-attempt establishing an RDP session.
Step 5: Run the WinApps Installer
With Windows still powered on, run the WinApps installer.
bash <(curl https://raw.githubusercontent.com/winapps-org/winapps/main/setup.sh)Once WinApps is installed, a list of additional arguments can be accessed by running winapps-setup --help.
Managing apps post-installation
Redetect and add new apps installed in Windows using the WinApps Install Wizard
The initial setup process will detect any Community Tested Applications and any additionally detected applications and make them available in your Linux application menu. If in the future you install a new application in Windows and want to add it to WinApps, you need to run the winapps-setup again to detect the new application(s).
The setup command has a number of options that can be passed to it:
winapps-setup --help
Usage:
--user # Install WinApps and selected applications in /home/$(whoami)
--system # Install WinApps and selected applications in /usr
--user --setupAllOfficiallySupportedApps # Install WinApps and all officially supported applications in /home/$(whoami)
--system --setupAllOfficiallySupportedApps # Install WinApps and all officially supported applications in /usr
--user --uninstall # Uninstall everything in /home/$(whoami)
--system --uninstall # Uninstall everything in /usr
--user --add-apps # Add new applications to existing installation in /home/$(whoami)
--system --add-apps # Add new applications to existing installation in /usr
--help # Display this usage message.To re-run the app detection, run the setup like
winapps-setup --user --add-appsThis will bring up the familiar setup wizard screen and you step through the wizard as above choosing the apps you wish to make available. Note that if your Windows VM is not yet running, the setup will exit and tell you to start the VM first.
Adding Additional Pre-defined Applications
Adding your own applications with custom icons and MIME types to the installer is easy. Simply copy one of the application configurations in the apps folder located within the WinApps repository, and:
- Modify the name and variables to reflect the appropriate/desired values for your application.
- Replace
icon.svgwith an SVG for your application (ensuring the icon is appropriately licensed). - Remove and reinstall WinApps.
- Submit a pull request to add your application to WinApps as a community tested application once you have tested and verified your configuration (optional, but encouraged).
Running Applications Manually
WinApps offers a manual mode for running applications that were not configured by the WinApps installer. This is completed with the manual flag. Executables that are in the Windows PATH do not require full path definition.
winapps manual "C:\my\directory\executableNotInPath.exe"
winapps manual executableInPath.exeUpdating WinApps
The installer can be run multiple times. To update your installation of WinApps:
- Run the WinApps installer to remove WinApps from your system.
- Pull the latest changes from the WinApps GitHub repository.
- Re-install WinApps using the WinApps installer by running
winapps-setup.
WinApps Launcher (Optional)
The WinApps Launcher provides a simple system tray menu that makes it easy to launch your installed Windows applications, open a full desktop RDP session, and control your Windows VM or container. You can start, stop, pause, reboot or hibernate Windows, as well as access your installed applications from a convenient list. This lightweight, optional tool helps streamline your overall WinApps experience.
Installation using Nix
First, follow Step 1 of the normal installation guide to create your VM.
Then, install WinApps according to the following instructions.
After installation, it will be available under winapps, with the installer being available under winapps-setup
and the optional launcher being available under winapps-launcher.
Using standalone Nix
First, make sure Flakes and the nix command are enabled.
In your ~/.config/nix/nix.conf:
experimental-features = nix-command flakesnix profile install github:winapps-org/winapps#winapps
nix profile install github:winapps-org/winapps#winapps-launcher # optionalOn NixOS using Flakes
# flake.nix
{
description = "My configuration";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
winapps = {
url = "github:winapps-org/winapps";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs =
inputs@{
nixpkgs,
winapps,
...
}:
{
nixosConfigurations.hostname = nixpkgs.lib.nixosSystem rec {
system = "x86_64-linux";
specialArgs = {
inherit inputs system;
};
modules = [
./configuration.nix
(
{
pkgs,
system ? pkgs.system,
...
}:
{
environment.systemPackages = [
winapps.packages."${system}".winapps
winapps.packages."${system}".winapps-launcher # optional
];
# set up binary cache (optional)
nix.settings = {
substituters = [ "https://winapps.cachix.org/" ];
trusted-public-keys = [ "winapps.cachix.org-1:HI82jWrXZsQRar/PChgIx1unmuEsiQMQq+zt05CD36g=" ];
trusted-users = [ "<your username>" ]; # replace with your username
};
}
)
];
};
};
}On NixOS without Flakes
Flakes aren't real and they can't hurt you..
However, if you still don't want to use flakes, you can use WinApps with flake-compat like:
# configuration.nix
{
pkgs,
system ? pkgs.system,
...
}:
{
# set up binary cache (optional)
nix.settings = {
substituters = [ "https://winapps.cachix.org/" ];
trusted-public-keys = [ "winapps.cachix.org-1:HI82jWrXZsQRar/PChgIx1unmuEsiQMQq+zt05CD36g=" ];
trusted-users = [ "<your username>" ]; # replace with your username
};
environment.systemPackages =
let
winapps =
(import (builtins.fetchTarball "https://github.com/winapps-org/winapps/archive/main.tar.gz"))
.packages."${system}";
in
[
winapps.winapps
winapps.winapps-launcher # optional
];
}Star History
File: docs/docker.md
Creating a Windows VM in `Docker` or `Podman`
Although WinApps supports using QEMU+KVM+libvirt as a backend for running Windows virtual machines, it is recommended to use Docker or Podman. These backends automate the setup process, eliminating the need for manual configuration and optimisation of the Windows virtual machine.
[!IMPORTANT]
Running a Windows virtual machine usingDockerorPodmanas a backend is only possible on GNU/Linux systems. This is due to the necessity of kernel interfaces, such as the KVM hypervisor, for achieving acceptable performance. The performance of the virtual machine can vary based on the version of the Linux kernel, with newer releases generally offering better performance.
[!IMPORTANT]
WinApps does NOT officially support versions of Windows prior to Windows 10. Despite this, it may be possible to achieve a successful installation with some additional experimentation. If you find a way to achieve this, please share your solution through a pull request for the benefit of other users.
Possible setup instructions for Windows 10:
- 'Professional', 'Enterprise' or 'Server' editions of Windows are required to run RDP applications. Windows 'Home' will NOT suffice.
- It is recommended to edit the initial
compose.yamlfile to keep your required username and password from the beginning.- It is recommended to not use
sudoto force commands to run. Add your user to the relevant permissions group wherever possible.
[!IMPORTANT]
The iptables kernel module must be loaded for folder sharing with the host to work.
Check that the output oflsmod | grep ip_tablesandlsmod | grep iptable_natis non-empty.
If the output of one of the previous commands is empty, runecho -e "ip_tables\niptable_nat" | sudo tee /etc/modules-load.d/iptables.confand reboot.
`Docker`
Installation
You can find a guide for installing Docker Engine here.
Setup `Docker` Container
WinApps utilises docker compose to configure Windows VMs. A template compose.yaml is provided.
Prior to installing Windows, you can modify the RAM and number of CPU cores available to the Windows VM by changing RAM_SIZE and CPU_CORES within compose.yaml.
It is also possible to specify the version of Windows you wish to install within compose.yaml by modifying VERSION.
Please refer to the original GitHub repository for more information on additional configuration options.
[!NOTE]
If you want to undo all your changes and start from scratch, run the following. Forpodman, replacedocker composewithpodman-compose.bashdocker compose down --rmi=all --volumes
Installing Windows
You can initiate the Windows installation using docker compose.
cd winapps
docker compose --file ./compose.yaml upYou can then access the Windows virtual machine via a VNC connection to complete the Windows setup by navigating to http://127.0.0.1:8006 in your web browser.
Changing `compose.yaml`
Changes to compose.yaml require the container to be removed and re-created. This should NOT affect your data.
# Stop and remove the existing container.
docker compose --file ~/.config/winapps/compose.yaml down
# Remove the existing FreeRDP certificate (if required).
# Note: A new certificate will be created when connecting via RDP for the first time.
# If you configured a custom RDP_PORT, replace 3389 with that port.
rm ~/.config/freerdp/server/127.0.0.1_3389.pem
# Re-create the container with the updated configuration.
# Add the -d flag at the end to run the container in the background.
docker compose --file ~/.config/winapps/compose.yaml upSubsequent Use
docker compose --file ~/.config/winapps/compose.yaml start # Power on the Windows VM
docker compose --file ~/.config/winapps/compose.yaml pause # Pause the Windows VM
docker compose --file ~/.config/winapps/compose.yaml unpause # Resume the Windows VM
docker compose --file ~/.config/winapps/compose.yaml restart # Restart the Windows VM
docker compose --file ~/.config/winapps/compose.yaml stop # Gracefully shut down the Windows VM
docker compose --file ~/.config/winapps/compose.yaml kill # Force shut down the Windows VM`Podman`
Installation
- Install
Podmanusing this guide. - Install
podman-composeusing this guide.
Setup `Podman` Container
Please follow the docker instructions.
[!NOTE]
Rootless `podman` containers
If you are invoking podman as a user, your container will be "rootless". This can be desirable as a security feature. However, you may encounter an error about missing permissions to /dev/kvm as a consequence.
For rootless podman to work, you need to add your user to the
kvmgroup (depending on your distribution) to be able to access/dev/kvm. Make sure that you are usingcrunas your container runtime, notrunc. Usually this is done by stopping all containers and (de-)installing the corresponding packages. Then either invoke podman-compose aspodman-compose --file ./compose.yaml --podman-create-args '--group-add keep-groups' up. Or editcompose.yamland uncomment thegroup_add:section at the end, and add[].
[!IMPORTANT]
EnsureWAFLAVORis set to"podman"in~/.config/winapps/winapps.conf.
Installing Windows
You can initiate the Windows installation using podman-compose.
cd winapps
podman-compose --file ./compose.yaml upYou can then access the Windows virtual machine via a VNC connection to complete the Windows setup by navigating to http://127.0.0.1:8006 in your web browser.
Changing `compose.yaml`
Changes to compose.yaml require the container to be removed and re-created. This should NOT affect your data.
# Stop and remove the existing container.
podman-compose --file ~/.config/winapps/compose.yaml down
# Remove the existing FreeRDP certificate (if required).
# Note: A new certificate will be created when connecting via RDP for the first time.
# If you configured a custom RDP_PORT, replace 3389 with that port.
rm ~/.config/freerdp/server/127.0.0.1_3389.pem
# Re-create the container with the updated configuration.
podman-compose --file ~/.config/winapps/compose.yaml upSubsequent Use
podman-compose --file ~/.config/winapps/compose.yaml start # Power on the Windows VM
podman-compose --file ~/.config/winapps/compose.yaml pause # Pause the Windows VM
podman-compose --file ~/.config/winapps/compose.yaml unpause # Resume the Windows VM
podman-compose --file ~/.config/winapps/compose.yaml restart # Restart the Windows VM
podman-compose --file ~/.config/winapps/compose.yaml stop # Gracefully shut down the Windows VM
podman-compose --file ~/.config/winapps/compose.yaml kill # Force shut down the Windows VMFile: docs/libvirt.md
Creating a `libvirt` Windows VM
This method of configuring a Windows virtual machine for use with WinApps is significantly more involved than utilising Docker or Podman. Nevertheless, expert users may prefer this method due to its greater flexibility and wider range of customisation options (e.g. GPU passthrough).
Understanding The Virtualisation Stack
Before beginning, it is important to have a basic understanding of the various components involved in this particular method.
QEMUis a FOSS emulator that performs hardware virtualisation, enabling operating systems and applications designed for one architecture (e.g., aarch64) to run on systems with differing architectures (e.g., amd64). When used in conjunction withKVM, it can run virtual machines at near-native speed (provided the guest virtual machine matches the host architecture) by utilising hardware extensions like Intel VT-x or AMD-V.KVMis a Linux kernel module that enables the kernel to function as a type-1 hypervisor.KVMruns directly on the underlying hardware (as opposed to on top of the GNU/Linux host OS). For many workloads, the performance overhead is minimal, often in the range of 2-5%.KVMrequires a CPU with hardware virtualisation extensions.libvirtis an open-source API, daemon, and management tool for orchestrating platform virtualisation. It provides a consistent and stable interface for managing various virtualisation technologies, includingKVMandQEMU(as well as others).libvirtoffers a wide range of functionality to control the lifecycle of virtual machines, storage, networks, and interfaces, making it easier to interact with virtualisation capabilities programmatically or via command-line tools.virt-manager(Virtual Machine Manager) is a GUI desktop application that provides an easy-to-use interface for creating, configuring and controlling virtual machines.virt-managerutiliseslibvirtas a backend.
Together, these components form a powerful and flexible virtualization stack, with KVM providing low-level kernel-based virtualisation capabilities, QEMU providing high-level userspace-based virtualisation functionality, libvirt managing the resources and virt-manager offering an intuitive graphical management interface.
Prerequisites
Ensure your CPU supports hardware virtualisation extensions by reading this article.
Install all dependencies by installing
virt-manager. This will ensure that your package manager automatically installs all the necessary components.bashsudo apt install virt-manager # Debian/Ubuntu sudo dnf install virt-manager # Fedora/RHEL sudo pacman -S virt-manager # Arch Linux sudo emerge app-emulation/virt-manager # Gentoo LinuxConfigure
libvirtto use the 'system' URI by adding the lineLIBVIRT_DEFAULT_URI="qemu:///system"to your preferred shell profile file (e.g.,.bashrc,.zshrc, etc.).bashecho 'export LIBVIRT_DEFAULT_URI="qemu:///system"' >> ~/.bashrc
[!NOTE]
WinApps may not read your shell's configuration. If you're having issues getting the installer to detect your VM, try addingLIBVIRT_DEFAULT_URI="qemu:///system"to your/etc/environmentlike:bashecho 'LIBVIRT_DEFAULT_URI="qemu:///system"' | sudo tee -a /etc/environmentThanks to imoize for pointing this out: https://github.com/winapps-org/winapps/issues/310#issuecomment-2505348088
Configure rootless
libvirtandkvmby adding your user to groups of the same name.bashsudo usermod -a -G kvm $(id -un) # Add the user to the 'kvm' group. sudo usermod -a -G libvirt $(id -un) # Add the user to the 'libvirt' group. sudo reboot # Reboot the system to ensure the user is added to the relevant groups.Note: On NixOS, the group name for libvirt is
libvirtdand notlibvirt. In addition, user and group management on NixOS is handled through the Nix configuration files and not via traditional tools likeusermod. Please see "Adding User to a group" on this NixOS Wiki page.Note: Due to a known bug in
rpm-ostree, which affects various distributions such as Silverblue, Bazzite, Bluefin, Kinoite, Aurora, UCore, and others, the commands provided earlier may not properly add your user to all required groups. If thegroups $USERcommand does not show your user as being part of the necessary groups, you'll need to manually add these groups to/etc/groupif they are present in/usr/lib/group.To resolve this:
Identify which groups are missing from the output of
groups $USER.Use the following snippet to add each missing group to
/etc/group. Ensure you replace "kvm" with the name of the missing group.bashgrep -E '^kvm:' /usr/lib/group | sudo tee -a /etc/group sudo usermod -aG kvm $USERReboot your system to ensure that the user is correctly added to the relevant groups.
If relevant to your distribution, disable
AppArmorfor thelibvirtdaemon.bashsudo ln -s /etc/apparmor.d/usr.sbin.libvirtd /etc/apparmor.d/disable/ # Disable AppArmor for the libvirt daemon by creating a symbolic link.
[!NOTE]
Systems withSELinuxmay also require security policy adjustments if virtual machine images are stored outside the default/var/lib/libvirt/imagesdirectory. Read this guide for more information.
- Download a Windows 10 or Windows 11 installation
.ISOimage.
[!IMPORTANT]
'Professional', 'Enterprise' or 'Server' editions of Windows are required to run RDP applications. Windows 'Home' will NOT suffice.
- Download VirtIO drivers for the Windows virtual machine.
[!NOTE]
VirtIO drivers enhance system performance and minimize overhead by enabling the Windows virtual machine to use specialised network and disk device drivers. These drivers are aware that they are operating inside a virtual machine, and cooperate with the hypervisor. This approach eliminates the need for the hypervisor to emulate physical hardware devices, which is a computationally expensive process. This setup allows guests to achieve high-performance network and disk operations, leveraging the benefits of paravirtualisation.
The above link contains the latest release of theVirtIOdrivers for Windows, compiled and signed by Red Hat. Older versions of theVirtIOdrivers can be downloaded here.
You can read more aboutVirtIOhere and here.
Creating a Windows VM
- Open
virt-manager.
[!NOTE]
The name given to the application can vary between GNU/Linux distributions (e.g., 'Virtual Machines', 'Virtual Machine Manager', etc.)
Navigate to
Edit→Preferences. EnsureEnable XML editingis enabled, then click theClosebutton.Create a new virtual machine by clicking the
+button.Choose
Local install mediaand clickForward.Select the location of your Windows 10 or 11
.ISOby clickingBrowse...andBrowse Local. EnsureAutomatically detect from the installation media / sourceis enabled.Configure the RAM and CPU cores allocated to the Windows virtual machine. We recommend
2CPUs and4096MBof RAM. We will use theVirtIOMemory Ballooning service, which means the virtual machine can use up to4096MBof memory, but it will only consume this amount if necessary.Configure the virtual disk by setting its maximum size. While this size represents the largest it can grow to, the disk will only use this space as needed.
Name your virtual machine
RDPWindowsto ensure it is recognized by WinApps, and select the option toCustomize configuration before installation.
[!NOTE]
A name other thanRDPWindowscan be used ifVM_NAMEis set in~/.config/winapps/winapps.conf.
- After clicking
Finish, selectCopy host CPU configurationunder 'CPUs', and then clickApply.
[!NOTE]
Sometimes this feature gets disabled after installing Windows. Make sure to check and re-enable this option after the installation is complete.
Navigate to the
XMLtab, and edit the<clock>section to disable all timers except for the hypervclock, thereby drastically reducing idle CPU usage. Once changed, clickApply.xml<clock offset='localtime'> <timer name='rtc' present='no' tickpolicy='catchup'/> <timer name='pit' present='no' tickpolicy='delay'/> <timer name='hpet' present='no'/> <timer name='kvmclock' present='no'/> <timer name='hypervclock' present='yes'/> </clock>Enable Hyper-V enlightenments by adding the following to the
<hyperv>section. Once changed, clickApply.xml<hyperv> <relaxed state='on'/> <vapic state='on'/> <spinlocks state='on' retries='8191'/> <vpindex state='on'/> <synic state='on'/> <stimer state='on'> <direct state='on'/> </stimer> <reset state='on'/> <frequencies state='on'/> <reenlightenment state='on'/> <tlbflush state='on'/> </hyperv>
[!NOTE]
Hyper-V enlightenments make Windows (and other Hyper-V guests) think they are running on top of a Hyper-V compatible hypervisor. This enables use of Hyper-V specific features, allowingKVMto implement paravirtualised interfaces for improved virtual machine performance.
Add the following XML snippet within the
<devices>section to enable the GNU/Linux host to communicate with Windows usingQEMU Guest Agent.xml<channel type='unix'> <target type='virtio' name='org.qemu.guest_agent.0'/> <address type='virtio-serial' controller='0' bus='0' port='2'/> </channel>In the 'Memory' section, set the
Current allocationto the minimum amount of memory you want the virtual machine to use, with a recommended value of1024MB.
[!NOTE]
Depending upon certain apps (like OneDrive), the balloon driver cannot keep up. If you are having segfaults (random reboots), turn off memory ballooning.<memballoon model="none"/>
(Optional) Under
Boot Options, enableStart virtual machine on host boot up.Navigate to 'SATA Disk 1' and set the
Disk bustype toVirtIO. This allows disk access to be paravirtualised, improving virtual machine performance.Navigate to 'NIC' and set the
Device modeltype tovirtioto enable paravirtualised networking.
[!NOTE]
virtiois the recommended device model and should be used for normal operation. If you specifically want internet access during the Windows installation (for example, to sign in with a Microsoft account), you may temporarily set the device model toe1000e. After installation and VirtIO driver setup are complete, switch the NIC back tovirtiofor best performance.
- Click the
Add Hardwarebutton in the lower left, and chooseStorage. ForDevice type, selectCDROM deviceand choose the VirtIO driver.ISOyou downloaded earlier. ClickFinishto add the new CD-ROM device.
[!IMPORTANT]
If you skip this step, the Windows installer will fail to recognise and list the virtual hard drive you created earlier.
(Optional) Assign Specific Physical CPU Cores
Assigning specific physical CPU cores to the virtual machine can improve performance by reducing context switching and ensuring that the virtual machine's workload consistently uses the same cores, leading to better CPU cache utilisation. This is an optional step.
Run
lscpu -eto determine which L1, L2 and L3 caches are associated with which CPU cores.Example 1 (Intel 11th Gen Core i7-1185G7):
textCPU NODE SOCKET CORE L1d:L1i:L2:L3 ONLINE MAXMHZ MINMHZ 0 0 0 0 0:0:0:0 yes 4800.0000 400.0000 1 0 0 1 1:1:1:0 yes 4800.0000 400.0000 2 0 0 2 2:2:2:0 yes 4800.0000 400.0000 3 0 0 3 3:3:3:0 yes 4800.0000 400.0000 4 0 0 0 0:0:0:0 yes 4800.0000 400.0000 5 0 0 1 1:1:1:0 yes 4800.0000 400.0000 6 0 0 2 2:2:2:0 yes 4800.0000 400.0000 7 0 0 3 3:3:3:0 yes 4800.0000 400.0000- C0 = T0+T4 → L10+L20+L30
- C1 = T1+T5 → L11+L21+L30
- C2 = T2+T6 → L12+L22+L30
- C3 = T3+T7 → L13+L23+L30
Example 2 (AMD Ryzen 5 1600):
textCPU NODE SOCKET CORE L1d:L1i:L2:L3 ONLINE MAXMHZ MINMHZ 0 0 0 0 0:0:0:0 yes 3800.0000 1550.0000 1 0 0 0 0:0:0:0 yes 3800.0000 1550.0000 2 0 0 1 1:1:1:0 yes 3800.0000 1550.0000 3 0 0 1 1:1:1:0 yes 3800.0000 1550.0000 4 0 0 2 2:2:2:0 yes 3800.0000 1550.0000 5 0 0 2 2:2:2:0 yes 3800.0000 1550.0000 6 0 0 3 3:3:3:1 yes 3800.0000 1550.0000 7 0 0 3 3:3:3:1 yes 3800.0000 1550.0000 8 0 0 4 4:4:4:1 yes 3800.0000 1550.0000 9 0 0 4 4:4:4:1 yes 3800.0000 1550.0000 10 0 0 5 5:5:5:1 yes 3800.0000 1550.0000 11 0 0 5 5:5:5:1 yes 3800.0000 1550.0000- C0 = T0+T1 → L10+L20+L30
- C1 = T2+T3 → L11+L21+L30
- C2 = T4+T5 → L12+L22+L30
- C3 = T6+T7 → L13+L23+L31
- C4 = T8+T9 → L14+L24+L31
- C5 = T10+T11 → L15+L25+L31
Select which CPU cores to 'pin'. You should aim to select a combination of CPU cores that minimises sharing of caches between Windows and GNU/Linux.
Example 1:
- CPU cores share the same singular L3 cache, so this cannot be optimised.
- CPU cores utilise different L1 and L2 caches, so isolating corresponding thread pairs will help improve performance.
- Thus, if limiting the virtual machine to a maximum of 4 threads, there are 10 possible optimal configurations:
- T0+T4
- T1+T5
- T2+T6
- T3+T7
- T0+T4+T1+T5
- T0+T4+T2+T6
- T0+T4+T3+T7
- T1+T5+T2+T6
- T1+T5+T3+T7
- T2+T6+T3+T7
Example 2:
- Threads 0-5 utilise one L3 cache whereas threads 6-11 utilise a different L3 cache. Thus, one of these two sets of threads should be pinned to the virtual machine.
- Pinning and isolating fewer than these (e.g. threads 8-11) would result in the host system making use of the L3 cache in threads 6 and 7, resulting in cache evictions and therefore bad performance.
- Thus, there are only two possible optimal configurations:
- T0+T1+T2+T3+T4+T5
- T6+T7+T8+T9+T10+T11
Prepare and add/modify the following to the
<vcpu>,<cputune>and<cpu>sections, adjusting the values to match your selected threads.Example 1: The following selects 'T2+T6+T3+T7'.
xml<vcpu placement="static">4</vcpu> <cputune> <vcpupin vcpu="0" cpuset="2"/> <vcpupin vcpu="1" cpuset="6"/> <vcpupin vcpu="2" cpuset="3"/> <vcpupin vcpu="3" cpuset="7"/> </cputune> <cpu mode="host-passthrough" check="none" migratable="on"> <topology sockets="1" dies="1" clusters="1" cores="2" threads="2"/> </cpu>Example 2: The following selects 'T6+T7+T8+T9+T10+T11'.
xml<vcpu placement="static">6</vcpu> <cputune> <vcpupin vcpu="0" cpuset="6"/> <vcpupin vcpu="1" cpuset="7"/> <vcpupin vcpu="2" cpuset="8"/> <vcpupin vcpu="3" cpuset="9"/> <vcpupin vcpu="4" cpuset="10"/> <vcpupin vcpu="5" cpuset="11"/> </cputune> <cpu mode="host-passthrough" check="none" migratable="on"> <topology sockets="1" dies="1" clusters="1" cores="3" threads="2"/> </cpu>
[!NOTE]
More information on configuring CPU pinning can be found in this excellent guide.
Below is an example .XML file that describes a Windows 11 virtual machine.
Example .XML File
/* Detailed source-code truncated for AI context efficiency. */Install Windows
Click Begin Installation in the top left.
Once you get to the point of selecting the location for installation, you will see there are no disks available. This is because the VirtIO driver needs to be specified manually.
Select
Load driver.The installer will then ask you to specify where the driver is located. Select the drive the
VirtIOdriver.ISOis mounted on.Choose the appropriate driver for the operating system you've selected, which is likely either the
w10orw11drivers.The virtual hard disk should now be visible and available for selection.
The next hurdle will be bypassing the network selection screen. As the VirtIO drivers for networking have not yet been loaded, the virtual machine will not be able to be connected to the internet.
Method 1: When prompted to select your country or region during the Windows 11 setup, press Shift + F10 to open the Command Prompt. Type OOBE\BYPASSNRO and press Enter. The system will restart, allowing you to select "I don't have internet" on the network screen. Note: It is crucial to do this as early in the setup process as possible.
Method 2 (Alternative): If you are already further along in the installation and the first command fails, you can try a fallback method. Press Shift + F10 to open the Command Prompt, type start ms-cxh:localonly, and press Enter. The setup will immediately skip to the local account creation page.
For Windows 10: Simply click "I don't have internet".
Following the above, choose to "Continue with limited setup".
Final Configuration Steps
Open File Explorer and navigate to the drive where the "virtio-win" .iso is mounted. Run virtio-win-guest-tools.exe to install all necessary drivers as well as QEMU Guest Agent. Leave everything as default and click Next through the installer.
Confirm QEMU Guest Agent was successfully installed by running Get-Service QEMU-GA within a PowerShell window. The output should resemble:
Status Name DisplayName
------ ---- -----------
Running QEMU-GA QEMU Guest AgentYou can then test whether the host GNU/Linux system can communicate with Windows via QEMU Guest Agent by running virsh qemu-agent-command RDPWindows '{"execute":"guest-get-osinfo"}' --pretty. The output should resemble:
{
"return": {
"name": "Microsoft Windows",
"kernel-release": "26100",
"version": "Microsoft Windows 11",
"variant": "client",
"pretty-name": "Windows 10 Pro",
"version-id": "11",
"variant-id": "client",
"kernel-version": "10.0",
"machine": "x86_64",
"id": "mswindows"
}
}Next, you will need to make some registry changes to enable RDP Applications to run on the system. Start by downloading the RDPApps.reg file, right-clicking on the Raw button, and clicking on Save target as. Repeat the same thing for the install.bat, the TimeSync.ps1 and the NetProfileCleanup.ps1. Do not download 'Container.reg' - this file is only required for users using docker or podman.
Once you have downloaded all three files, right-click the install.bat and select "Run as administrator".
Once this is complete, restart the Windows virtual machine.
(Optional) Configuring a Fallback Shared Folder
When connecting to Windows through FreeRDP, your home folder will be shared automatically. However, this sharing setup does not apply when using Windows via virt-manager. To configure a fallback shared folder, follow these steps:
Navigate to "Virtual Hardware Details", then "Memory" and then check the box for "Enable shared memory".
Add filesystem hardware by going to "Virtual Hardware Details" and selecting "Add Hardware" followed by "Filesystem". Choose
virtiofsas the driver, enter the path to the shared folder, and provide a name for the shared folder in the target path (e.g., "Windows Shared Folder").Install
WinFSPon Windows.Enable and start a 'VirtIO Filesystem' service within Windows by running the following commands within a PowerShell prompt.
powershellsc.exe create VirtioFsSvc binpath= "C:\Program Files\Virtio-Win\VioFS\virtiofs.exe" start=auto depend="WinFsp.Launcher/VirtioFsDrv" DisplayName="Virtio Filesystem Service" sc.exe start VirtioFsSvcReboot Windows.
(Optional) Configuring a Static IP Address
Identify the Windows MAC address.
bashvirsh dumpxml "RDPWindows" | grep "mac address"Edit the virtual network configuration.
Identify the correct network name.
bashvirsh net-list # Will likely return "default"Edit the configuration file.
bashvirsh net-edit "default" # Replace "default" with the appropriate network name if differentUpdate the
<dhcp>section in the configuration file using the MAC address you obtained earlier. In the below example, "RDPWindows" has MAC address "df:87:4c:75:e5:fb" and is assigned the static IP address "192.168.122.2".xml<dhcp> <range start="192.168.122.2" end="192.168.122.254"/> <host mac="df:87:4c:75:e5:fb" name="RDPWindows" ip="192.168.122.2"/> <host mac="53:45:6b:de:a0:7b" name="Debian" ip="192.168.122.3"/> <host mac="7d:62:4f:59:ef:f5" name="FreeBSD" ip="192.168.122.4"/> </dhcp>Restart the virtual network.
bashvirsh net-destroy "default" # Replace with the correct name on your system virsh net-start "default" # Replace with the correct name on your systemReboot Windows.
(Optional) Installing Spice Guest Tools
You may also wish to install Spice Guest Tools inside the virtual machine, which enables features like auto-desktop resize and cut-and-paste when accessing the virtual machine through virt-manager. Since WinApps uses RDP, however, this is unnecessary if you don't plan to access the virtual machine via virt-manager.
Installing Windows Software and Configuring WinApps
You may now proceed to install other applications like 'Microsoft 365', 'Adobe Creative Cloud' or any other applications you would like to use through WinApps.
[!IMPORTANT]
EnsureWAFLAVORis set to"libvirt"in your~/.config/winapps/winapps.confto prevent WinApps looking for aDockerinstallation instead.
Finally, restart the virtual machine, but DO NOT log in. Close the virtual machine viewer and proceed to run the WinApps installation.
bash <(curl https://raw.githubusercontent.com/winapps-org/winapps/main/setup.sh)