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
If you're looking for a server but don't know what to pick, how about a $5 Vultr. These have a solid ratio of cost to performance as of my most recent experiments (mid 2019). Also solid: linode, digitial ocean.
If you like my articles and want me to get $$$ when you try out a VPS, you can use my affiliate link and like, maybe they'll pay me something, I don't know.
Vultr FREE $50 Credit https://www.vultr.com/?ref=7983529-4F - expires at some point, claims to give *you* $50, and me $25.
Vultr Regular Referral (incase the above expires) https://www.vultr.com/?ref=7290094 - maybe gives me $10, eventually.
The following commands will install an 12.x version of Node.js.
cd ~
curl -sL https://deb.nodesource.com/setup_12.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 12+ and npm 6+
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.
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. If you just need a random program to test, then git clone one of the nengi game templates.
After we have the game files deployed to the server, we are going to configure nginx to serve the game's static files.
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
sudo nano /etc/nginx/sites-available/default
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.
With respects to running web games, there are a few specific features of nginx that may warrant further reading.
The nginx manual: https://nginx.org/en/docs/.
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.
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 on this remote machine).
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.