Skip to content

An on-demand Windows machine, for testing the POS desktop app

Source: g2labs-in/linode-infra@f503b3f · docs/runbooks/azure-windows-test-vm.md · updated 2026-09-19

Status: plan, not built. Nothing exists in Azure today. This is what to run when we need it.

Last updated 2026-09-19.


Why this exists

Nobody on the team runs Windows. Abhilash and Anshul are on MacBooks, Aakash is on Linux, and the Billuu POS desktop app is Windows-only (build.win is the only target in package.json). That leaves one platform we ship to and cannot touch.

There are two different gaps hiding under “we need Windows”, and they need different answers.

GapAnswerCost
Does it build, boot and behave?GitHub Actions windows-latest, already runningfree
Does the installer work, and how does the app feel?this VMper hour, only while running
Does it print on a real till?a physical Windows box, laterone-time hardware

This document covers the middle row. It does not replace the other two.


What this machine can and cannot do

Can:

  • Run the NSIS installer and see the real SmartScreen prompt
  • Prove the update path end to end: install build N, publish N+1, watch it update
  • Measure how the app actually performs, on hardware that is not a developer’s laptop
  • Exercise the Windows spooler path, including enumerating printers
  • Catch real Windows path, permission and filesystem problems
  • Reproduce a customer’s bug report on something that resembles their machine

Cannot:

  • Print anything real. Azure VMs have no USB passthrough to a thermal printer, and RDP redirection is unreliable for raw printing. printerManager.cjs:276 picks windows-spooler-raw on Windows, and the output end of that path needs physical hardware. Printing verification waits for the mini PC.
  • Replace the CI job. Anything CI already asserts should not be checked by hand here.

The cost model, and how to keep it near zero

Three states, and only one of them is free.

StateComputeDiskWhat to run
Runningbilled hourlybilled./windows-test-vm.sh start
Stopped properlyfreebilled./windows-test-vm.sh stop
Deletedfreefree./windows-test-vm.sh destroy

Two traps worth stating plainly:

  1. az vm stop does not stop the billing. It keeps the compute allocated and keeps charging. az vm deallocate, which the stop subcommand uses, is the one that releases it. This is the single most common way to waste money on an idle Azure VM.
  2. A reserved public IP also bills while idle. This VM has none. It is reached over Tailscale, which costs nothing and matches the rest of the estate.

So the idle cost is the OS disk alone. For a 64 GB StandardSSD that is a few dollars a month, which is the price of not waiting twenty minutes for a rebuild when someone needs to test something.

If the disk cost is not worth it, destroy removes the resource group entirely and cost drops to zero. Rebuilding is one command and a few minutes. Choose per how often it is used.

Prices must be read in the Azure portal. az consumption returns no amounts on this subscription, which CONTEXT.md already records.


Budget constraint to clear first

CONTEXT.md records that the $200 Azure credit ends around 2026-10-13, and that the account stops working on the 12-month grants unless it moves to pay-as-you-go.

Creating a Windows VM after that date needs the account transition finished first. This is a dependency, not a detail. If the account is not moved, this plan cannot be executed at all.


How to use it

The script is azure/windows-test-vm.sh. It is a plan you can run, not a build step.

Terminal window
cd ~/code/linode
./azure/windows-test-vm.sh create # once. Validates, creates, joins the tailnet.
./azure/windows-test-vm.sh start # power on when needed
./azure/windows-test-vm.sh ip # the address to RDP to
./azure/windows-test-vm.sh stop # deallocate, which stops the billing
./azure/windows-test-vm.sh destroy # remove everything, cost drops to zero

Access is RDP over Tailscale, so the port is never exposed to the internet:

mstsc /v:<tailscale-ip> # from Windows
# from macOS, use Microsoft Remote Desktop; from Linux, remmina

Then, on the VM, install the POS from the release feed and use it the way an outlet would.

Size and image

SettingDefaultWhy
SizeStandard_B2s (2 vCPU, 4 GB)Burstable is right for occasional interactive use. Windows 11 wants 4 GB minimum.
ImageWindows 11 ProThe point is to see what a customer sees. Server has a different shell, no consumer SmartScreen, and no consumer UX.
Disk64 GB StandardSSDEnough for Windows plus the app.

If Standard_B2s is refused, try Standard_B2ms. CONTEXT.md is explicit that SKU restriction flags on this offer are unreliable, which is why the script runs az vm create --validate before creating anything. That check costs nothing and takes seconds.

Password

Windows needs an admin password for RDP. The script prompts for one, or reads WINTEST_PASSWORD from ~/.config/billuu/infra.env. Put it in the password manager either way.


When to build it

Not yet. Build it when one of these becomes true:

  • A customer reports a Windows-only bug that CI cannot reproduce
  • Someone needs to verify the update path against a real install, not the packaged --dir build
  • The POS desktop is about to be installed at an outlet where we cannot watch it
  • Performance is in question and a developer’s laptop is not a fair test

Until then it costs nothing to leave unbuilt, and building it early only starts the disk billing.


What this is not

  • Not a staging environment. Those are .scratch/staging-environment-split.
  • Not a substitute for CI. CI already packages and boots the real Windows app on every PR.
  • Not a print test. Buy the mini PC for that. It is the only thing that closes that gap.
  • Not a macOS answer. macOS is not a target, and printerManager.cjs takes a different transport there, so a Mac test would exercise a code path no customer runs.

State of things, for the record

ItemState
VM existsno
Account transition to pay-as-you-gonot done, needed before 2026-10-13
Tailscale auth key in ~/.config/billuu/infra.envyes
CI windows-latest jobrunning, desktop-smoke.yml
Physical Windows machine for printingnot bought, recommended later