I Ran a Space Engineers Dedicated Server on macOS. The Blocker Everyone Names Is the Wrong One.

What everyone answers, and why it misses
I wanted to play Space Engineers with a friend who plays on console. I have a Mac. Every answer I found said the same thing: get a Windows PC, or rent a host.
Neither suited me, so I checked whether the claim was actually true. It is not. The server runs on macOS, with a modded world and a console player connected to it.
Here is the method, and above all the three traps that cost me the most time.
The server is not the game
Search for "Space Engineers on Mac" and you get an avalanche of results explaining that the game does not run on macOS. Those results are correct, and they answer a different question.
The dedicated server is a separate binary, SpaceEngineersDedicated.exe, shipped alongside the client. It has no renderer. It never opens a window, loads a shader, or touches the GPU. It simulates physics, holds world state, and talks to clients over the network.
The whole story is in that distinction. The client is hard to port because it is a DirectX 11 application doing real graphics work. The server is a headless .NET application doing math. Under Wine, one is a research project and the other is an evening.
I lost an hour to this confusion myself. I had read "the game does not run" and stopped thinking.
Getting the files without a Steam account
You do not need Windows to obtain the binaries, and you do not need a Steam account either. SteamCMD has a native macOS build, and the dedicated server downloads anonymously:
steamcmd +force_install_dir "$PWD/game" +login anonymous \
+app_update 298740 validate +quit
App 298740 is the dedicated server. +login anonymous is not a workaround: it is how Valve publishes dedicated server packages. No account, no game licence on the machine. Your friends still need to own the game. The server does not.
The trap that eats your evening: .NET Framework
The server targets .NET Framework 4.8. The standard advice, for any .NET application under Wine, is to install the real Microsoft runtime with winetricks dotnet48.
Do not do this on Wine 11.
The .NET Framework 4.8 installer is a 32-bit executable. Wine 11 shipped a rewritten WoW64 layer, the shim that runs 32-bit Windows code inside a 64-bit Wine process. The installer and that new layer do not get along. It does not crash. It does not error. It sits there holding a lock, indefinitely.
The fix is to not install it at all, and the fix is also the default behaviour. Wine Mono, Wine's own .NET implementation, ships inside the wine-stable cask and installs itself when you create the prefix:
export WINEPREFIX="$PWD/prefix"
wineboot --init
wineserver -w
That is all. Wine Mono is 64-bit, it takes seconds, and the server does not care which .NET implementation it is talking to.
One detail turns a wasted evening into a wasted night. The dotnet48 verb of winetricks deletes Wine Mono first, before it installs anything. So if you try that route and it deadlocks, you do not end up back where you started: you end up with a prefix that has no .NET runtime at all, and a server that now fails for a completely different reason than the one you were chasing. Delete the prefix and recreate it.
The only Microsoft component you genuinely need is the Visual C++ 2015-2019 x64 redistributable, which is a 64-bit installer and behaves itself.
Console crossplay, and its price
Two settings in the server config:
<NetworkType>EOS</NetworkType>
<ConsoleCompatibility>true</ConsoleCompatibility>
EOS switches transport from Steam networking to Epic Online Services, which is what console clients speak. ConsoleCompatibility restricts the world to features consoles can handle.
The price is mods. With console compatibility on, Steam Workshop becomes unavailable. Your entire mod list has to come from mod.io, which has a smaller catalogue and different IDs for the same mods. If you had a patiently curated Workshop collection, you will be rebuilding it.
Hash the password yourself
The config does not store your password, it stores a hash, and the format is not documented anywhere official. Several websites offer to generate one for you.
Do not use them: you are typing a password into a stranger's form.
The format is standard and fits in ten local lines. PBKDF2 with HMAC-SHA1, 10000 iterations, a 20 byte key, a 16 byte random salt, salt and key concatenated then base64 encoded:
import base64, hashlib, os
def password_hash(password: str) -> str:
salt = os.urandom(16)
key = hashlib.pbkdf2_hmac("sha1", password.encode(), salt, 10000, 20)
return base64.b64encode(salt + key).decode()
Three lessons about process lifetime
This is where a working install becomes a usable one, and where I made every mistake on offer.
The server dies with the terminal. Obvious in hindsight. The fix is a detached tmux session, after which it lives independently.
The Mac going to sleep takes the server with it. caffeinate handles that, tied to the server's own PID so it releases automatically when the server stops. And I made exactly the same mistake again: I had written that line inside the startup script, so caffeinate was a child of the script, so it died the second the script exited. It had never worked once since I wrote it. The fix is the same principle as the server itself: detach it properly, with start_new_session=True.
And when it crashed anyway, sleep was not the cause. The server went down twice in one evening. I had just written the sleep protection, so I spent an hour proving it worked. It did work. The server kept dying.
The real cause was an unrelated background process on the same machine touching the installation. What hid it was the timestamps: the server writes UTC, my clock is local, and a two hour offset was enough that the correlation never jumped out. The moment I normalised both to one timezone, the events lined up to the second.
The lesson outlives this game. When you have just built a fix for problem X and X keeps happening, your certainty about the cause is the least reliable thing in the room. Normalise every timestamp before you theorise.
A guard is not a guard if something bypasses it by default
The Space Engineers dedicated server has no clean shutdown. No "save and quit" command, no signal it handles properly. You kill the process, and everything built since the last autosave is gone.
So the stop script refuses to run when the last save is too old, unless you pass an explicit --force.
That guard has already saved me once, and how it saved me is instructive. I had a settings panel that stopped the server, wrote the changes, then restarted. To make it convenient, I had it call the stop script with --force. It worked perfectly, silently discarded a chunk of unsaved world, and I had built exactly the bypass that made my own check useless.
The fix was not to remove the option, but to make the human ask for it: force became an explicit checkbox in the panel, unchecked by default, sitting right next to the age of the last save. You keep the escape hatch, you just cannot take it by accident.
What it actually gets you
A dedicated server does not exist to let two people play together. Console players have been hosting each other for years.
What it gets you is what a console-hosted session structurally cannot do. Microsoft and Sony forbid running custom scripts on console, so the programmable block, Space Engineers' scripting system, is unavailable in single player and in console-hosted multiplayer. On a dedicated server it works, and console players get it by joining. The restriction is on who hosts, not on who plays.
You also get a world that keeps simulating when nobody is connected, a mod list you control, and thirty-odd settings you can change without going through anyone's storefront.
The code
I cleaned all of this into a public repository: install script, start and stop with the save age guard, a local settings panel for the world settings that otherwise mean hand editing XML, and a README where every dead end is documented rather than quietly omitted.
github.com/Stark-52/se-server-macos
MIT licensed. If you were looking for this and only finding "get a Windows PC," I hope it saves you the evening it cost me.
