Files
wehub-resource-sync 3e779be6f3
CI / test (3.14, ubuntu-24.04-arm) (push) Waiting to run
CI / lint (push) Failing after 13m4s
CI / test (3.11, ubuntu-latest) (push) Failing after 2m4s
CI / test (3.13, ubuntu-latest) (push) Successful in 13m30s
CI / test (3.14, ubuntu-latest) (push) Successful in 17m21s
CI / test (3.12, ubuntu-latest) (push) Successful in 17m55s
CI / discover-apps-ps (push) Successful in 1m56s
CI / test (3.9, ubuntu-latest) (push) Successful in 13m17s
CI / test (3.10, ubuntu-latest) (push) Successful in 26m21s
CI / audit (push) Successful in 13m38s
Deploy site / deploy (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:32:37 +08:00

18 KiB
Raw Permalink Blame History

Install

English | 한국어

Every way to install WinPodX — the one-line installer, distro package managers, Nix, source builds, and offline scenarios.

One-line install

curl -fsSL https://raw.githubusercontent.com/kernalix7/winpodx/main/install.sh | bash

Detects your distro, installs missing system dependencies (Podman, FreeRDP, KVM, Python 3.9+) with your confirmation, drops winpodx into ~/.local/bin/winpodx-app/. The Windows-app menu populates automatically the first time the pod boots — discovery scans your running Windows guest and registers every installed app with its real icon. No root required except for the dependency install step. Works on openSUSE, Fedora (including Atomic Desktops: Silverblue, Kinoite, Sericea, Bluefin, Bazzite), Debian/Ubuntu, RHEL-family, Arch, and NixOS.

Windows licensing. dockur downloads a Windows ISO from Microsoft at first pod boot. Your use of the resulting Windows guest is governed by Microsoft's Software License Terms (the EULA shown on first activation). WinPodX does not redistribute Windows; it only orchestrates the install on your machine. Bring your own Windows license key for activation — Home / Pro / Enterprise are all supported by dockur.

By default the installer pins to the latest published GitHub release. Pre-release / development versions stay opt-in.

Choose a version

Pass --main (or --ref TAG) for development builds, otherwise stick with the default release:

# Install the latest stable release (default)
curl -fsSL https://raw.githubusercontent.com/kernalix7/winpodx/main/install.sh | bash

# Install the latest main HEAD (development; may be unstable)
curl -fsSL https://raw.githubusercontent.com/kernalix7/winpodx/main/install.sh | bash -s -- --main

# Install a specific tag, branch, or commit
curl -fsSL https://raw.githubusercontent.com/kernalix7/winpodx/main/install.sh | bash -s -- --ref vX.Y.Z

# Env-var equivalent (works under curl | bash without -s --)
WINPODX_REF=main  curl -fsSL https://raw.githubusercontent.com/kernalix7/winpodx/main/install.sh | bash
WINPODX_REF=vX.Y.Z curl -fsSL https://raw.githubusercontent.com/kernalix7/winpodx/main/install.sh | bash

Upgrading. Re-running install.sh (or upgrading the package) installs the new version in place. A running system tray / GUI restarts itself automatically so the new version applies — no manual restart needed. The Windows pod keeps running throughout.

Manual install (skip provisioning)

For users who want to install the binary now and customize the Windows guest later (pick edition / language / debloat / tuning knobs before the ~7.5 GB ISO download + Sysprep + OEM apply kicks off), pass --manual:

curl -fsSL https://raw.githubusercontent.com/kernalix7/winpodx/main/install.sh | bash -s -- --manual
# or via env var:
WINPODX_MANUAL=1 curl -fsSL https://raw.githubusercontent.com/kernalix7/winpodx/main/install.sh | bash

Manual mode installs the binary + desktop entry + icon only -- no winpodx setup, no pod wait-ready, no app discovery, no reverse-open setup. The next time you run winpodx (CLI or GUI), the first-run prompt offers three options:

  • Auto -- host-detected defaults, non-interactive (= what default install.sh would have done)
  • Customize -- wizard mode (pick every knob); equivalent to winpodx setup --customize
  • Skip -- exits without changes; re-runs the prompt on next invocation

This is the same flow that fires after a package-manager install. Use it when you want the wizard but prefer not to interrupt install.sh half-way through.

Offline / air-gapped install

The installer takes three optional flags for machines with no registry / package-repo access:

# Copy winpodx from a local clone instead of git clone (also env: WINPODX_SOURCE)
./install.sh --source /media/usb/winpodx

# Preload the Windows image tar instead of fetching at first boot (env: WINPODX_IMAGE_TAR)
./install.sh --image-tar /media/usb/windows-image.tar

# Skip distro package install (env: WINPODX_SKIP_DEPS=1) — fails early if deps aren't present
./install.sh --skip-deps

# Everything at once:
./install.sh --source /media/usb/winpodx --image-tar /media/usb/windows-image.tar --skip-deps

Env vars are honored even under curl | bash, so WINPODX_SKIP_DEPS=1 curl ... | bash works.

Choosing the Windows edition

By default WinPodX installs the latest dockur Windows 11 image. Pass --win-version VER (or the WINPODX_WIN_VERSION env var) to pick a different curated edition during a fresh install:

# Install Windows 10 LTSC instead of Win11
./install.sh --win-version ltsc10

# IoT Enterprise LTSC (long-term-service for kiosks / appliances)
./install.sh --win-version iot11

# Debloated community build
./install.sh --win-version tiny11

# Server 2022
./install.sh --win-version 2022

Curated set: 11 | 10 | ltsc11 | ltsc10 | iot11 | tiny11 | tiny10 | 2025 | 2022 | 2019 | 2016. Pre-Win10 editions (XP / Vista / 7 / 8 / Server 2003-2012) are out of Microsoft security support and don't match the rdprrap / agent.ps1 / install.bat assumptions WinPodX is built on — they'll still pass through to dockur with a WARNING but aren't first-class supported.

The --win-version flag only applies on fresh installs (no existing winpodx.toml). Existing installs change the edition via the GUI Settings → Container/VM → Windows Edition dropdown (or winpodx setup --win-version VER if you've removed the config).

For booting your own custom ISO with programs pre-installed, see Advanced: Custom Windows ISO.

Choosing the Windows language

By default, Windows installs in English (US). You can configure the display language, regional format, and keyboard layout by editing ~/.config/winpodx/winpodx.toml after running the installer (or by creating it beforehand for a fresh install):

[pod]
# Spanish example
language = "Spanish"
region = "es-ES"
keyboard = "es-ES"

Common language configurations:

Language language region keyboard
English (US) English en-001 en-US
Spanish (Spain) Spanish es-ES es-ES
Spanish (Latin America) Spanish es-MX la-Latin
French (France) French fr-FR fr-FR
German (Germany) German de-DE de-DE
Italian (Italy) Italian it-IT it-IT
Portuguese (Brazil) Portuguese pt-BR pt-BR
Portuguese (Portugal) Portuguese pt-PT pt-PT
Japanese Japanese ja-JP ja-JP
Chinese (Simplified) Chinese zh-CN zh-CN

These settings only apply to fresh Windows installations. If you've already run winpodx setup and booted Windows once, you'll need to either:

  1. Recreate the container with winpodx pod stop, delete the storage volume, edit the config, and run winpodx setup again, or
  2. Change the language manually inside Windows via Settings → Time & Language → Language & region

For the complete list of supported languages and region codes, see the dockur/windows documentation.

Native package managers

Prebuilt RPM and .deb packages are attached to every GitHub Release — openSUSE/Fedora RPMs come from the openSUSE Build Service (home:Kernalix7/winpodx), the rest from GitHub Actions. The winpodx AUR package is live as of v0.5.2 — Arch users can install via yay -S winpodx or paru -S winpodx.

After any package-manager install, run winpodx setup once. The package payload is binary + desktop entry + icon + man page only -- no post-install hook fires the Windows VM provisioning, because (a) winpodx setup is interactive (backend / credentials prompts), (b) winpodx pod start triggers a ~7.5 GB Windows ISO download + Sysprep + OEM apply (510 min on typical connections), and (c) apt install / dnf install / yay -S running as root shouldn't fire user-namespace rootless podman provisioning. The curl one-liner does the same winpodx setup --non-interactive + winpodx pod wait-ready chain itself, which is why it appears not to need a manual setup step. First-time flow:

winpodx setup                # interactive: backend / credentials / specs / locale
winpodx app run desktop      # auto-provisions the pod on first call (~510 min)

openSUSE Tumbleweed / Leap 15.6 / Leap 16.0 / Slowroll

sudo zypper addrepo \
  https://download.opensuse.org/repositories/home:/Kernalix7/openSUSE_Tumbleweed/home:Kernalix7.repo
sudo zypper refresh
sudo zypper install winpodx

Replace openSUSE_Tumbleweed with openSUSE_Leap_16.0, openSUSE_Leap_15.6, or openSUSE_Slowroll as needed.

Fedora 42 / 43 / 44

sudo dnf config-manager addrepo --from-repofile=\
https://download.opensuse.org/repositories/home:/Kernalix7/Fedora_43/home:Kernalix7.repo
sudo dnf install winpodx

Replace Fedora_43 with Fedora_42 or Fedora_44 as needed.

Note: Fedora 41 + ships dnf5; the syntax above (addrepo --from-repofile=) matches it. On dnf4 (Fedora ≤40, EOL) the equivalent is sudo dnf config-manager --add-repo <URL>. Reported by @payayas in #228.

Fedora Atomic Desktops (Silverblue / Kinoite / Sericea / Bluefin / Bazzite)

Atomic Fedora uses rpm-ostree instead of dnf — the same OBS RPM is layered onto the booted deployment with --apply-live (no reboot needed) when the running system accepts it, otherwise staged for the next boot. The universal install.sh autodetects rpm-ostree and runs the layered path; you can also do it by hand:

sudo curl -sSL \
  https://download.opensuse.org/repositories/home:/Kernalix7/Fedora_43/home:Kernalix7.repo \
  -o /etc/yum.repos.d/home-Kernalix7-winpodx.repo
sudo rpm-ostree install --apply-live winpodx     # try live apply first
# If live apply isn't supported on the booted deployment:
sudo rpm-ostree install winpodx                  # staged; reboot to activate

Replace Fedora_43 with Fedora_42 or Fedora_44 to match your base image.

Debian 12 / 13, Ubuntu 24.04 / 25.04 / 25.10

Download the matching .deb from the latest release and install:

sudo apt install ./winpodx_<version>_all_debian13.deb   # pick your flavor

AlmaLinux / Rocky / RHEL 9 & 10

EPEL is required on el9 for python3-tomli. Download the matching .rpm from the latest release and install:

sudo dnf install epel-release                            # el9 only
sudo dnf install ./winpodx-<version>-0.noarch.el9.rpm    # or .el10.rpm

Arch Linux / Manjaro

Install from the AUR using your preferred helper:

yay -S winpodx
# or
paru -S winpodx

The PKGBUILD lives at packaging/aur/PKGBUILD; each tag push (v*.*.*) auto-stamps the version + tarball sha256 and pushes to aur.archlinux.org/winpodx.git.

Development build — track main (winpodx-git). To run the latest unreleased code instead of the tagged release:

yay -S winpodx-git

winpodx-git builds from the main branch (the version is derived from git, so each rebuild pulls the newest commit — use yay -Syu --devel to auto-update). It provides/conflicts winpodx, so install one or the other, not both. Recipe + maintainer notes: packaging/aur-git/.

AppImage (Thin bundle: Python + Qt + FreeRDP + winpodx; host container runtime required)

A distro-agnostic AppImage of WinPodX ships as a release asset on every tagged release. 0.6.0 redesigned this as a Thin AppImage (item A). Pre-0.6.0 the AppImage was a ~296 MB fat bundle that carried the entire container stack (Podman + podman-compose + conmon + crun + netavark + aardvark-dns + pasta + passt + slirp4netns + transitive libs) into the AppImage's PATH / LD_LIBRARY_PATH. That shadowed and poisoned the host's working stack on every distro that already had a podman — it seems that you do not have podman installed on Ubuntu 26.04 (#357), OPENSSL_3.4.0 not found from aardvark-dns on Fedora Bluefin (#363), and similar elsewhere. 0.6.0 removes the root cause by dropping the entire container stack from the AppImage. The current bundle carries only what is safe to bundle — Python 3, winpodx, Qt6 (PySide6), and the FreeRDP 3 client (xfreerdp, wlfreerdp, sdl-freerdp) — and uses the host's container runtime via standard PATH resolution. Dropping the container stack alone only reached ~274 MB, though — the real bulk is PySide6, which bundles the whole Qt6 stack (QtWebEngine alone is ~195 MB) while winpodx uses only QtCore/QtGui/QtWidgets/QtSvg/QtDBus — so the unused Qt6 modules are stripped too (packaging/appimage/slim-pyside6.sh), bringing the AppImage to ~110 MB.

FreeRDP client source. The FreeRDP client source is selectable, and auto-discovery prefers the Flatpak client (com.freerdp.FreeRDP) with the native client (xfreerdp / wlfreerdp / sdl-freerdp on PATH) as a fallback (#366 / #393).

Host-side requirements:

  • A container runtime installed via your distro's package manager: podman ≥ 4 recommended, docker also supported (the manual backend uses an existing RDP host instead). Use the same install.sh (RPM / DEB / AUR) one-liner installs above if you don't have one yet.
  • /dev/kvm exposed by the host kernel (most distros do this by default once VT-x / AMD-V is enabled in BIOS).
  • The current user belongs to the kvm group (and /etc/subuid + /etc/subgid entries exist for rootless Podman — usually preconfigured on modern distros; check with cat /etc/subuid).

The setup-host wizard still ships in the AppImage for the kvm-group / subuid step (one polkit prompt instead of a manual sudo dance):

# 1. Download the AppImage from the latest GitHub release
#    -> winpodx-x86_64.AppImage

# 2. Make it executable
chmod +x winpodx-x86_64.AppImage

# 3. (Optional) First-run host setup — kvm group, subuid/subgid, kvm module
./winpodx-x86_64.AppImage setup-host          # detect + interactive prompt
./winpodx-x86_64.AppImage setup-host --apply  # apply without prompt
./winpodx-x86_64.AppImage setup-host --status # detect only, no mutation

# 4. Log out + back in so the new kvm group membership takes effect.

# 5. Standard winpodx setup (auto-detect cores / RAM / timezone)
./winpodx-x86_64.AppImage setup

# 6. Launch the desktop (or any installed Windows app by name)
./winpodx-x86_64.AppImage app run desktop

Best fit for:

  • Immutable distros (Fedora Silverblue / Kinoite, openSUSE Aeon, Steam Deck) once a host podman is layered in.
  • Locked-down environments where users can't run curl ... | bash but can run a single downloaded executable.
  • Quick try-it-on-a-friend's-laptop when a host podman / docker is already installed.

Not the best fit if you prefer:

  • Native package-manager integration (use the RPM / DEB / AUR paths above instead).
  • Auto-update from the system update cycle (the AppImage is downloaded + replaced manually unless you wire it into AppImageUpdate yourself).
  • A truly zero-host-prep run — the Thin AppImage needs a host container runtime; if you want the installer to install one for you, use install.sh.

Recipe and CI live under packaging/appimage/ — see packaging/appimage/README.md for local-build instructions if you want to roll your own. A regression test (tests/test_appimage_recipe.py) fails CI the moment the recipe re-introduces any of podman / podman-compose / conmon / crun / netavark / aardvark-dns / passt / pasta / slirp4netns / fuse-overlayfs.

Nix

A flake is provided for NixOS / nix-on-any-distro users:

# Run directly without installing
nix run github:kernalix7/winpodx

# Install into your profile
nix profile install github:kernalix7/winpodx

# As a flake input
inputs.winpodx.url = "github:kernalix7/winpodx";

The wrapper bundles FreeRDP, podman / podman-compose, iproute2 and libnotify, so the default Podman backend works out of the box. The Docker backend still requires Docker to be present on the host; the manual backend connects to an RDP host you provide.

From source

git clone https://github.com/kernalix7/winpodx.git
cd winpodx
./install.sh

The source installer automatically:

  1. Detects your distro (openSUSE, Fedora, Ubuntu, Arch, ...)
  2. Installs missing dependencies (Podman, FreeRDP, KVM), asks before installing
  3. Copies winpodx to ~/.local/bin/winpodx-app/
  4. Creates config and compose.yaml
  5. Auto-discovery (winpodx app refresh) fires on first pod boot to populate the menu

Manual run (no install)

git clone https://github.com/kernalix7/winpodx.git
cd winpodx
export PYTHONPATH="$PWD/src"
python3 -m winpodx app run word

Uninstall

One canonical script -- same behavior regardless of how WinPodX was installed (curl / pip / deb / rpm / aur).

Two equivalent entry points:

# Stop everything, keep Windows container + config (apt-remove semantics)
./uninstall.sh
# OR
winpodx uninstall

# Full wipe: container, volume, ~50 GB Windows disk, config, launcher (apt-purge semantics)
./uninstall.sh --purge --yes
# OR
winpodx uninstall --purge --yes

winpodx uninstall is a thin wrapper that locates and execs the same uninstall.sh shipped at one of: /usr/share/winpodx/uninstall.sh (deb/rpm/aur), ~/.local/bin/winpodx-app/uninstall.sh (curl), or the wheel's shared-data dir (pip).

--yes or --purge is required when piping from curl (interactive prompts can't read from a terminal while bash consumes stdin):

curl -fsSL https://raw.githubusercontent.com/kernalix7/winpodx/main/uninstall.sh | bash -s -- --yes
curl -fsSL https://raw.githubusercontent.com/kernalix7/winpodx/main/uninstall.sh | bash -s -- --purge

If installed via a package manager (apt/dnf/zypper/pacman), uninstall.sh detects this and prompts you to run the package-manager removal first -- that's the correct order: the package manager's post-remove hook re-runs uninstall.sh for the user-side cleanup, keeping the package database in sync with disk state.

Default mode never touches (use --purge to also remove these):

  • Podman container / volumes (Windows VM disk, ~50 GB)
  • ~/.config/winpodx/ config + compose.yaml
  • Storage bind-mount contents

Never removed by either mode:

  • System packages (podman, freerdp, python3) -- the package-manager removal prompt handles those
  • Other files in your home directory