Some games ship an "official" self-hosting tool that flatly requires Windows plus Hyper-V — nested virtualization and all. Open the box before believing that. Often the actual payload is just a portable Linux disk image with a full container orchestration stack already inside it, and the Windows/Hyper-V wrapper is only there because that's what the publisher's own tooling happened to be built on top of.
A modern "dedicated server" for a live-service game is rarely a single executable anymore — it's often a small fleet of coordinated services (a database, a message queue, matchmaking/gateway logic, the actual game-world process) bundled together with something like Kubernetes to manage them. If the official installer requires Windows, check what it's actually shipping before assuming you need a Windows box at all: publishers have said as much publicly for at least one game using this pattern — Linux-direct hosting works fine, they just don't provide official instructions for it, because their own packaging tool happens to require Windows/Hyper-V to unpack it.
Once you've confirmed the official installer is really just unpacking a self-contained disk image (VHDX, in the case this is based on), convert it to your own hypervisor's format and boot it directly:
qemu-img convert -f vhdx -O qcow2 server-disk.vhdx server-disk.qcow2
qemu-img resize server-disk.qcow2 80G
Boot that directly under KVM (or whatever your hypervisor is) — no Windows, no Hyper-V, no nested virtualization anywhere in the chain.
modprobe nbd max_part=8
qemu-nbd --connect=/dev/nbd0 server-disk.qcow2
vgchange -ay vg0
mount /dev/mapper/vg0-lv_root /mnt
# edit /mnt/etc/network/interfaces for a static IP
# check /mnt/etc/resolv.conf -- shipped images often point at their original
# host environment's internal DNS, which is dead anywhere else
umount /mnt; vgchange -an vg0; qemu-nbd --disconnect /dev/nbd0
x509: invalid signature: parent certificate cannot sign this kind of certificate right after
first boot looks alarming but is typically just clock skew during early startup before NTP has synced.
Wait a few minutes and retry the same command rather than troubleshooting further.
This is the part that actually caused a real, confusing bug — worth walking through in full because the debugging process is the useful part, including two wrong turns along the way.
The symptom: a player transferred their character onto a self-hosted world and then got a generic "Claim failed, try again later" error trying to redeem a returning-player reward package — even after waiting over an hour, as the game's own message suggested.
First finding, and it's an important one for anyone running one of these: a self-hosted world is not actually isolated from the publisher's live infrastructure. The game-world processes make real outbound HTTPS calls to the publisher's own cloud backend for entitlements, transfers, and reward systems — none of that is simulated locally just because you're hosting the "dedicated server" part yourself. The actual failure was findable in the **game process's own logs**, in a category clearly labeled as talking to the publisher's live services, not anywhere in the hosting/orchestration layer's own logs:
LogFuncomLiveServices: Error: https://[publisher-live-service-host]/api/ClaimSystem_GrantPacksForCharactersServer... Failed: Request Timeout or null response
LogDuneCharacter: Error: ...GrantReturnRewards... Failed to grant returning-player award packs for the character...
The actual answer, found through the publisher's own patch notes and player community reports, not guessed: this was a documented bug. Transferring a character to a new world without first logging into the character's origin world to view the reward there resets its eligibility. The publisher had already shipped a fix for the common case months earlier — but it has a real edge case: if the character's origin world had already been shut down by the time of the transfer, there's nothing left to "log into first," and the fix can't retroactively apply. The only resolution other players in that exact situation reported success with was an official support ticket requesting manual compensation — not anything fixable through local server configuration.
If the disk image is distributed through a platform like Steam rather than a bespoke publisher download, you likely already have a lightweight way to check whether you're running the latest available build, without a full re-download or even a real login:
steamcmd +login anonymous +app_info_print <appid> +quit
Look for the branches → public → timeupdated field in the output (a Unix timestamp — pipe it
through date -u -d @<value> to read it) and compare it against when you actually built
your deployment. If the publisher's build predates your own deployment date, you're already current and a
stale binary can be ruled out as a cause — worth checking before assuming an obscure bug needs a version
bump to fix.