UNET Server Hosting Tutorial
This tutorial will teach you how to make a headless mode server that can be used to run your code on a dedicated server, allowing you to test your network games in a real world environment.
We will find a decent host for our game, and then transfer and run our game server binary on it. As with any of our other tutorials, we will explain the whole process step by step, so that everyone can understand it.
Please read the tutorial carefully as there are a few gotchas that we will mention later in the tutorial, mainly if you are planning to use a server provider such as Google, Amazon or Microsoft Azure.
In addition, this tutorial requires you to pay a server provider to be able to rent a server for your game. Many providers will not do free trials and any free server hosting services from unknown companies should be avoided for security reasons.
A little background information
Starting from Unity 2018.3, Unity allows us to build "Server Builds" of our Unity games. This is especially useful as you can build server instances that only contain the multiplayer levels, while your main instances have everything else such as join game menus, etc. One benefit these builds have over their normal counterparts is that they require no graphics card installed in your server.
Previously, Server Builds were only available for Linux platforms. However, thanks to recent versions of Unity, Windows and Mac OS are supported for Server Builds as well. This tutorial will focus on Windows and Linux servers only.
Linux Server vs Windows Server Instances
One might ask themselves the question "What operating system should I use for my server? There's so many!". The truth is that there's actually two major operating systems, Windows and Linux. The Server family of Windows is preferred for corporate and enterprise environments, while Linux is the go-to solution for servers. Before we begin, let's look at some benefits and downsides of both flavours of operating systems:
Windows Server Instances
Windows Server offers you a familiar Windows experience with some powerful server-only features, unless you opt for Server Core which just gives you a very basic Command Prompt. That means what you do on your desktop version of Windows can be done on Windows Server with some caveats.
Since Windows Server is designed for business and enterprise users, it can confuse people who haven't used a server operating system before. That said, for the majority of the time, it will operate much like a desktop version of Windows as previously mentioned.
There's also an additional licensing fee since Microsoft requires all server instances to be licensed. Compared to a Linux equivalent server instance, Windows Server instances are more expensive in the long run. For people who want the comfort of Windows and are only using it to test their game before deploying it into the wild, then this OS is a good choice.
Linux Server Instances
Linux rules the server platform. The secret to its success is that it's supported by thousands of communities, companies and server providers. It runs literally anywhere - toasters, single-board computers, coffee machines and laptops just to name a few - and is secure by design. Not to mention, the diversity of the distributions mean there's a Linux variant for gaming, science, security, data recovery, and of course servers.
You usually don't get a desktop experience unlike Windows Server instances, and most of the administration is done via the command line over SSH. While this might sound painful at first the ability to have control over what software is installed and how it's updated outweighs the negatives.
For this tutorial, we'll explain how to set up your game mainly using a Linux server instance. Windows Server users shouldn't feel left out - we'll cover a few Windows Server-specific things too.
Preparing our game to run on a Server
Our first step is to open our Game Project and select File -> Build Settings.... Then, we make sure we're building for the Linux (or Windows if you are going for Windows Server) platform, specifying x86_64 for the Architecture and selecting Server Build. This instructs Unity to output a lighter build than normal for use on our new server.
Note: The above screenshot is targeting Linux 64Bit.
After pressing the Build button, Unity will create the headless executable in the directory that we specify. Since we have to transfer the build to the server later, so let's also compress it (using 7-Zip, WinRAR or some other archiver like Ark or File-Roller on Linux) as one zip file and name it headless.zip:
Note: If you build for Windows, you will notice that you have a few files including an executable and a Data folder. You will need all files to run it on Windows Server.
Renting a Server
In order to host the game server on the Internet, we first need to rent a server. For this tutorial, we are going to choose a virtual private server (also known as a VPS for short). Most hosting companies offer virtual private servers and dedicated servers, and a simplified comparsion is as follows:
Virtual Private Server
A virtual private server means that we share the resources with other virtual private servers that all run on the physical machine (called the host) using a method called time-slicing. Such time slices are represented by a virtual CPU (called a vCPU): the more vCPUs you have assigned to your virtual private server, the more processing time on the host your server has.
Note: More vCPUs is not always better, for reasons we'll discuss later.
This platform is cheaper, but your VPS can get placed onto host servers that are overloaded and as a result, performance can suffer.
Dedicated Server
A dedicated server means that it's just one physical machine all for us alone. These cost a lot more to rent, but you get all the resources the server has to offer.
One downside is that you must treat your server like a normal computer - make regular backups, making sure it's up to date, etc. If a piece of hardware fails in your server, you will often need to submit a support ticket to your hosting provider to get back up and running.
For development and testing, a virtual private server is totally fine though, and is a cheaper way to go. When it's launch day and you need real performance, then dedicated servers are the way to go.
Hardware Selection
When it comes to the hardware, we have to understand that all our Unity Scripts run in a single thread, so we should prefer a server with only a few really fast cores over many slow cores. For example, 4 cores with 4 GHz would give us better performance than 8 cores with 2 GHz.
Note that some hosts will not tell you the hardware specifications of their host nodes for various reasons. You will be able to know the speed of your host by checking Task Manager on your Windows Server instance, or by running lscpu in your Linux instance SSH terminal.
The amount of RAM we need for our server mostly depends on the amount of entities in our Scene(s), so it's recommended to test the game locally first and monitor the RAM usage over a few hours. For small basic games like Pong or Tanks, a server with at least 512 MB is sufficient - just keep in mind that you will need to give some of this memory to keep the OS running. Ideally, up to 2GB is enough for in-depth testing. In production, you would opt for 4GB or even more depending on how big your game is.
Note: Do not attempt to use a Windows Server instance with less than 2GB of RAM as a game server - you will suffer very poor performance as Windows will very likely complain it's running low on memory soon after launching the game server instance. A minimum of 2GB is recommended, 3GB or more is preferred.
The storage device should be an Solid State Drive (SSD for short). An SSD is a lot faster than a tranditional slower Hard Disk Drive (HDD for short) and this means that loading and saving data from/to the drive happens as fast as possible. For small games, this may make a very minimal difference.
For medium to large scale games with databases (such as games built with uSurvival and uMMORPG), you will find that you will run out of room quickly if the disk is too small and you have high user counts that need to store lots of data per user account.
Keep in mind you will be sharing some of this storage space with the operating system, however most providers will give you enough storage on even the cheapest plans.
Windows Operating System
The best choice for a server running Windows is the latest version of Windows Server. At time of writing this, this was Server 2019 however running a older version of Windows Server such as 2012 or 2016 that is still supported is fine too. Just keep in mind the pros and cons of Windows as described earlier in this tutorial.
Linux Operating System
The best choice for a server running Linux is a distribution that is supported by Unity. Since those are a dime a dozen, we'll just stick to one of the best server operating systems called Ubuntu. This distro is supported by Unity Technologies themselves.
For the rest of this guide, we will be focusing on Linux Servers. If you order a Windows Server instance, all you need to do is fire up Remote Desktop Connection on your Windows machine once it is provisioned. On MacOS, this is available on the App Store under "Microsoft Remote Desktop". On Linux, you will need to check your package manager for a Remote Desktop compatible application.
Then it is a matter of simply copying and pasting the game files onto the server using the Remote Desktop application.
Renting the Server
As stated previously, please avoid Microsoft Azure, Amazon Web Services and Google server instances for now. These providers have complicated two-layer firewall systems. Configuring the two-layer firewall system is outside the scope of this tutorial.
We recommend to use a major hosting company that doesn't mess with the networking settings too much. Smaller companies and Big-name companies like the ones mentioned above tend to have weird configurations and limitations that may cause UNET bugs. The following provider works perfectly fine with our uMMORPG product and has outstanding customer support:
Other high quality providers that are worth mentioning and have excellent track record:
It's important to select Ubuntu as the operating system.
After purchasing, it can take up to a few hours for them to setup (provision) our server. Some hosts will be almost-instant, some take a little while. Keep your email inbox open during this time. It won't be long until you will receive an email with server details. The email contains something like:
- IP Address: 1.2.3.4
- Port: 22
- Username: root
- Password: password-set-at-setup-time
If you don't get a username and password in the email, you may need to log into the control panel and you may find it there. Vultr auto-sets a random root password on every instance, which can be viewed by clicking the following icon in your instance control panel:
Linode will set the root password to the one you entered during setup of your server instance.
Remember that the password is case sensitive: HelloWorld2019 is not the same as helloworld2019 or HeLloWoRlD2019.
NEVER give this password out to anyone unless you want to have your server compromised by a rogue third party. In addition, make sure it is strong enough so it's not easily guessed. Feel free to use a non-english word plus a set of digits and a symbol as your password.
Configuring the Linux Server (one time setup)
SSH stands for secure shell, which is like running a Terminal or Command Prompt on the remote server.
Before we get started, we need to do some setup. You will not need to do this more than once.
Requirements
- Windows users can use the PuTTY tool.
- On Linux and MacOS, we can simply open a Terminal and use the ssh command directly.
Battening down the hatches
Do not skip this part. You do not want to run any Unity game server instances as the administrator (root). If your game is compromised with a remote code execution exploit, then you can suffer irrepairable damage to your servers' data depending on the severity of the exploit.
Firstly, we need to create a normal user because we should never run our game server as root.
Windows
Fire up PuTTY. In the Server address field, enter the server's new IP address. Leave Port 22 as default and click Open:
Note: replace your-server-ip
with the server's IP address.
You will be asked for the first time if you accept the server's SSH key. Say "Accept" or "Yes" and you will be then be asked for the login username. Enter "root", followed by enter. It will then ask you for the root password. Enter your password slowly, as there will be no on-screen indication (eg. stars or dots) to indicate the password is going through. Then press enter.
After a slight pause, you should see something similar to the following:
Last login from 127.0.0.1 on 28th July 2019 00:00 AEST
There has been 99 failed login attempts since last login.
Welcome to Ubuntu 18.04 LTS!
(...)
root@ubuntu-server:~#
Follow the steps in "Installing our requirements" section.
MacOS/Linux
Fire up a Terminal Window. Then in your terminal, execute the following:
ssh root@your-server-ip
Note: replace
your-server-ip
with the server's IP address.
You may get a message saying that the host key could not be verified. Type yes
, followed by pressing enter (return on Mac) as this will only be asked once. We will be asked for our password (the root SSH password) after a few seconds. Enter your password slowly, as there will be no on-screen indication (eg. stars or dots) to indicate the password is going through. Then press enter/return again.
It should look similar to the following:
ssh root@1.2.3.4
The server at 1.2.3.4 could not be verified. [...]
Do you wish to continue connecting? (Yes/No) yes
root@1.2.3.4's password: (your password followed by enter)
After a slight pause, you should see something similar to the following:
Last login from 127.0.0.1 on 28th July 2019 00:00 AEST
There has been 99 failed login attempts since last login.
Welcome to Ubuntu 18.04 LTS!
(...)
root@ubuntu-server:~#
Continue with the next step.
Installing our requirements
At the command line, enter the following, pressing enter after each line:
apt update
apt -y dist-upgrade
apt -y install screen tmux sudo zip unzip
Note: We update the package lists, upgrade installed packages and install some tools now as this saves us time later.
If you get any messages asking Do you wish to continue?, answer with either y
or yes
. This is the package manager application asking you if you are sure you know what you're doing.
Creating a new user for our use
At the command line, enter:
adduser your-user-name
Note: Replace
your-user-name
with the username you want. For example, it could be a video game character, your first/last name, an abbrevation, etc. Make sure you remember this username for later - write it down somewhere safe.
After doing so, you'll get the following:
Adding user `your-user-name' ...
Adding new group `your-user-name' (1002) ...
Adding new user `your-user-name' (1002) with group `your-user-name' ...
Creating home directory `/home/your-user-name' ...
Copying files from `/etc/skel' ...
Enter new UNIX password: (pick a good password and enter it here)
Retype new UNIX password: (re-enter your password you just typed in)
passwd: password updated successfully
Changing the user information for your-user-name
Enter the new value, or press ENTER for the default
Full Name []: (press ENTER)
Room Number []: (press ENTER)
Work Phone []: (press ENTER)
Home Phone []: (press ENTER)
Other []: (press ENTER)
Is the information correct? [Y/n] (enter Y and press ENTER)
Make sure you pick a good password when it asks you and after a few questions you will then be returned to the command line.
Then, we need to make this new account able to use administration commands without having to log into the administrator account. We do this by entering:
adduser your-user-name sudo
Note: Replace your-user-name
with the username you created previously.
This will assign you administration powers on commands when calling the sudo
command and entering your password. After doing so, you should get a message that the system assigned you to the sudo
group successfully.
Awesome! You've just made a new user and assigned yourself administrator powers on your system. We need to now reconnect as the user account, not the administrator account. So, at the command line, enter the following:
logout
Note: Pressing Control + D also does the same trick.
This will log you out from the administrator (root) account on the server.
On Windows, PuTTY will suddenly disappear, looking like it crashed. On Mac/Linux, you will get a message saying that the remote host has been disconnected. That's okay - don't panic!
Reconnecting to our server with our new user details
Reconnect to the server again using the username and password you created above (ie your-user-name
rather than root
) and you will get your command line again, running as your own user account.
Keep the Terminal/SSH window open for now - we'll be using this later. Now it's time to start pushing files to the server.
Copying our built game to the server
SCP is a tool that copies a file from our local machine over SSH to the remote server. For Windows, we will use WinSCP. For Mac/Linux, we'll use the built-in scp
tool.
- Windows users need to install the WinSCP tool.
- On Linux and MacOS we can use the scp command in the Terminal.
If you're using Windows, once the WinSCP tool is installed it's time to move on.
Alright, let's begin by copying the headless.zip file to the server.
Windows Users
Firstly, fire up the newly installed WinSCP application and you should be greeted with the following. Remember to replace the shown example text in the appropriate boxes, and click Login when done:
You would enter the server's IP address in the "Host Name" box, leave port number set to 22, enter your newly created username in the "Username" box and the password for that username in the "Password" box. Ensure File protocol is set to SFTP (very important!)
Once logged in, you will get a window like the following:
On the left pane, is your local computer. Normally it will start in your Documents folder, but the drop down menu allows you to navigate around your filesystem.
On the right pane is the remote computer. This will most likely be your user's home directory, /home/your-username
. Much like the left pane, it navigates the servers' filesystem.
We want to use the left (local) pane to navigate to our headless.zip file, and then drag it to the right (server) pane like so:
In a moment when the transfer settings prompt appears, accept the defaults and click OK:
Depending on the speed of your Internet Connection, your file will now be uploading to the server. However, one thing to keep in mind is that uploads to servers are bandwidth intensive, and if anyone else is using your internet connection the upload speed can be affected. You may experience temporary choppiness and lag until the upload is completed.
Once the upload is completed, WinSCP will return back to the dual-pane local and remote filesystem window.
Note: If you have used any dual-pane file managers before, like Norton/Midnight/Total Commander or Q-Dir then the WinSCP interface will look familiar.
You have successfully copied the file to the server! Now, you can decide to leave WinSCP open for further exploring on your own, or close it. Continue to the "Unpacking the File" step.
MacOS & Linux Users
Execute the following in a new Terminal window/tab:
scp /path/to/headless.zip your-user-name@1.2.3.4:~/headless.zip
Note: replace the first path with the path to your headless.zip file and replace
your-user-name
with your new user name and the IP with your server's IP address. For example:
Linux:
scp /home/username/headless.zip username@1.2.3.4:~/headless.zip
Mac:
scp /Users/someusername/headless.zip someuser@1.2.3.4:~/headless.zip
You may get a message saying that the host key could not be verified. Type yes
, followed by pressing enter as this will only be asked once. We will be asked for our password (the new user's password) after a few seconds. Afterwards it starts transferring the file:
Once complete, you will be returned to your normal command line. That was pretty easy, wasn't it?
Unpacking the File
Back on your SSH tab/window that is connected to your server, you can can enter ls to see the files on the server:
ls
Which shows us our file:
Awesome! Now we can unzip our file:
unzip headless.zip
After a bunch of files get extracted from the archive, we will be returned to the command line. We're almost there.
Running the Server
The fun part is to see if our game operates as intended while headless. Let's get right to it and run the following commands to get it started:
chmod +x ./game.x*
./game.x86_64
Note: The asterisk (or star) after the .x part of the file is a wildcard. This would match anything like
game.x86
or game.x86_64
.
If you get a 'file not found' error:
- Type 'ls' to make sure that the file really exists. You might have named your game
myGame
instead of justgame
. Try again using the proper name. Otherwise, if you have a folder that saysgame
, you might need tocd
(change directory) into that folder first by doingcd folder-name
. - If it exists and still shows the error, it's because you are trying to run a 32 bit binary on a 64 bit system that doesn't have 32 bit support installed. Either re-upload your game executable making sure to select the x86_64 architecture when building or run the following commands and then try again:
sudo dpkg --add-architecture i386
sudo apt-get update
sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386
If everything goes correctly after successfully entering the executable name, we can see the default Unity headless output:
Set current directory to /home/dummy/
Found path: /home/dummy/game.x86_64
Mono path[0] = '/home/dummy/game_Data/Managed'
Mono config path = '/home/dummy/game_Data/MonoBleedingEdge/etc'
Initialize engine version: 2018.4.4f1 (5440768ff61c)
Forcing GfxDevice: Null
GfxDevice: creating device client; threaded=0
NullGfxDevice:
Version: NULL 1.0 [1.0]
Renderer: Null Device
Vendor: Unity Technologies
Begin MonoManager ReloadAssembly
- Completed reload, in 0.037 seconds
UnloadTime: 0.400000 ms
[...]
Note: closing the PuTTY/Terminal window will also close the server. Your output may differ - this example output was run under a user called 'dummy'.
It's important to know that this command just runs the game server. UNET also requires us to call the StartServer function after startup. Read our Detect Headless Mode Tutorial for more info. The UNET replacement, Mirror Networking, can auto-start server mode without intervention.
Note: uMMORPG already does that automatically.
Showing Debug Messages
In older versions of Unity Server builds, Unity didn't show any Debug.Log/Warning/Error messages on the console. However thanks to the new Server build option, should any script emit a Log/Warning/Error message it will show up in the console.
Keeping the Server running after closing the Console
By default, the server process will end as soon as we close the SSH session. The solution is to use a little tool called screen that we installed earlier Here is how to use it.
Back in your normal user PuTTY/SSH tab/window, if the game server is still running press Control + C to quit the instance and we can start a new screen session by simply entering:
screen
Some screen versions will throw a little information screen up on first launch, just read the information and press Space or Enter to get past it.
You will be in a virtual session of your main session. Things you do here can keep running while you disconnect from the main session. It's a little complicated to explain, but it is very handy.
Start the game server:
./game.x86_64
Detach from the screen session with:
Ctrl + A and then Ctrl + D
You will see a [detached]
message. The server is still running and you can close the console. To later reattach to that screen session, you would login as your non-root user and enter:
screen -r
This would then reattach the screen instance and allow you to quit the server instance by using Control + C. To terminate the screen instance, on the command line inside the screen session press Control + D. If you see screen is terminating
then you have closed the screen instance correctly. If it logs you out instead, you were not inside the screen session.
(Source)
Connecting with a Game Client
Finally we can open our Unity Project, select the Network Manager component and insert our server's IP address under Network Info in the Network Address field in the Inspector. If we press Play then we can now connect to our remote server!
Wrapping up
In this Tutorial we learned how to run the server remotely in the easiest way possible. We also rented a VPS, created a non-root user to run our game safely without the risk of being compromised if a malicious person finds a code exploit that could damage our server, installed some required applications, uploaded our game and ran it for the first time.
With this knowledge, you'll be one step closer to administrating your own server fleet when you make the next big game that takes the world by storm!
As with any new operating system it is recommended you become familiar with your tools. Windows Server is easier to understand and learn since it has a familiar desktop like normal versions of Windows on desktops and laptops. Linux Servers do require additional effort and time investment but you can do things that Windows Server cannot do.