Skip to content

v0.5.9

Choose a tag to compare

@github-actions github-actions released this 27 May 04:35
81c5485

[0.5.9] - 2026-05-27

Highlights

Multilingual UI, self-growing disk, and a guest that updates without a reinstall.

  • The whole tray / GUI / CLI is now translatable and fully translated to 7 languages (en/ko/zh/ja/de/fr/it) — picked from your system locale, switchable with winpodx language or the GUI dropdown (fixes the stray-Korean reports, #335).
  • The Windows C: drive grows on its own when it fills up — and can be grown by hand with winpodx pod grow-disk — including past the WinRE recovery partition dockur leaves behind (#318).
  • Guest sync: upgrading winpodx on the host now pushes the new agent / fixes / binaries into a running guest with no wipe-reinstall (winpodx pod sync-guest, automatic on pod start).
  • Pod auto-start on login is now a real, opt-in feature (winpodx autostart on).
  • Fixes: USB shortcut erroring with no media mounted, RemoteApp painting the logon screen (#332), AppImage podman-compose ModuleNotFoundError on atomic distros (#322), and a too-tight install agent-wait that gave up early.

Added

  • Selectable, fully translated UI — 7 languages (en/ko/zh/ja/de/fr/it). winpodx's own tray / GUI / CLI text is now translatable, and all ~814 user-facing strings are wrapped and fully translated to all six non-English languages (placeholders, backtick command snippets, and product names preserved verbatim). [ui] language (default auto) picks the language from the host locale ($LANG) and falls back to English; override it from the CLI (winpodx language ko, or winpodx language to show current) or the GUI Settings → winpodx UI language dropdown (applies on next launch). English is the source/baseline — always 100% complete — and any string a future language hasn't translated falls back to English (no blanks). Catalogs live at winpodx/locale/<lang>.json as flat {english: translation} maps, so adding a language is a file drop with no code change. Addresses the stray-Korean reports (#335).
  • Pod auto-start on login (opt-in). cfg.pod.auto_start was a stored-but-unused flag; now it works — but it's off by default and explicitly opt-in (booting Windows on every login is heavy, so a plain install never forces it). Turn it on with winpodx autostart on (or the GUI Settings checkbox): that installs the tray autostart entry and sets auto_start, so the tray — launched on login — starts the pod (or resumes it if suspended). winpodx autostart off / status manage it. Background + best-effort (a failure just leaves the pod stopped, logged; never crashes the tray); no-op when already running.
  • Guest sync — apply host updates to a running guest without a reinstall. Upgrading winpodx on the host used to leave the guest's agent.ps1, urlacl reservation (#269), rdprrap/shim binaries, and registry fixes stale until a wipe-reinstall. /oem is a live bind mount of the host's config/oem, so after a host upgrade the container already has the new files; winpodx now delivers them into the running guest (same channel as pod recover-oem, but automated over the agent /exec), re-applies the idempotent fixes, restarts the agent (via a one-shot scheduled task so it doesn't kill the /exec it's serving), and stamps the guest version (C:\winpodx\install-state\guest_version.json). Runs automatically once per pod start when the guest stamp is older than the host (guest_autosync, default on); also triggered by winpodx migrate (so a package / AppImage / flatpak upgrade — whose update path never runs install.sh — gets the full guest refresh from a single command), manual via winpodx pod sync-guest [--force], and a GUI Tools → Sync Guest action. No agent change. See docs/design/GUEST_SYNC_DESIGN.md.
  • Windows disk auto-grow + manual grow (#318). The Windows C: drive now grows on its own: when the system volume fills past disk_autogrow_threshold_pct (default 80%) and the pod is idle, winpodx grows the virtual disk enough to restore disk_autogrow_target_free_pct free space (default 30%, in whole disk_autogrow_increment steps — not a flat bump), recreates the container so dockur grows the image, then extends C: to fill via Resize-Partition — no manual Disk Management step. The grow is bounded by the host's free space (minus a safety reserve); disk_max_size is now an optional explicit ceiling (empty by default) rather than a fixed cap. The same operation is exposed manually: winpodx pod grow-disk (add one increment), winpodx pod grow-disk 128G (absolute target), winpodx pod grow-disk --extend-only (just extend C: into existing unallocated space), and winpodx pod disk-usage (size / free / used%). The GUI Tools page gains a Grow Disk action. Auto-grow runs only while idle so it never interrupts a live RemoteApp session, and the guest-side work reuses the agent /exec path (no agent change). Default-on; set disk_autogrow = false to manage size manually. Note: dockur has no online disk resize, so each grow recreates the container (a quick guest reboot) — winpodx schedules auto-grows during idle for exactly this reason. dockur's Windows layout puts a WinRE Recovery partition right after C:, so the grown space lands behind it and a plain Resize-Partition can't reach it; the extend step detects this, detaches WinRE, removes the blocking recovery partition, extends C: to fill, and re-enables WinRE (in C:\Windows when no dedicated partition remains). Reported by @drjwhitty (Linux Mint 22.2).

Fixed

  • Upgrade re-install hung at [4/4] waiting for the OEM reboot pass. Re-running install.sh over an already-provisioned guest froze pod wait-ready --logs at phase 4. Two causes: (1) --logs --tail 100 replayed the original first-boot download log, and a stale wget ETA line inflated the wait deadline to tens of minutes; (2) phase 4 (_wait_for_oem_reboot) blocked for that whole inflated window when the agent was still transitioning, because the "marker never reappears → this is an upgrade" exit only fired on a clean probe, never while the agent was rejecting connections. Fixes: the deadline no longer extends once the container is running (any ETA line after that is replayed history); phase 4 is hard-capped at 180s (it's a marker poll, not a download); and the upgrade-path exit now triggers on the appear-grace clock regardless of probe outcome.
  • USB desktop shortcut errored when no removable media was mounted. install.bat always drops a USB shortcut pointing at \\tsclient\media, but winpodx only redirected that drive when a removable-media base (/run/media/$USER etc.) existed — so clicking USB with nothing plugged in failed with "\\tsclient\media is not accessible … Attempt to access invalid address." winpodx now always redirects a media drive: the real base when mounted, otherwise an empty placeholder dir, so the shortcut opens to an empty folder instead of erroring.
  • Stray Korean text in the UI (#335). The tray "Quit" confirmation dialog and the CPU/RAM tier preset labels (Low/Mid/High) were hardcoded in Korean, so an English-locale user got a Korean prompt on exit. Both are now English (winpodx's UI is English; a full selectable-UI-language i18n layer is planned separately). Reported by @camegone (CachyOS).
  • Install: agent-readiness wait is now dynamic + generous, with no misleading errors. On a slow first boot (cold cache / slow disk / a long ISO download that pushes the whole install late) the post-RDP agent /health wait was capped at a hard 180s, so it gave up early — leaking a scary agent didn't answer within 180s WARN and then skipping apply-fixes / discovery even though the agent was just minutes from coming up. The wait now honors the caller's full (dynamic, ISO-ETA-extended) deadline — pod wait-ready phase 3 already passes the auto-extending deadline, so the agent gets as long as the install legitimately needs. Separately, the guest version stamp read/write now go through the windowless agent /exec channel (run_via_transport) instead of FreeRDP (#346) — so a transitioning agent on a fresh first boot fails clean and the stamp is re-attempted on the next pod start, rather than leaking a scary FreeRDP timed out after 30s / ERRCONNECT_ACTIVATION_TIMEOUT warning mid-install. The stamp is best-effort and surfaces at info level ("deferred; will retry next start"), never a warning. The post-install app-discovery retry budget was also raised from 3 to 6 attempts (~50s) so it outlasts the apply chain's TermService/rdprrap cycle instead of falling through to pending-resume on the next launch.
  • First-run setup prompt fired on every invocation (#341). "winpodx has not been set up yet" is gated on an internal initialized flag, not on the config file existing. The non-interactive existing-config path printed "skipping setup" and returned before flipping that flag, so a config with it still false (created via install.sh's own skip path, or written before the flag existed) made the prompt loop forever — pick "Auto", setup short-circuits, prompt returns next time. The skip path now marks the install initialized too. Reported by @ntruhan (Fedora 44).
  • RemoteApp launched into the logon/lock screen → corrupted render (#332). Apps sometimes came up showing the Windows login background instead of the app, with xf_Pointer: Invalid appWindow spam — the app had launched, but FreeRDP's RAIL window was created while the guest session was still transitioning through the logon/lock screen (dockur's autologon session briefly re-spawns), so FreeRDP painted the stale logon framebuffer and never repainted the app. Version-independent (reproduced on current FreeRDP). winpodx now waits — best-effort, agent-only so it never flashes a FreeRDP probe window — until the guest console is interactive (explorer.exe up, no LogonUI.exe) before firing the RemoteApp connection; if the agent is unreachable or it times out, the launch proceeds as before. Reported by @tolistim (Mint 22.3).
  • AppImage: podman-compose ModuleNotFoundError (#322). The fat AppImage bundled Fedora's /usr/bin/podman-compose launcher script but not the podman_compose Python module it imports (it's pure Python, so ldd can't pull it in), and the script's shebang fell through to the host's python3 — which lacks the module on atomic distros. Pod creation failed with ModuleNotFoundError: No module named 'podman_compose'. Now the build pip-installs podman-compose into the AppImage's bundled interpreter and ships a usr/bin/podman-compose wrapper that runs it via python3 -m podman_compose (a pip console script can't be used directly — its shebang is the dead build-time path, same reason AppRun uses python3 -m winpodx). Reported by @jmayniac (Bluefin / Fedora atomic).