Brazil's biggest MU Online portal — since 2003
Tutorial Advanced Server

How to automate MU Online server file deployment

Learn to build a reliable deployment pipeline for your MU Online server, with copy scripts, ordered stopping and starting of services, automatic backup, rollback and scheduling.

GA Gabriel · Updated on Jun 28, 2026 · ⏱ 16 min read
Quick answer

Automating a MU Online server's deployment is the difference between a calm five-minute maintenance and an entire night copying files by hand, hoping you didn't forget anything. A typical private server runs several interdependent processes — ConnectServer, GameServer, DataServer, the events service

Automating a MU Online server's deployment is the difference between a calm five-minute maintenance and an entire night copying files by hand, hoping you didn't forget anything. A typical private server runs several interdependent processes — ConnectServer, GameServer, DataServer, the events service and the website — and they all read the same configuration files and binaries. Swapping an .exe or a .dat with the process running simply doesn't work on Windows, because the system keeps the file locked. On top of that, a copy done by hand is prone to human error: a forgotten file, a swapped folder, a lost permission. This tutorial shows how to turn that whole ritual into a predictable pipeline: a script that backs up the current state, takes the services down in the right order, syncs the new files, brings everything back up and, if something goes wrong, lets you return to the previous state with a single command. We'll use PowerShell as the example because it is native to Windows, where most MU servers run, but the logic applies to any tool. Remember: paths, service names and folder structure vary by emulator/version, so treat the examples as a skeleton to adapt, not as absolute truth.

Prerequisites

Before writing the first line of automation, have a clear map of your server. If you are still building the environment from scratch, it is worth reviewing the guide on how to create a MU Online server first, because automation only makes sense on top of a base that already works manually.

You will need:

  • Administrative access to the server machine (the deploy touches services and protected folders).
  • PowerShell 5.1 or higher, already included in Windows Server and Windows 10/11.
  • A known folder structure: where the binaries (ConnectServer, GameServer, DataServer), the configuration files and the game data live.
  • A source folder (staging) with the already-validated files that will be published.
  • Enough disk space to keep at least the last 3 to 5 full backups of the server folder.
  • Permission to manage the services via Stop-Service/Start-Service or, if the processes run as ordinary applications, via Stop-Process/Start-Process.

An important detail: not every emulator registers its components as Windows services. Many run as simple executables open in a session. That changes how you stop and start each piece, and the script has to reflect your reality. Varies by emulator/version.

Understanding the stop and start order

The order matters more than it seems. The components of a MU server have clear dependencies:

ComponentDepends onStop orderStart order
DataServerSQL Server3rd to stop1st to start
GameServerDataServer2nd to stop2nd to start
ConnectServerRegistered GameServer1st to stop3rd to start
Website / panelSQL Serveroptionallast

The practical rule: take them down top to bottom (from what players touch first) and bring them up bottom to top (from the foundations). The ConnectServer is the entry point, so it is the first to fall to prevent new logins during the swap. The DataServer is the base that talks to SQL, so it is the first to come back. Reversing this produces GameServers that start without being able to register and get stuck in an error loop.

Step 1 — Define variables and the script structure

Start by isolating everything that changes between environments into variables at the top of the script. This avoids hard-coded paths scattered through the code.

# deploy.ps1 - example (adapt paths and names to your emulator/version)
$ServerPath  = "D:\MuServer"           # production destination
$StagingPath = "D:\Deploy\staging"     # new, validated files
$BackupRoot  = "D:\Deploy\backups"
$Timestamp   = Get-Date -Format "yyyyMMdd_HHmmss"
$BackupPath  = Join-Path $BackupRoot $Timestamp
$LogFile     = "D:\Deploy\logs\deploy_$Timestamp.log"

# Processes/services in STOP ORDER
$ProcessesToStop = @("ConnectServer","GameServer","DataServer")
# On startup we'll use the reverse order

Always adopt a Timestamp when creating the backup. It is what makes rollback possible and traceable: each deploy leaves a dated snapshot of the previous state.

Step 2 — Log everything

A deploy with no log is a deploy you can't debug at three in the morning. Create a simple log function that writes to the screen and to a file at the same time.

function Write-Log {
    param([string]$Msg, [string]$Level = "INFO")
    $line = "{0} [{1}] {2}" -f (Get-Date -Format "HH:mm:ss"), $Level, $Msg
    Write-Host $line
    Add-Content -Path $LogFile -Value $line
}

Call Write-Log at every relevant step: start, backup completed, each service stopped, copy finished, each service started. When something fails, the log will tell you exactly where the pipeline stalled.

Step 3 — Backup before anything else

This is the non-negotiable step. Never overwrite a production file without first copying the current state to a safe place. The pre-deploy backup is your parachute.

Write-Log "Starting backup of $ServerPath"
New-Item -ItemType Directory -Path $BackupPath -Force | Out-Null

robocopy $ServerPath $BackupPath /E /R:2 /W:3 /NFL /NDL /NP | Out-Null

if ($LASTEXITCODE -ge 8) {
    Write-Log "Backup FAILED. Aborting deploy." "ERROR"
    exit 1
}
Write-Log "Backup completed at $BackupPath"

A note about robocopy: its exit codes don't follow the usual convention. Values from 0 to 7 indicate success (with or without files copied); 8 or higher indicate a real error. That is why the check is -ge 8 and not -ne 0. Ignoring this detail makes the script abort for no reason on every run.

Note that this backup covers only the server's files. The database has its own life cycle and should not be touched by file deployment — it needs a separate backup routine on SQL Server. Mixing the two is a classic source of headaches.

Step 4 — Stop the services in the correct order

With the backup in place, take the processes down. The handling depends on how your emulator runs each piece.

foreach ($proc in $ProcessesToStop) {
    Write-Log "Stopping $proc"
    $p = Get-Process -Name $proc -ErrorAction SilentlyContinue
    if ($p) {
        $p | Stop-Process -Force
        Start-Sleep -Seconds 2
        Write-Log "$proc stopped"
    } else {
        Write-Log "$proc was not running" "WARN"
    }
}

If, in your case, the components are registered Windows services, swap it for Stop-Service -Name $proc -Force. The Start-Sleep gives the system time to release the file locks before we attempt the copy. Without that pause, the next step can fail with "file in use". It varies by emulator/version whether the components are services or loose processes.

Step 5 — Sync the new files

Now that nothing is holding the files, copy the staging into production. Use robocopy again, being careful not to delete data that should not be touched.

Write-Log "Copying files from $StagingPath to $ServerPath"
robocopy $StagingPath $ServerPath /E /R:2 /W:3 /XD "Backup" /NFL /NDL /NP | Out-Null

if ($LASTEXITCODE -ge 8) {
    Write-Log "Copy FAILED. Starting rollback." "ERROR"
    # rollback call here (Step 7)
    exit 1
}
Write-Log "Files synced successfully"

Notice the /XD (exclude directory): use it for folders the deploy should never alter, like logs, dumps or persistent data. If you use the /MIR (mirror) flag, be very careful — it deletes at the destination everything that doesn't exist at the source, which can destroy local configurations. For an incremental deploy, prefer /E (copies subfolders, including empty ones) without mirroring.

Step 6 — Start the services in reverse order

Foundations first. Start in the order opposite to the stop.

$ProcessesToStart = @(
    @{ Name="DataServer";    Exe="D:\MuServer\DataServer\DataServer.exe" }
    @{ Name="GameServer";    Exe="D:\MuServer\GameServer\GameServer.exe" }
    @{ Name="ConnectServer"; Exe="D:\MuServer\ConnectServer\ConnectServer.exe" }
)

foreach ($s in $ProcessesToStart) {
    Write-Log "Starting $($s.Name)"
    Start-Process -FilePath $s.Exe
    Start-Sleep -Seconds 5
    $ok = Get-Process -Name $s.Name -ErrorAction SilentlyContinue
    if ($ok) { Write-Log "$($s.Name) online" }
    else     { Write-Log "$($s.Name) did NOT start" "ERROR" }
}

The 5-second Start-Sleep between each piece gives the DataServer time to register before the GameServer tries to connect, and for the GameServer to be ready before the ConnectServer accepts players. Adjust the time to your machine's speed. Varies by emulator/version.

Step 7 — Automatic rollback

Rollback is simply the inverse of the deploy: stop the services, restore the backup folder and start again. Wrap it in a reusable function.

function Invoke-Rollback {
    param([string]$BackupDir)
    Write-Log "ROLLBACK from $BackupDir" "WARN"
    foreach ($proc in $ProcessesToStop) {
        Get-Process -Name $proc -ErrorAction SilentlyContinue | Stop-Process -Force
    }
    Start-Sleep -Seconds 3
    robocopy $BackupDir $ServerPath /E /R:2 /W:3 /NFL /NDL /NP | Out-Null
    Write-Log "Files restored. Start the services manually and validate."
}

Call this function whenever a critical step fails, passing that deploy's $BackupPath. The key point is that the backup was created before any change, so the restore returns the server exactly to the state that worked. Keep the most recent backups and clean the old ones periodically so you don't fill the disk.

# Retention: keep only the 5 most recent backups
Get-ChildItem $BackupRoot -Directory |
    Sort-Object Name -Descending |
    Select-Object -Skip 5 |
    Remove-Item -Recurse -Force

Step 8 — Post-deploy validation

Starting the processes doesn't guarantee the server is healthy. Do objective checks:

  1. Confirm that each process appears in the list (Get-Process).
  2. Test whether the ConnectServer and GameServer ports are listening with Test-NetConnection -ComputerName 127.0.0.1 -Port <port>.
  3. Do a test login with an account reserved for that.
  4. Check the components' own logs for registration or database-connection errors.

Only declare the maintenance over after a real login works. A process that is "up" but doesn't accept connections is worse than a process that is down, because it gives a false sense of success.

Step 9 — Scheduling with the Task Scheduler

For recurring or early-morning deploys, register the script in the Windows Task Scheduler. Do this only with scripts that have been tested exhaustively.

$action = New-ScheduledTaskAction -Execute "powershell.exe" `
    -Argument "-NoProfile -ExecutionPolicy Bypass -File D:\Deploy\deploy.ps1"
$trigger = New-ScheduledTaskTrigger -Daily -At 04:00
Register-ScheduledTask -TaskName "MU Deploy" -Action $action -Trigger $trigger `
    -RunLevel Highest -Description "Automatic MU server deploy"

Even when scheduled, keep someone on call for the first runs and configure sending the logs by email or webhook. Automation doesn't eliminate the need for supervision — it only reduces the repetitive effort.

Common errors and fixes

SymptomLikely causeFix
"File in use" during the copyService was not fully stoppedIncrease the Start-Sleep after stopping and confirm with Get-Process
Script always aborts at the backupCheck using -ne 0 on robocopySwitch to -ge 8, since 1–7 are success
GameServer starts and crashes in a loopDataServer wasn't ready yetIncrease the pause between DataServer and GameServer
Local config disappeared after deployUse of /MIR deleted what wasn't in stagingUse /E without mirroring and /XD for protected folders
Rollback doesn't restore the stateBackup created after the changeMake sure the backup runs before any copy
Scheduled task doesn't run as adminMissing -RunLevel HighestRecreate the task with elevated privilege
Ports don't respond after startupStart order reversedStart DataServer → GameServer → ConnectServer

Launch checklist

  • Folder structure and service names mapped and correct in the script
  • Staging folder contains only files already validated in the test environment
  • Log function writing to a dated file
  • Pre-deploy backup tested and with the -ge 8 check
  • Backup retention policy configured (last 3–5)
  • Stop order: ConnectServer → GameServer → DataServer
  • Start order: DataServer → GameServer → ConnectServer
  • Copy flags reviewed (no accidental /MIR; /XD on protected folders)
  • Rollback function tested by restoring a real backup
  • Post-deploy validation includes a test login with a reserved account
  • Database backup handled by a separate routine
  • Maintenance window announced to players
  • Person on call assigned to watch the logs

With this pipeline in place, deployment stops being a source of anxiety and becomes a routine, reversible operation. The biggest gain is not the time saved, but the confidence: you know that, if something goes wrong, the dated backup and the rollback function put the server back online in minutes. Start simple, run it manually a few times, and only then schedule it. Adapt every path and service name to your emulator's reality, because these details always vary by emulator/version.

Frequently asked questions

Do I need to stop the GameServer to swap files?

Yes. Binaries and DLLs in use are locked by Windows, so the deploy has to take ConnectServer and GameServer down before overwriting any executable. Loose data files sometimes tolerate a hot swap, but never rely on that in production.

How often should I deploy?

Deploy whenever there is a change validated in the test environment. The ideal is a small, frequent deploy, with an announced maintenance window, rather than large accumulated packages that make rollback riskier.

Does the pre-deploy backup replace the database backup?

No. The pre-deploy backup protects the server's files (binaries and configs). The database needs its own backup routine via SQL Server, since file deployment should not touch the live database.

How do I roll back if the deploy breaks the server?

Restore the backup folder the script itself created before the copy, and start the services again. That is why the script should always version the backup with a date and time before overwriting any file.

Can I schedule the deploy for the early morning?

Yes, with the Windows Task Scheduler. It is recommended to schedule only already-tested deploys, announced to players in advance, keeping someone on call to watch the startup logs.

GA
Guides & builds editor

Gabriel covers gameplay, class builds, PvP and progression. He tests every strategy on a live server before publishing.

Keep reading

Related articles