> For the complete documentation index, see [llms.txt](https://axiomemu.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://axiomemu.gitbook.io/docs/guides/launch-server.md).

# Launching Your Server

This guide walks through a clean install from the files you downloaded off the customer portal to players connecting with the client. It assumes a single Windows machine (local test or dedicated host) running SQL Server.

{% hint style="danger" %}
**Operating system minimum: Windows Server 2016 / Windows 10 (x64) or newer.** The shipped `MuOnline.bak` requires SQL Server 2022 to restore (see step 4), and SQL Server 2022 won't install on anything older than Windows Server 2016 / Windows 10. If you're on Windows Server 2012 R2, Windows 7, Windows 8.1, or any 32-bit edition, upgrade the host OS before you start - the install will block at SQL Server setup otherwise.
{% endhint %}

## 1. Get the files

Sign in to the customer portal and download the latest server bundle and matching client bundle. The portal dashboard surfaces a banner when a new release is out and your servers haven't been upgraded yet.

{% hint style="info" %}
Keep an eye on the portal and the Discord announcements channel. Required updates (security hotfixes) close your running server with a popup the next time it heartbeats - you must apply them before it will run again.
{% endhint %}

Extract the server archive somewhere with no spaces or localized characters in the path. `C:\AxiomServer` is a safe default. You should end up with this layout:

```
AxiomServer\
├── ConnectServer\        ConnectServer.exe + ServerList.xml + Log\
├── DataServer\           DataServer.exe + DataServer.ini
├── GameServer\           GameServer.exe + configs
├── JoinServer\           JoinServer.exe + JoinServer.ini
├── Data\                 shared game data (items, monsters, drops)
├── Tools\                ConfigEncoder, AxiomEditor, ServerStartUP, PngToOzt, SQL, DB
└── migrations\           SQL migrations for updates
```

## 2. Add an antivirus exclusion before you launch anything

Windows Defender and most third-party AV products flag the server binaries because of the protection wrapper around them. If you skip this step, the EXEs get quarantined mid-run and you will chase phantom crashes.

{% tabs %}
{% tab title="PowerShell (admin)" %}
Open PowerShell **as administrator** (right-click the Start menu → **Windows PowerShell (Admin)** / **Terminal (Admin)**, or right-click the PowerShell icon → **Run as administrator**). Without elevation the cmdlet fails with an access-denied error.

```powershell
Add-MpPreference -ExclusionPath "C:\AxiomServer"
```

Replace the path with wherever you extracted the server.
{% endtab %}

{% tab title="Windows Security GUI" %}
**Windows Security → Virus & threat protection → Manage settings → Exclusions → Add exclusion → Folder** → select the install folder.
{% endtab %}

{% tab title="Already quarantined" %}

```powershell
Get-MpThreat | Format-Table -AutoSize
Restore-MpThreat -ThreatID <id>
```

Or use **Windows Security → Protection history → Restore**.
{% endtab %}
{% endtabs %}

{% hint style="warning" %}
Third-party AV (Bitdefender, Kaspersky, Norton, ESET, Avast, etc.) each have their own exclusion UI. Add the install folder there too.
{% endhint %}

## 3. Paste your license key

Your portal license key has to be written into every server's config and into ConfigEncoder. All five locations validate the key at startup and refuse to run without it.

Grab the key from [axiomemu.com/portal/licenses](https://www.axiomemu.com/portal/licenses): click the license card to open its detail page, find the **License Key** field at the top, then click **Click to reveal** and use the copy button next to the revealed value.

| Component     | File                                          | Field                   |
| ------------- | --------------------------------------------- | ----------------------- |
| DataServer    | `DataServer\DataServer.ini`                   | `LicenseKey=`           |
| JoinServer    | `JoinServer\JoinServer.ini`                   | `LicenseKey=`           |
| ConnectServer | `ConnectServer\ConnectServer.ini`             | `LicenseKey=`           |
| GameServer    | `GameServer\DATA\GameServerInfo - Common.dat` | `LicenseKey=`           |
| ConfigEncoder | `Tools\ConfigEncoder\EncoderConfig.xml`       | `<License Key="..." />` |

{% hint style="info" %}
`GameServerInfo - Common.dat` is a plain text INI file - open it with any editor. The `.dat` extension is historical.
{% endhint %}

## 4. Install SQL Server

**Minimum supported version: SQL Server 2022 (engine 16.00.1000).** The shipped `MuOnline.bak` was taken on 2022, and SQL Server refuses to restore a backup onto an older engine - the file format is forward-compatible only. 2019, 2017, 2014, and 2012 will fail step 5 with `Msg 3169`. 2022 is the sweet spot; 2025 also works.

{% hint style="danger" %}
If you already have SQL Server 2019 or older installed, you must install SQL Server 2022 (or newer) before continuing. You can keep the older instance side-by-side under a different instance name - just point the ODBC DSN in step 6 at the 2022 instance.
{% endhint %}

**SQL Server Express** (free, sufficient for private servers up to a few hundred concurrent players):

* [SQL Server 2025 Express](https://go.microsoft.com/fwlink/?LinkID=2213259\&clcid=0x409)
* [SQL Server 2022 Express](https://www.microsoft.com/en-us/download/details.aspx?id=104781)

**SQL Server Management Studio (SSMS)** - pick any version, all are backward-compatible with older SQL Server engines:

* [SSMS 22](https://aka.ms/ssms/22/release/vs_SSMS.exe)
* [SSMS 21](https://aka.ms/ssms/21/release/vs_SSMS.exe)
* [SSMS 20.2](https://learn.microsoft.com/en-us/sql/ssms/download-sql-server-management-studio-ssms?view=sql-server-ver16)
* [SSMS 19.3](https://aka.ms/ssmsfullsetup)
* [SSMS 18.12.1](https://support.microsoft.com/en-au/topic/microsoft-sql-server-management-studio-ssms-18-12-1-kb5014879-efead12c-3f8b-4d75-bb51-abbac5ae3c98)
* [SSMS 17](https://download.microsoft.com/download/D/D/4/DD495084-ADA7-4827-ADD3-FC566EC05B90/SSMS-Setup-ENU.exe)

During SQL Server setup:

1. Choose **Mixed Mode authentication** - this enables the `sa` account alongside Windows auth.
2. Set a strong `sa` password and write it down. You will need it for the ODBC DSN.
3. On the **Server Configuration** step, make sure **SQL Server Browser** is set to **Automatic** if you plan to connect by instance name.

{% hint style="info" %}
If you get stuck, there are hundreds of SQL Server setup walkthroughs on YouTube - the steps above are the only ones that matter for AXIOM-EMU. Ask in our Discord if something specific breaks.
{% endhint %}

## 5. Restore the MuOnline database

The backup ships at `server\migrations\MuOnline.bak`. The `.mdf` / `.ldf` paths baked into it are from the machine it was taken on, so the restore has to redirect them. The script below reads your instance's default data/log folders and builds the `RESTORE` dynamically, so the only thing you edit is the path to `MuOnline.bak`.

Connect to your SQL Server 2022 instance in SSMS using **Windows Authentication** (the account that installed SQL Server is already `sysadmin`; the `sa` password from step 4 is for DataServer/JoinServer at runtime, not this restore). **New Query** → paste, edit `@bak`, **F5**:

```sql
DECLARE @bak  nvarchar(4000) = N'C:\AxiomServer\server-v1.0.0\server\migrations\MuOnline.bak';
DECLARE @data nvarchar(4000) = CAST(SERVERPROPERTY('InstanceDefaultDataPath') AS nvarchar(4000));
DECLARE @log  nvarchar(4000) = CAST(SERVERPROPERTY('InstanceDefaultLogPath')  AS nvarchar(4000));
DECLARE @sql  nvarchar(max) = N'
RESTORE DATABASE [muonline]
FROM DISK = N''' + @bak + N'''
WITH
    MOVE ''MuOnlineS6''     TO N''' + @data + N'muonline.mdf'',
    MOVE ''MuOnlineS6_log'' TO N''' + @log  + N'muonline_log.ldf'',
    REPLACE,
    STATS = 10;';

EXEC sp_executesql @sql;
```

Success prints `RESTORE DATABASE successfully processed ...` in the **Messages** pane and `muonline` appears under **Databases** (F5 the node to refresh).

Verify:

```sql
USE muonline; SELECT COUNT(*) FROM MEMB_INFO;
```

Returns `0` on a fresh restore.

### Common restore errors

* **`Msg 3156`** or **`Msg 3634 - Access is denied`** - the SQL Server service account can't write to the default data folder. Rare, but happens on locked-down hosts; grant the service account write access to the folder `SERVERPROPERTY('InstanceDefaultDataPath')` returns.
* **`Msg 3169`** - backup was taken on a newer engine. See the troubleshooting entry at the bottom of this page; you're on SQL 2019 or older and need to install 2022 (step 4).
* **Empty string / `NULL` path from `SERVERPROPERTY`** - only happens on very old engines or unusual installs. Fall back to an explicit `RESTORE ... WITH MOVE ... TO N'C:\...\muonline.mdf'` and hard-code the paths.

<details>

<summary>sqlcmd alternative (no SSMS)</summary>

`-E` uses Windows Authentication. Run from a shell signed in as a `sysadmin` account. Save the T-SQL above to `restore.sql` (edit `@bak`), then:

```cmd
sqlcmd -S localhost -E -i restore.sql
```

</details>

## 6. Set up the ODBC DSN

DataServer and JoinServer both talk to SQL Server through an ODBC DSN named `MuOnline`. The server bundle ships registry files that create the DSN for you.

### 6a. Multiple SQL Server instances? Edit the .reg first

The shipped `MuOnline.reg` and `MuOnline64.reg` hard-code `"Server"="(local)"`, which resolves to the **default** unnamed instance. If you have more than one SQL Server installed - for example a leftover SQL 2019 alongside the SQL 2022 you added in step 4, or a named Express install like `SQLEXPRESS02` - `(local)` either picks the wrong engine or fails to connect at all. Edit the `.reg` before importing so the DSN targets the 2022 instance that holds the restored `muonline` database.

1. Find your instance name. In SSMS, connect to the 2022 engine and look at the title bar - it shows `HOSTNAME\INSTANCENAME`. Or run `SELECT @@SERVERNAME;` in a new query. Common values: `SQLEXPRESS`, `SQLEXPRESS2022`, `MSSQLSERVER` (the default instance - use `(local)` for this one).
2. Open `server\migrations\MuOnline.reg` in Notepad (right-click → **Edit**, not **Merge**).
3. Change the `"Server"` line under the `MuOnline` DSN key:

```reg
"Server"=".\\SQLEXPRESS2022"
```

Use `.\\INSTANCENAME` for a named instance on the same machine (note the **doubled backslash** - `.reg` files require it), or `HOSTNAME\\INSTANCENAME` for remote. Leave `(local)` only if you're on the default unnamed instance.

4. Repeat for `MuOnline64.reg` if you plan to use AxiomEditor x64.
5. Save, then import as below.

{% hint style="warning" %}
Single backslash in a `.reg` file silently truncates the value - `".\SQLEXPRESS2022"` becomes `".SQLEXPRESS2022"` after import and the DSN fails to connect with no obvious error. Always double the backslash in `.reg`; the ODBC UI stores it as a single backslash, which is what you'll see if you open the DSN afterwards.
{% endhint %}

### 6b. Import the DSN

{% tabs %}
{% tab title="Import the .reg file" %}
The files live in `server\migrations\` (e.g. `C:\AxiomServer\server-v1.0.0\server\migrations\`):

* **`MuOnline.reg`** - 32-bit DSN. Required; DataServer and JoinServer are both 32-bit.
* **`MuOnline64.reg`** - 64-bit DSN. Optional; AxiomEditor x64 uses this.

Double-click the file, confirm the UAC prompt, then confirm the import.
{% endtab %}

{% tab title="Manual (ODBC Data Source Administrator)" %}

1. Run `C:\Windows\SysWOW64\odbcad32.exe` (this is the **32-bit** administrator - the one DataServer/JoinServer's DSN must live in).
2. **System DSN → Add → SQL Server** (or **ODBC Driver 17/18 for SQL Server** if installed).
3. Name: `MuOnline`. Server: `(local)` (or `.\SQLEXPRESS`, `.\SQLEXPRESS02`, etc. - match step 4).
4. Authentication: **With Windows NT authentication** for a local install, or **With SQL Server authentication** + `sa` + the password from step 4 for remote / locked-down setups.
5. Default database: `muonline`.
6. Click **Test Data Source** - it must succeed before you move on.
   {% endtab %}
   {% endtabs %}

{% hint style="warning" %}
The shipped `.reg` files assume `Trusted_Connection=Yes` against `(local)` with `Database=MuOnline`. If your instance name isn't the default, your auth isn't Windows, or you want the DSN to point at the lowercase `muonline` from step 5, open the DSN in `C:\Windows\SysWOW64\odbcad32.exe` after the import and adjust. **Test Data Source** must pass before continuing.
{% endhint %}

## 7. Configure server IPs

ConnectServer binds to all interfaces, so its own .ini has no IP field - only ports. The addresses your players (and your other servers) connect to live in a handful of other places. Pick your **public** IP (or `127.0.0.1` for a single-box local test) and replace it in each file below.

### `GameServer\DATA\GameServerInfo - Common.dat`

```ini
ServerCode = 0
ServerPort = 55901
ServerVersion = 1.04.05
ServerSerial = TbYehR2hFUPBKgZj

DataServerAddress = 127.0.0.1
DataServerPort = 55960
JoinServerAddress = 127.0.0.1
JoinServerPort = 55970
ConnectServerAddress = 127.0.0.1
ConnectServerPort = 55557
```

If GameServer lives on the same box as DataServer, JoinServer, and ConnectServer, leave all three `*Address` lines at `127.0.0.1`. If you split them across hosts, point each to the right internal IP.

`ServerCode` is the map-group ID that ties this GameServer instance to a `<Server Code="...">` entry in `MapServerInfo.xml` and `ServerList.xml` - all three must agree.

### `JoinServer\JoinServer.ini`

```ini
ConnectServerAddress = 127.0.0.1   ; change to your ConnectServer IP
ConnectServerPort = 55557
```

JoinServer uses this to push user and server status updates to ConnectServer.

### `GameServer\Data\MapServerInfo.xml`

```xml
<MapServerInfo>
    <Server Code="0" Group="0" Init="1" Ip="S62.84.187.28" Port="55901"/>
    <Server Code="2" Group="0" Init="1" Ip="S62.84.187.28" Port="55904"/>
</MapServerInfo>
```

This is the address GameServer hands back to the **client** after the server-select screen. Replace the IP - keep the leading `S`, it's part of the format. The `Port` on each row must match the `ServerPort` in the corresponding GameServer's `Common.dat`.

### `ConnectServer\ServerList.xml`

Edit the `<Server>` entries so the `Code` values match your `MapServerInfo.xml` / GameServer `ServerCode`, and set the display names you want on the server-select screen.

### `Tools\ConfigEncoder\ServerConfig.xml`

```xml
<ServerConfig>
    <Connection IP="62.84.187.28" Port="44405" />
    <Client Serial="TbYehR2hFUPBKgZj" Version="1.04.05" />
</ServerConfig>
```

`Connection` is the address **the client** uses to reach ConnectServer. `Serial` and `Version` have to match `ServerSerial` / `ServerVersion` in every GameServer's `Common.dat` - if you change them anywhere, change them in both places, or clients will fail the handshake.

### `Tools\ConfigEncoder\ClientConfig.xml`

```xml
<AutoUpdater
    Enabled="1"
    ServerIP="62.84.187.28"
    Port="80"
    UseHTTPS="0"
/>
```

Point this at your patch server. Set `Enabled="0"` only if you're replacing the built-in updater with your own launcher DLL/EXE. See the comments above each block in `ClientConfig.xml` for every other tunable - graphics, interpolation, economy caps, launcher branding.

## 8. Encode the client configs

Before the first run, point ConfigEncoder at your client install by editing `Tools\ConfigEncoder\EncoderConfig.xml`:

```xml
<EncoderConfig>
    <Output Path="C:\AxiomClient\Data\Local" />
    <DLLIntegrity Path="C:\AxiomClient" />
    <License Key="..." />
</EncoderConfig>
```

* `Output Path` - the client's `Data\Local\` folder. ConfigEncoder writes the encoded blobs straight into here.
* `DLLIntegrity Path` - the root of the client install, used to compute integrity hashes for its DLLs.

Then run `Tools\ConfigEncoder\ConfigEncoder.exe`. It reads `ServerConfig.xml` and `ClientConfig.xml` and writes:

* `ServerInfo.axiom` - connection details (ConnectServer IP/port, serial, version).
* `ClientConfig.axiom` - client-side tunables (graphics, interpolation, economy caps, launcher branding).

Both files are consumed by the **client only**. GameServer reads its own `GameServerInfo - *.dat` files and never touches the `.axiom` blobs.

{% hint style="info" %}
Re-run ConfigEncoder every time you change `ServerConfig.xml` or `ClientConfig.xml`. The client reads the encoded blob on startup; editing the XML alone has no effect. No manual copy step - the tool overwrites the blobs in `Output Path` directly.
{% endhint %}

{% hint style="warning" %}
ConfigEncoder only produces blobs for the **client and launcher**. The C++ servers (GameServer / DataServer / ConnectServer / JoinServer) read their own plain-text `.dat` / `.ini` files directly and never load these `.axiom` blobs.
{% endhint %}

## 9. Start the servers

You can launch the four EXEs by hand, or use the bundled `Tools\ServerStartUP\ServerStartUP.exe` to start them in one go. Expected startup order:

```
DataServer  ->  JoinServer  ->  ConnectServer  ->  GameServer
```

Launching manually: open each server's folder, double-click the EXE, wait for the console to settle (no new red/error lines) before starting the next.

### Using ServerStartUp

`StartUp.xml` ships empty on first install - you add your servers through the tool's UI, not by hand-editing the file. Run `ServerStartUp.exe` and, for each server in the order above, add a row with:

* **Path** - absolute path to the server EXE (e.g. `C:\AxiomServer\DataServer\DataServer.exe`).
* **Delay** - milliseconds to wait after launching this process before launching the next. `2000` (2s) is a reasonable default; bump it if your SQL Server is slow to accept connections.
* **Run** - leave enabled. Disable a row to skip that server without deleting it (useful when debugging one component in isolation).
* **Parameters** - leave empty unless you have a specific reason to pass command-line arguments.

The tool persists your rows back to `StartUp.xml`, so you only do this once. After that, launch `ServerStartUp.exe` any time and it boots the whole stack in order.

Healthy startup looks like each server loading its config, opening its listening ports, and then going quiet aside from periodic status lines. If a server exits immediately, re-read its console - the vast majority of startup failures come down to:

* Wrong or missing license key.
* ODBC DSN not created, or pointing at the wrong instance / wrong credentials.
* Port already in use (another AXIOM-EMU instance, another MU emulator, or SSMS holding a connection).
* Address mismatch - e.g. `JoinServer.ini` pointing to a ConnectServer IP that isn't reachable.

## 10. Create an account and connect

Accounts live in the `MEMB_INFO` table. The shipped way to create them is **AxiomEditor**.

1. Run `Tools\AxiomEditor\AxiomEditor.exe`.
2. On first launch, configure the DB connection. Two options:
   * **ODBC** - reuse the `MuOnline` DSN. No password needed if the DSN uses Windows auth.
   * **Direct** - server `127.0.0.1`, port `1433`, database `MuOnline`, user `sa`, password as set in step 4.
3. Open the **Accounts** tab → **New Account**. Set username, password, and (optionally) pre-create a character.
4. Launch the client with the encoded `ServerInfo.axiom` and `ClientConfig.axiom` in place, log in with the account you just created, and you should land on the character-select screen.

{% hint style="info" %}
`AxiomEditor.exe` needs the .NET 8 Desktop Runtime. If it fails to start with no error dialog, install it from [dotnet.microsoft.com](https://dotnet.microsoft.com/download/dotnet/8.0).
{% endhint %}

## Troubleshooting

<details>

<summary>Server exits on startup with a license error</summary>

The key in one of the five license locations is empty, has surrounding quotes, or doesn't match the one issued on the portal. Double-check all five: `DataServer.ini`, `JoinServer.ini`, `ConnectServer.ini`, `GameServerInfo - Common.dat`, and `EncoderConfig.xml`. Copy the key fresh from the portal dashboard.

</details>

<details>

<summary>DataServer fails to connect to the database</summary>

The `MuOnline` DSN doesn't exist, points at the wrong instance, or the SQL Server service isn't running. Verify by running `C:\Windows\SysWOW64\odbcad32.exe`, opening the DSN, and clicking **Test Data Source**.

</details>

<details>

<summary>Client connects to ConnectServer but character list is empty</summary>

ConnectServer reached GameServer, but GameServer can't advertise its map. Check that `MapServerInfo.xml` has the correct IP with the leading `S` and that the `Code` matches your `ServerList.xml` entry.

</details>

<details>

<summary>Client can't reach the server at all</summary>

Port-forwarding or firewall. You need inbound rules for TCP `44405` (ConnectServer), `55557` UDP (ConnectServer announce), and every `Port=` listed in `MapServerInfo.xml`. On a dedicated host, add them to Windows Firewall and to your provider's network firewall.

</details>

<details>

<summary>Restore fails with <code>Msg 3169</code> - backup is from a newer server version</summary>

The `.bak` was taken on SQL Server 2022 (engine `16.00.1000`). Older engines (2019 / 2017 / 2014 / 2012) cannot restore it - SQL Server backup format is forward-compatible only.

```
The database was backed up on a server running version 16.00.1000.
That version is incompatible with this server, which is running version 12.00.2000.
```

Install SQL Server 2022 (or newer) and restore onto that instance. Existing older instances can stay - just point the ODBC DSN at the 2022 instance name (e.g. `.\SQLEXPRESS2022`).

</details>

<details>

<summary>Servers run fine then get quarantined after a few minutes</summary>

AV exclusion missing or not applied to the right folder (step 2). Real-time scanning waits until the protection wrapper finishes unpacking before it fires. Add the exclusion, restore the quarantined EXE, and relaunch.

</details>
