Tutorial: Deploying a Game to an Ubuntu Server

This article is a rough draft. The commands have not been tested.

Deploying a nengi instance to a production environment can be daunting. This walkthrough contains the commands neccesary to deploy and run one of the nengi demos or similarly structured game on a virtual private server.

Outline

  1. Install Node.js
  2. Install Nginx
  3. Upload the game
  4. Configure Nginx to server static content
  5. Modifying the game for production
  6. Start the game instance manually
  7. Create a Game Service

Prerequisites

If you're looking for a server but don't know what to pick, I suggest getting a $5/mo linode (https://www.linode.com) and then working through both of the following tutorials before tackling this one.

Initial setup: https://www.linode.com/docs/getting-started/

Basic security: https://www.linode.com/docs/security/securing-your-server/

Install Node.js

The following commands will install an 8.x version of Node.js. At the time of writing this (summer 2018) both the default version of nodejs available to Ubuntu and the 10.x branches have incompatibilities with uws and therefore nengi. I presume these will be ironed out in the near future at which point we can move to a 10+ version of node.

cd ~
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
apt-get install -y nodejs

After installing node.js, verify that node and npm are viable programs by typing:

node -v

and

npm -v

If the installation worked then these commands will return version numbers, e.g. node v8.11.3 and npm 5.6.0

Install Nginx

sudo apt-get install nginx

If nginx installed correctly you should be able to visit the server's ip in a web browser and see the Welcome to Nginx page.

We'll discuss how to get nginx to serve the static files associated with a game later in this tutorial.

Upload the game

For the sake of this tutorial let's pretend that our game is named mmorpg, and our files shall live in:

/srv/mmorpg

I'll be referring to mmorpg a lot, feel free to replace it with the name of your own project, or perhaps something like nengi-3d-demo if you're just deploying an existing nengi demo to learn the linux side of things.

There are many ways to get these files onto the server. One way is to git clone your game within the /srv directory. Another method is to use WinSCP or ssh-copy to upload the files. Do one of those things before moving on.

After we have the game files deployed to the server, we are going to configure nginx to serve the game's static files.

Configure Nginx to serve static content

Our game's static files are located in /srv/mmorpg/public. This folder contains index.html as well as any images, css and javascript we need to display the game's website. One file in particular, app.js, is our game client. This file is created with webpack and is just a static file as far as our webserver is concerned.

Nginx's default configuration in Ubuntu is located at /etc/nginx/sites-available/default. We are going to overwrite this file with the following configuration:

server {
    listen 80;
    
    # use your domain name here
    # or delete this line if just using an ip
    server_name example.com; 
    
    root /srv/mmorpg/public;
    
    location / {
        index index.html;
    }
}

There are a variety of ways to get this configruation onto the server. One way is to edit it directly with the command

  1. sudo nano /etc/nginx/sites-available/default
  2. delete all the lines by holding Ctrl-k (this is the cut line command, if you cut and never paste it'll clear eveyrthing)
  3. copy the configuration from this webpage
  4. paste the configuration into the nano window (focus the terminal window, then right click)
  5. close nano with Ctrl-x
  6. press y to save changes

After the nginx config is saved, reload nginx.

sudo systemctl restart nginx.service

Now if we visit the server ip in a browser, we should see our index.html -- though the game will not yet work.

Learning more Nginx

With respects to running web games, there are a few specific features of nginx that may warrant further reading.

I recommend reading the specific nginx manual page and also trying to find one developer-written article for each topic.

The nginx manual: https://nginx.org/en/docs/.

Modifying the game for production

The nengi game templates/demos magically work when we run npm start. This command in turn runs a series of commands that you can see for yourself (and maybe should, because they vary one demo to the next) in package.json.

Generally speaking, npm start on these demos does at least the following:

If you read the start script in package.json you'll find that the game instance is told to listen on port 8001. In GameClient.js we'll find that the client is hardcoded to make a websocket connection to ws://localhost:8001. And that's how the dev environment is wired together.

To get the game client connected to production, change ws://localhost:8001 in GameClient.js to ws://your-ip-or-domain:8001.

Note that changing GameClient.js only affects the source code, and will not produce a change in app.js until we run webpack and it produces a new bundle. This can be done in our development enviroment by running npm start, and then copying app.js from dev to prod.

Start the game instance manually

At this point we've got nginx serving the files for our game, specifically index.html and app.js -- the latter of which attempts to connect to a game instance in production which we have yet to turn on.

Let's start the game instance on the server!

cd /srv/mmorpg
npm install
node ./server/server.js --port 8001

Note: modify this command as needed. If /srv/mmorpg/server/server.js isn't the path to the script that starts the game instnace, try to figure out what is. Remember that we can always figure out what exactly npm start does in our dev environment by reading package.json.

At this point visiting the server's ip or domain in a browser should produce a playable game. Take a moment and be happy, we're almost done!

But we're not finished, we must turn the game instance into a service that can run on its own (without us having to stay connected and executing a command).

Create a Game Service

Services in Ubuntu are created using systemd. I'm going to provide a file that will specify our service, but if you'd like to learn more, research "Ubuntu systemd."

sudo nano /etc/systemd/system/mmorpg.service

Paste in the following, but change User=root to your own user if you have one.

[Unit]
Description=mmorpg server instance 1
After=network-online.target

[Service]
Environment=NODE_ENV=production
Type=simple
User=root
WorkingDirectory=/srv/mmorpg
ExecStart=/usr/bin/node ./server/server.js --port 8001
Restart=on-failure

[Install]
WantedBy=multi-user.target

What does it all do? Well essentially it goes to the /srv/mmorpg directory and runs the command /usr/bin/node ./server/server.js --port 8001 which is just the longhand way of executing node and the command we tested above.

It does some other cool things too, like it specifies that the program should be restarted if it crashes, and that the program should be started after the machine reboots, but only after the network interface has finished loading (awesome, right?).

Creating multiple service files that run the game instance on different ports (e.g. 8001 through 8020) allows us to run multiple game servers on the same machine. This and other more ambitious setups will covered in future tutorials.

Now that the service file is created, tell systemd to reload, which will result in it processing our new service file:

sudo systemctl daemon-reload

enable the service (makes it so the service can start itself after a reboot)

sudo systemctl enable mmorpg.service

start the service (actually runs the service)

sudo systemctl start mmorpg.service

Double check that you can connect to your website and play the game. If that is working, then reboot the server and check the website again to confirm that nginx.service and mmorpg.service can start up on their own.

Congratulations! You've setup a file server and deployed a game server!

With practice and study the above can be repeated in 5 - 30 minutes, and with a lot of practice we can ascend from this whole thing and use automation to modify or create hundreds of servers at once. Automation is powerful, and linux likes to be automated.