Deploy the Game Server

iFun Engine game server can be packed in a single package and copied around to install/upgrade on a live server. The package includes service script and auxiliary resource files as well as server binary. This chapter explains how to manage iFun Engine game servers installed by the package.

Currently, Ubuntu 14.04 / 16.04, Centos 7 are supported. Centos 6.5 is experimentally supported.

Deployment to Ubuntu 14.04 / 16.04

Tweaking the Upstart service file

etc/upstart/init/{project-name}.conf

This file is an upstart configuration file. You can edit the file to control how the upstart service works. In general, default setting is sufficient. For details about Upstart, please refer to Upstart Intro, Cookbook and Best Practises.

Note

If you are using Flavors: Identifying servers according to their role, you need to edit etc/upstart/init/${project-name}.${flavor}.conf.

etc/upstart/default/{project-name}

This file contains default values for variables used in the configuration file. You may want to update the enabled, uid, and gid as follows:

# Sets this to 1 to enable, to 0 to disable
enabled=1
uid=root
gid=root
  • enabled: 1 if the service should start by default.

  • uid: user id to run the service. root, by default. You better consider using a non-root user for security reasons.

  • gid: group id to run the service. Similarly to the uid, non-root user is preferred.

If you changed the upstart conf file, you may want to your custom variables in this file.

Note

If you are using Flavors: Identifying servers according to their role, you need to edit etc/upstart/default/${project-name}.${flavor}.

Warning

Ubuntu 16.04 manages services via systemd instead of upstart. So, please refer to Deployment to Centos 7.

Packaging the Server

Generate a package as explained in Server management part 3: Server packaging. (Running make package after turning on WANT_DEB_PACKAGE in CMakeLists.txt is sufficient.) After getting a deb file, you can verify its contents using dpkg-deb --contents.

$ dpkg-deb --contents example_0.0.1_install.deb
drwxrwxr-x root/root         0 2015-03-16 17:46 ./etc/
drwxr-xr-x root/root         0 2015-03-16 17:46 ./etc/init/
-rw-r--r-- root/root      1090 2015-03-13 16:58 ./etc/init/example.conf
drwxr-xr-x root/root         0 2015-03-16 17:46 ./etc/default/
-rw-r--r-- root/root        72 2015-03-13 16:58 ./etc/default/example
drwxrwxr-x root/root         0 2015-03-16 17:46 ./usr/
...
drwxrwxr-x root/root         0 2015-03-16 17:46 ./usr/lib/
-rw-r--r-- root/root   3305589 2015-03-16 14:46 ./usr/lib/libexample.so
drwxrwxr-x root/root         0 2015-03-16 17:46 ./usr/bin/
-rwxr-xr-x root/root      2688 2015-03-13 16:58 ./usr/bin/example-launcher

Make sure the package contains all the required resource files. Then, copies it to a live server.

Installing / Upgrading the Server

After copying the deb file, install the server using the dpkg command like this: (We assume a project name example here.)

$ sudo dpkg -i example_0.0.1_install.deb
[sudo] password for ubuntu:
Selecting previously unselected package example.
(Reading database ... 424079 files and directories currently installed.)
Preparing to unpack example_0.0.1_install.deb ...
Unpacking example (0.0.1) ...
Setting up example (0.0.1) ...
Processing triggers for ureadahead (0.100.0-16) ...
ureadahead will be reprofiled on next reboot

You may see an installation error message if you have not installed the funapi1-runtime package on the target server. If the case, simply run like this:

$ sudo apt-get install -f

Then, it will resolves the dependency issue and continue to install the game package.

Starting the service

Game server can start as a service like this:

$ sudo start example
example start/running, process 27687

Stopping the service

Similarly, service can be stopped using the stop command.

$ sudo stop example
example stop/waiting

Giving an extra command line arguments

As explained, iFun Engine uses MANIFEST.json as its configuration storage. And this file is also automatically packaged when running make package.

We also have studied in Flavors: Identifying servers according to their role that different flavors could have different MANIFEST.json. But same flavor must share the same MANIFEST.json, since flavor is a unit of the same configuration.

To tweak the behavior, we have introduced tentative ways like Temporarily overriding MANIFEST.json. The technique can be applied in the live environment, too.

But what if we want to add a command line argument rather than one managed by MANIFEST.json? Since iFun Engine uses Google Gflag you may want to add your own flags. .. code-block:: c++

DEFINE_string(my_arg1, “my_default_value”, “description on my_arg1”);

This is perfectly fine and easy to pass the argument especially it’s in the development environment.

$ ./my_game_server-local --my_arg1=my_value

Or, it’s also possible to pass the argument in a predefined environment variable named EXTRA_ARGS.

$ EXTRA_ARGS="--my_arg1=my_value" ./my_game_server-local

OR

$ export EXTRA_ARGS="--my_arg1=my_value"
$ ./my_game_server-local

Either works for the development environment because you can control the shell. But you do not have such a control when running the game server through Upstart. Instead, you need to add the EXTRA_ARGS in /etc/default/<project_name> (or /etc/default/<project_name>.<flavor> if using Flavors: Identifying servers according to their role) Please note that it should be like:

export EXTRA_ARGS="--my_arg1=my_value --my_arg2=another_value"

export must be there and there are no whitespaces before/after =.

Deployment to Centos 7

Tweaking systemd unit file

You need to edit etc/systemd/{project-name}.service in your source directory. In general, default setting is sufficient. For details, please refer to Systemd.

Note

If you are using Flavors: Identifying servers according to their role, you need to edit etc/systemd/${project-name}.${flavor}.service.

Running as a non-root user

It’s recommended to run the service as a non-root user for security reasons. Suppose we want to run a user id of centos and a group id of centos. The unit file can look like this:

[Service]
LimitNOFILE=999999

# It is strongly recommended that one should use uid:gid other than the root
# NOTE: Please update User=, Group=, and ExecStartPre=
User=centos
Group=centos

# Makes the daemon automatically restart
Type=simple
Restart=on-failure
RestartSec=5s

# create directories, and change permissions (with root privileges)
PermissionsStartOnly=true
ExecStartPre=/usr/bin/mkdir -p /var/log/funapi/example/glog \
  /var/log/funapi/example/activity \
  /var/crash/funapi/example
# NOTE: change root:root to service's uid:gid
ExecStartPre=/usr/bin/chown -R centos:centos /var/log/funapi/example/glog \
  /var/log/funapi/example/activity \
  /var/crash/funapi/example

ExecStart=/usr/bin/example-launcher

Packaging the Server

Generate a package as explained in Server management part 3: Server packaging. (Running make package after turning on WANT_RPM_PACKAGE in CMakeLists.txt is sufficient.) After getting a rpm file, you can verify its contents using rpm --qpl.

$ rpm -qpl example_0.0.1_install.rpm
/lib/systemd/system/example.service
/usr/bin/example-launcher
/usr/lib/libexample.so
/usr/share/example/DEBIAN
/usr/share/example/LICENSE
/usr/share/example/README
/usr/share/example/VERSION
/usr/share/example/manifests/default
/usr/share/example/manifests/default/MANIFEST.json
/usr/share/example/resources/.stamp
/usr/share/example/resources/game_data/.stamp
/usr/share/example/resources/json_protocols/.stamp
/usr/share/example/symbols/libexample.so/91EE2EBCB776CA83BCB729D47A709F4A0/libexample.so.sym

Installing / Upgrading the Server

After copying the rpm file, install the server using the rpm command like this: (We assume a project name example here.)

$ sudo rpm -i example_0.0.1_install.rpm

Activating the systemd service

To make the service automatically starts after reboot, we need to activate the systemd service:

$ sudo systemctl enable example

Starting the service

Game server can start as a service like this:

$ sudo systemctl start example

Stopping the service

Similarly, service can be stopped using the stop argument.

$ sudo systemctl stop example

Giving an extra command line arguments

The idea explained in Giving an extra command line arguments applies the same here. That is EXTRA_ARGS must be added in /etc/default/<project name>. However, Centos should drop prepended export like this:

EXTRA_ARGS="--my_arg1=my_value --my_arg2=another_value"

Installing the Server at Non-Standard Location

We have studied how to install the game server using the DEB and RPM (Deployment to Ubuntu 14.04 / 16.04 and Deployment to Centos 7) This is recommended in most cases. However there might be a case that all the files should be installed at a non-standard location. For example, the publisher might request to make the game server runnable under a particular user home directory. In this case, you may need a game server in a gzipped tar file.

Open up CMakeLists.txt and make it generate a TGZ package.

set(WANT_TGZ_PACKAGE true)

Now, make package will generate <project_name>_<version>_install.tar.gz instead of .deb or .rpm.

Note

If using Flavors: Identifying servers according to their role, output should be <project_name>_<version>_install-<flavor_name>.tar.gz.

Assuming a project name hello and a flavor lobby, an output would be hello_0.0.1_install-lobby.tar.gz. Then, we can ship it to the publisher and let it install under any directory (say, /home/zeus).

$ cd /home/zeus
$ tar zxf hello_0.0.1_install-lobby.tar.gz

You can verify that the contents in the gzipped tar file have been extracted under the home directory. This looks fine so far. But what about the service scripts? Since it’s just a tar file, it won’t install the service script and we cannot run the game server as a daemon. This can be nagging. Unfortunately, we need one-time manual job to solve the problem.

Manually registering an Upstart script (Ubuntu 14.04)

After extracting the tar file, you can locate etc/ under /home/zeus/. Again, there should be init/ and default/ under etc/. The former contains an upstart script and the latter has a configuration file declaring variables used in the upstart script.

$ cd /home/zeus
$ ls etc
default init

Assuming a project name hello and a flavor lobby, we will have files like this:

$ ls etc/default
hello.lobby

$ ls etc/init
hello.lobby.conf

Append a line in etc/default/hello.lobby like this:

export GAME_ROOT_DIR=/home/zeus

Warning

export is required.

Tip

There are other variables that you can manipulate.

  • GAME_ROOT_DIR: Specifies the top-level directory of the game server. It defaults to /.

  • GAME_MANIFEST_OVERRIDE: Specifies a path to a MANIFEST override file as explained in Temporarily overriding MANIFEST.json. It defaults to /etc/<project_name>/MANIFEST.override.json.

  • GAME_LOG_ROOT_DIR: Specifies where glog files would be generated. It defaults to /var/log/funapi/<project_name>.

  • GAME_CRASHDUMP_ROOT_DIR: Specifies where dump files would be generated. It defaults to /var/crash/funapi/<project_name>.

  • GAME_GLOG_OPTIONS: Specifies Google’s glog options. It defaults to --max_log_size=10 --stop_logging_if_full_disk.

  • GAME_CONTACT_EMAIL_ADDRESS: Specifies an email address to receive server crash reports. The server must have been correctly configured a postfix. If null, the default, reporting is disabled.

After setting GAME_ROOT_DIR in the default file, copy /home/zeus/etc/default/hello.lobby and /home/zeus/etc/init/hello.lobby.conf to /etc/default/ and /etc/init/, respectively. All set! You can now run using sudo service hello start.

Manually registering a Systemd unit (CentOS 7 / Ubuntu 16.04)

Steps are similar to the Upstart case. After extracting the tar file, you can locate lib/systemd/system/ under /home/zeus/. It contains an systemd unit file. hello.lobby.service in this example.

$ ls lib/systemd/system
hello.lobby.service

Copy the file to /lib/systemd/system/ Then, creates /etc/default/hello.lobby and append a line like below:

GAME_ROOT_DIR=/home/zeus

Warning

Unlike the Ubuntu case, export shouldn’t be used.

Tip

There are other variables that you can manipulate.

  • GAME_ROOT_DIR: Specifies the top-level directory of the game server. It defaults to /.

  • GAME_MANIFEST_OVERRIDE: Specifies a path to a MANIFEST override file as explained in Temporarily overriding MANIFEST.json. It defaults to /etc/<project_name>/MANIFEST.override.json.

  • GAME_LOG_ROOT_DIR: Specifies where glog files would be generated. It defaults to /var/log/funapi/<project_name>.

  • GAME_CRASHDUMP_ROOT_DIR: Specifies where dump files would be generated. It defaults to /var/crash/funapi/<project_name>.

  • GAME_GLOG_OPTIONS: Specifies Google’s glog options. It defaults to --max_log_size=10 --stop_logging_if_full_disk.

  • GAME_CONTACT_EMAIL_ADDRESS: Specifies an email address to receive server crash reports. The server must have been correctly configured a postfix. If null, the default, reporting is disabled.

You can verify by running sudo systemctl start hello.lobby.

Locking iFun Engine Version

It could be catastrophic if auto-update could impact the running game server. Hence, we may want to lock the versions of funapi1-runtime and iFun agents like Authenticator, Biller, and Leaderboard.

On Ubuntu

To lock the version of funapi1-runtime:

$ sudo apt-mark hold funapi1-runtime

After the command, apt-get upgrade will skip the package.

Checking which packages are locked

$ sudo apt-mark showhold
funapi1-runtime

Releasing the version lock

$ sudo apt-mark unhold funapi1-runtime

After this, apt-get upgrade will upgrade the package.

On CentOS

CentOS requires an extra package to lock the version of installed package.

$ sudo yum install yum-versionlock

After installing yum-versionlock, run like this:

$ sudo yum versionlock funapi1-runtime

Then, yum update will skip the locked package.

Checking which packages are locked

$ sudo yum -q versionlock list
0:funapi1-runtime-1.0.0-1680centos7.*

Releasing the version lock

$ sudo yum versionlock delete funapi1-runtime

After this, yum update will try to upgrade the package.

Warning

On CentOS 6, you should do like sudo yum versionlock delete '*:funapi1-runtime*'.

Inspecting the Game Server

Checking the status and the service script logs

As explained, iFun Engine game server is managed either by upstart or systemd. If daemon could not start due to configuration errors or packaging issues, we can inspect the log messages of upstart or systemd like this:

upstart

/var/log/upstart/{project-name}.log contains log messages regarding upstart daemon spawning.

systemd

To access the systemd daemon logs, run journalctl -x -u {project-name}.

Game server logs

iFun Engine game server leaves log files in /var/log/funapi/{project-name}.

  • activity/{날짜}/activity_log.json.*: activity log messages as defined in {project-name}_loggers.json in your source directory.

  • glog/*: Google Glog messages via LOG(...).

Game server dump files

Once the game server crashes, it generates a dump file like /var/crash/funapi/{project-name}/{dump-uuid}.dmp To inspect the dump file, you can use funapi_stackwalk.