noobtuts

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.
Unity Server Mode Building

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:
Headless Mode 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:

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:

Reveal Root Password

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


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:

Connect to server using PuTTY

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.

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:

WinSCP on Windows 64bit

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:

WinSCP Idle Logged in

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:

WinSCP Drag Drop

In a moment when the transfer settings prompt appears, accept the defaults and click OK:

WinSCP Transfer Settings

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.

WinSCP transferring a file

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:
SCP Transfer

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:
SSH LS command

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:

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.