A Windows-only dedicated server can usually run on Linux under Wine, and the recipe is short: download the Windows build with SteamCMD forced to the Windows platform, create a 64-bit Wine prefix, install the Visual C++ runtime the server links against, add a virtual display if it insists on one, and start the .exe through wine. Headless servers are far easier for Wine than game clients, because they need no graphics, no sound and very little of Windows. It works well for many survival servers - Enshrouded, V Rising, Abiotic Factor, Sons of the Forest and others are commonly run this way - and badly for a few, with Space Engineers the famous hard case. This post covers the set-up, the Proton alternative, and the errors that account for nearly every failed attempt.
If you are still deciding whether you need any of this, Linux vs Windows game servers lists which servers ship a Linux build. Use the native one if it exists; Wine is for when it does not.
What Wine is actually doing#
Wine is not an emulator and not a virtual machine. It is a reimplementation of the Windows API on Linux: when a Windows program calls CreateFileW or opens a socket with Winsock, Wine's own libraries handle the call and translate it into the Linux equivalent. The CPU runs the program's machine code directly, which is why the performance cost is small.
A dedicated server is a good candidate because it uses a narrow slice of Windows: files, threads, sockets, a console, and the C++ runtime. The parts of Wine that cause trouble for games - DirectX translation, audio, controllers, anti-cheat drivers - are mostly not involved. Where servers do fail, it is usually one of four things: a missing runtime DLL, a dependency on .NET Framework, an insistence on a display even when it draws nothing, or a server-side anti-cheat component that wants real Windows.
Proton is Valve's distribution of Wine, bundled with extra patches and libraries for Steam games. For servers it is an alternative build of the same thing, occasionally more compatible, occasionally less. Start with plain Wine and reach for Proton (in practice, the community GE-Proton builds) if a specific server is known to need it.
Installing Wine and the server#
Distribution packages work, but they are often several releases behind. Game servers released in the last year or two sometimes need a newer Wine than a stable distribution ships, so the WineHQ repository is the usual choice:
$ sudo dpkg --add-architecture i386$ sudo mkdir -pm755 /etc/apt/keyrings$ sudo wget -O /etc/apt/keyrings/winehq-archive.key \ https://dl.winehq.org/wine-builds/winehq.key$ sudo wget -NP /etc/apt/sources.list.d/ \ https://dl.winehq.org/wine-builds/ubuntu/dists/noble/winehq-noble.sources$ sudo apt update$ sudo apt install --install-recommends winehq-stable$ sudo apt install winetricks xvfb cabextractSwap noble for your release's code name (WineHQ publishes a sources file for each supported Debian and Ubuntu release). winehq-stable is the conservative choice; winehq-staging carries patches that have not reached stable yet and is sometimes what a newly released server needs. Check what you got with wine --version.
Run everything that follows as the same unprivileged user that owns the server files. A Wine prefix created by root and then used by another user is a reliable way to spend an hour on permission errors.
Downloading the Windows build with SteamCMD
SteamCMD on Linux asks Steam for Linux depots by default. For a Windows-only server that request either fails with Invalid Platform or downloads nothing useful. Force the platform before logging in:
$ ./steamcmd.sh +@sSteamCmdForcePlatformType windows \ +force_install_dir /srv/enshrouded \ +login anonymous \ +app_update 2278520 validate +quitThe @sSteamCmdForcePlatformType windows setting applies for the rest of that session, so put it first. If you also run native Linux servers from the same SteamCMD, keep this in its own script so you do not accidentally fetch Windows builds of those. Server app IDs for the common Windows-only games are in SteamCMD app IDs and beta branches.
The Wine prefix#
A prefix is a directory that holds one fake Windows installation: a drive_c, a registry, installed runtimes. Wine uses ~/.wine unless you say otherwise. Give each server its own prefix so a runtime installed for one cannot break another:
$ export WINEPREFIX=/srv/enshrouded/.wine$ export WINEARCH=win64$ export WINEDEBUG=-all$ export WINEDLLOVERRIDES="mscoree,mshtml="$ wineboot --initWhat each of those does:
| Variable | Value | Why |
|---|---|---|
WINEPREFIX | a directory per server | Isolates registry and runtimes |
WINEARCH | win64 | 64-bit prefix; set only when creating it |
WINEDEBUG | -all | Silences Wine's own debug output in the log |
WINEDLLOVERRIDES | mscoree,mshtml= | Skips the Mono and Gecko install prompts on first boot |
WINEARCH matters only at creation. A prefix created as 32-bit stays 32-bit, and a 64-bit server started in it fails with an error about being unable to load or find the executable. If you get that, delete the prefix and create it again with WINEARCH=win64 set.
WINEDEBUG=-all is worth explaining. Without it, Wine prints fixme: lines for every Windows function it implements only partially. Those are almost always harmless, but they bury the server's own output, and people chase them for hours. Turn them off by default and turn them back on (WINEDEBUG=err+all is a reasonable middle ground) only when you are debugging Wine itself.
Runtimes: Visual C++ and .NET#
Most Unreal and Unity servers are built with Microsoft's Visual C++ toolchain and need its runtime DLLs - vcruntime140.dll, msvcp140.dll and friends. Wine ships its own replacements for some of these, which work for many programs and not for others. If the server fails at start with a missing or failing DLL in that family, install the real runtime into the prefix:
$ WINEPREFIX=/srv/enshrouded/.wine winetricks -q vcrun2022vcrun2022 installs the current combined 2015-2022 redistributable; older winetricks versions call it vcrun2019. Update winetricks itself if the verb is missing - the copy in a distribution's repository is often old, and running winetricks --self-update or installing it from the project's GitHub release fixes that.
.NET Framework is harder. A server that needs it (Space Engineers needs .NET Framework 4.8) wants winetricks -q dotnet48, which takes a long time, sometimes fails part-way, and produces a prefix that is sensitive to Wine version changes. When a server needs .NET Framework, look for a maintained community container or egg for that specific game before building your own; someone has usually already found the combination of Wine version and runtimes that works.
Virtual displays and starting the server#
Some Windows servers create a window even in "headless" mode, and Wine needs an X display to create one. Without it you get errors about being unable to open the display, or the process exits immediately. Xvfb is a virtual X server that draws to memory, and xvfb-run starts one for the lifetime of a command:
$ cd /srv/enshrouded$ xvfb-run --auto-servernum --server-args="-screen 0 640x480x24" \ wine enshrouded_server.exeTry without xvfb-run first. Many servers do not need it, and it is one less moving part. Add it if the server will not start without a display.
V Rising is a typical example with arguments:
$ cd /srv/vrising$ xvfb-run --auto-servernum wine VRisingServer.exe \ -persistentDataPath ./save-data -logFile ./logs/VRisingServer.logThe server's own configuration works exactly as it does on Windows - the JSON or ini files are read by the Windows program, which does not know it is on Linux. Paths inside those configs can use Windows form (C:\..., which maps to drive_c in the prefix), Wine's Z: drive (which maps to the Linux root, so Z:\srv\vrising is /srv/vrising), or relative paths. Relative paths are the least confusing. Game server config file formats covers the JSON and ini files these servers use.
Ports need no special handling. Wine's Winsock calls become ordinary Linux sockets, so the server listens on the ports in its config, and the usual firewall rules apply - see game server ports explained.
Running it as a service
On your own machine, a systemd unit keeps the server running after you log out and starts it at boot. The environment variables go into the unit so every start uses the same prefix:
[Unit]Description=Enshrouded server (Wine)After=network-online.target[Service]User=steamWorkingDirectory=/srv/enshroudedEnvironment=WINEPREFIX=/srv/enshrouded/.wine WINEDEBUG=-allExecStart=/usr/bin/wine enshrouded_server.exeKillSignal=SIGINTTimeoutStopSec=60Restart=on-failure[Install]WantedBy=multi-user.targetKillSignal=SIGINT asks for the gentlest stop systemd can send, and TimeoutStopSec gives the server a minute to save before it is killed. Whether the game actually saves on that signal under Wine is a separate question, covered under clean stops below. Systemd services for your apps explains the rest of the unit file.
Running it with Proton instead#
If a server is known to need Proton, download a GE-Proton release, unpack it, and run the server through its proton script. Proton expects two environment variables that Steam would normally set:
$ export STEAM_COMPAT_CLIENT_INSTALL_PATH=/home/steam/steamcmd$ export STEAM_COMPAT_DATA_PATH=/srv/abiotic/proton-data$ mkdir -p "$STEAM_COMPAT_DATA_PATH"$ /opt/GE-Proton/proton run AbioticFactor/Binaries/Win64/AbioticFactorServer-Win64-Shipping.exe \ -log -PORT=7777 -QueryPort=27015STEAM_COMPAT_DATA_PATH is where Proton keeps its prefix (it creates pfx inside it), so it plays the role of WINEPREFIX. The client install path just needs to exist; pointing it at the SteamCMD directory is the usual choice. Proton runs wineboot on its own the first time, which makes the first start slow.
The trade-off: Proton bundles fixes you would otherwise install with winetricks, but it is a larger moving part, its versions are tied to GE's release cadence, and debugging it means debugging Wine with more layers on top. For most servers, plain Wine is simpler.
Clean stops, saves and the panel#
This is the section that matters most once the server is running, because it is where worlds are lost.
On Linux, a stop is a signal. A native Linux server receives SIGINT or SIGTERM, saves and exits. A Windows program under Wine receives a translated console event instead, and whether it reacts the way it would to Ctrl+C on Windows depends on the program. Some save and exit cleanly. Some ignore it until they are killed. Some exit immediately without saving.
Test this before you trust it:
- Start the server and make a change in the world you can recognise.
- Stop it the way your panel or service manager does.
- Start it again and see whether the change survived.
If it did not, send the game's own save command before every stop - most of these servers have one in their RCON or console - and lower the autosave interval so a kill loses minutes rather than half an hour. The trade-offs of that interval are in game server autosave intervals.
On a Pterodactyl panel, Windows-only games are usually run this way under the hood: the egg uses a Wine-enabled image, the install script downloads the Windows build, and the startup line wraps the .exe in wine. Community images for this are published under ghcr.io/parkervcp/yolks with Wine tags, though tag names and contents change over time. The egg also defines the stop command, which is why the same Stop button can save cleanly for one Wine game and not for another. Pterodactyl eggs for game servers covers where that is set.
On RE:NODE, games such as Sons of the Forest, The Forest and Abiotic Factor install and start from the panel without you touching Wine at all, and every plan has backup slots and the Schedules tab, so a save command followed by a backup can run on a timer whatever the game does with a stop signal.
Memory and performance under Wine#
The cost is real but modest. Expect a few hundred megabytes more memory than the same server would use on Windows, mostly the Wine server process and loaded libraries. CPU overhead is usually small, because the program's code runs natively and only system calls go through translation. First start is slower while Wine sets up the prefix and, with Proton, compiles its own components; later starts are normal.
Two things make performance worse than it should be:
- Debug output. Leaving
WINEDEBUGunset on a chatty server can write thousands offixme:lines a minute to the log, costing disk and a little CPU. - An old Wine. Newer Wine releases regularly improve threading and file I/O. If a server stutters under Wine and runs smoothly for Windows hosts, try a newer stable or staging build before tuning the game.
Errors and what they mean#
| Error | Cause | Fix |
|---|---|---|
Invalid Platform from SteamCMD | Linux depot requested | +@sSteamCmdForcePlatformType windows first |
Library VCRUNTIME140.dll ... not found | No VC++ runtime | winetricks -q vcrun2022 |
wine: Bad EXE format for ... | 32-bit prefix, 64-bit server | Recreate the prefix with WINEARCH=win64 |
cannot open display / no X server | Server wants a window | Run under xvfb-run |
| Hangs on first start, Mono or Gecko prompt | Wine waiting for an installer | WINEDLLOVERRIDES="mscoree,mshtml=" |
wineserver: ... lock or a stuck start | A previous wineserver still running | wineserver -k with the same WINEPREFIX |
| Crashes after a game update | New build needs newer Wine | Update Wine, then try staging |
| World rolls back after restart | Stop is not saving | Save command before stop, shorter autosave |
Two habits shorten debugging considerably. Read the server's own log file, not Wine's output, because the useful error is usually the game's. And when a server that worked yesterday fails today, ask what changed - a game update, a Wine update, or a prefix someone touched - before reinstalling anything. Reading the console applies here exactly as it does to native servers.
FAQ#
Is running a server under Wine against the game's terms?
Not as a rule. You are running the developer's own server binary; Wine only provides the operating-system layer. What you do not get is developer support, so report bugs only once you have reproduced them on Windows.
Wine or Proton - which should I use for a game server?
Start with Wine from the WineHQ repository and the runtimes the server needs. Switch to GE-Proton when a specific server is known to work better with it or when Wine fails in ways a newer build does not fix.
Does Wine work for servers with anti-cheat?
It depends on what runs on the server. Server-side components that only need ordinary networking often work. Anything that expects a kernel driver or deep Windows integration does not, and some games refuse to start their anti-cheat under Wine at all.
Can I share one Wine prefix between several servers?
You can, but do not. A runtime or registry change for one server can break another, and deleting a broken prefix should only ever affect one game. Prefixes are cheap; give each server its own.
Why is my Wine server using more memory than the requirements say?
The requirements are written for Windows. Wine adds its own server process and libraries, usually a few hundred megabytes. Size the plan with that margin, especially for games that already sit close to their memory limit.




Comments
Completely anonymous: no account, no email, no cookie. We store the name you type, the text and the time - nothing else. Links are limited and markup is not rendered.