# The Blog of Charles Daniels

In this guide, I will discuss how you can go about running a headless factorio game server on your FreeBSD server. My server is an AMD64 system running FreeBSD 11-RELEASE, although to my knowledge nothing in this guide is specific to this version of FreeBSD. In particular, this guide will cover:

• Installing and running the Factorio standalone server.
• Writing a FreeBSD rc.d script to run the Factorio server as a system service.
• Configuring the Factorio standalone server.
• Managing the Factorio standalone servier via RCON.

This guide assumes you are familiar with the basics of UNIX server administration, and the UNIX shell. You must own a legitimately licensed copy of Factorio to run the game server.

Note: except as noted, all commands should be run as root.

## What is Factorio

For the un-initiated:

Factorio is a game in which you build and maintain factories.

You will be mining resources, researching technologies, building infrastructure, automating production and fighting enemies. Use your imagination to design your factory, combine simple elements into ingenious structures, apply management skills to keep it working and finally protect it from the creatures who don’t really like you.

The game is very stable and optimized for building massive factories. You can create your own maps, write mods in Lua or play with friends via Multiplayer.

source

## Software Versions

• FreeBSD 11.0-RELEASE
• Factorio 0.15.30 (experimental release)
• RCON 1.0.2

Last updated: 2017-07-24

## Installing Factorio

We will install Factorio under it’s own prefix in /opt, which will run under it’s own user account (for security). Before starting, you should enable Linux binary compatibility on your server. To get the Linux libraries needed to run the server, you should install linux_base-c7 (CentOS 7.X compatibility).

First, we will setup the Factorio user account:

pw useradd factorio


Now, we will create the required /opt folder. For convenience, and to make snapshots easy, you can optionally create /opt/factorio as a ZFS filesystem. if you don’t know what that means, just make it as a folder.

To make /opt/factorio as a ZFS filesystem:

zfs create -o mountpoint=/opt/factorio zroot/factorio


OR (don’t do both!)

To make /opt/factorio as a normal directory:

mkdir -p /opt/factorio


Set this directory to be owned by the factorio user:

chown -R factorio:factorio /opt/factorio


Henceforth, we will run as the factorio user account (su factorio) - all commands should be run as the user factorio unless otherwise noted.

Download the Factorio headless server for Linux from this page. The current version at the time this article was last updated is noted in the previous section. Save the current release tarball to /opt/factorio, and let’s call it /opt/factorio/factorio-release.tar.gz. Extract it and move the content’s to the current directory:

cd /opt/factorio
tar xvf factorio-release.tar.gz
mv factorio/* ./
rmdir factorio


Optionally, you can also remove the release tarball as well. We will not be using it again in this guide.

To test that you have installed Factorio correctly, and that Linux emulation is working as it should, you can run:

bin/x64/factorio --version


Version: 0.15.30 (build 30727, linux64, headless)
Binary version: 64
Map input version: 0.12.0-0
Map output version: 0.15.30-1


## Running Factorio as a Service

While reading this section, you may find the document Practical rc.d scripting in BSD helpful as reference material.

Note: in this section, we are running as root again.

Place the following script at /usr/local/etc/rc.d/factorio. Be sure to read through the script and configure it to your needs. Don’t forget to mark the script executable with chmod +x.


#!/bin/sh

# KEYWORD: shutdown

. /etc/rc.subr

# service name
name=factorio

# "on/off" variable for /etc/rc.conf
rcvar=factorio_enable

load_rc_config $name :${factorio_enable:=no}  # default disabled

# command to start the service
start_cmd="${name}_start" # command to stop the service stop_cmd="${name}_stop"

### factorio-specific configuration ###

# factorio installation dir (should contain bin/x64/factorio)
FACTORIO_PREFIX=/opt/factorio

# factorio binary path
FACTORIO_BINARY="$FACTORIO_PREFIX/bin/x64/factorio" # factorio save file FACTORIO_SAVE_FILE="$FACTORIO_PREFIX/serversave.zip"

# factorio server port (default is 34197)
FACTORIO_PORT=34197

# bind IP (XXX.XXX.XXX.XXX:port)
FACTORIO_IP="0.0.0.0:$FACTORIO_PORT" # RCON port FACTORIO_RCON_PORT=34198 # RCON password (CHANGE THIS!) FACTORIO_RCON_PASSWORD="default" # server server-settings.json FACTORIO_SETTINGS="$FACTORIO_PREFIX/data/server-settings.json"

# path to write console logs to
FACTORIO_LOGFILE="/var/log/factorio.log"

# path for the pidfile
FACTORIO_PIDFILE="/var/run/factorio.pid"

# user to run the server as
FACTORIO_USER="factorio"

# build up the factorio arguments list
FACTORIO_ARGS=" --bind $FACTORIO_IP --rcon-port$FACTORIO_RCON_PORT --rcon-password $FACTORIO_RCON_PASSWORD --server-settings$FACTORIO_SETTINGS --start-server $FACTORIO_SAVE_FILE" ####### factorio_get_running_pid() { # get the PIDfile stored on disk. If the PID is current running, echo it, else # return 1 if [ -e "$FACTORIO_PIDFILE" ] ; then
PID=$(cat "$FACTORIO_PIDFILE")
fi

N=$(ps aux | grep "$PID" | grep -v "grep" | wc -l)
if [ $N == 1 ] ; then echo "$PID"
else
return 1
fi
}

factorio_start() {
# check if there is already a copy of this service running
if [ -e "$FACTORIO_PIDFILE" ] ; then RUNNING_PID=$(factorio_get_running_pid)
if [ $? -ne 0 ] ; then # there is a stale pidfile rm "$FACTORIO_PIDFILE"
else
echo "factorio is already running with PID $RUNNING_PID" exit 1 fi fi # back up the old log file if [ -e "$FACTORIO_LOGFILE" ] ; then
mv "$FACTORIO_LOGFILE" "$FACTORIO_LOGFILE.old"
fi

# we have to create the log file so we can chown it to the factorio user
touch "$FACTORIO_LOGFILE" chown "$FACTORIO_USER" "$FACTORIO_LOGFILE" # launch the server /usr/local/bin/sudo -u$FACTORIO_USER sh -c "$FACTORIO_BINARY$FACTORIO_ARGS 2>&1 > $FACTORIO_LOGFILE" & PID=$!
echo "$PID" > "$FACTORIO_PIDFILE"
echo "started $name, pidfile is:$FACTORIO_PIDFILE, PID is $(cat$FACTORIO_PIDFILE) "

# make sure the server started correctly
sleep 5
factorio_get_running_pid > /dev/null
if [ $? -eq 0 ] ; then echo "factorio is running with PID$PID"
else
echo "factorio failed to start, check $FACTORIO_LOGFILE" exit 1 fi } factorio_stop() { # check to see if factorio is really running RUNNING_PID=$(factorio_get_running_pid)
if [ $? -ne 0 ] ; then echo "factorio is not running." exit 0 fi # if so, shut it down gracefully echo "Killing PID$RUNNING_PID..."
kill "$RUNNING_PID" sleep 10 # clean up the pidfile factorio_get_running_pid > /dev/null if [$? -ne 0 ] ; then
# the server has closed
echo "cleaning pidfile..."
rm "$FACTORIO_PIDFILE" else # the server is still running, try again echo "waiting for factorio server to stop..." factorio_stop fi echo "factorio has stopped." } # implement "status" command if [ "$1" == "status" ] ; then

RUNNING_PID=$(factorio_get_running_pid) if [$? -ne 0 ] ; then
echo "factorio is not running."
else
echo "factorio is running with pid $RUNNING_PID" fi exit 0 fi run_rc_command "$1"


This script will allow us to:

• Run factorio as a background daemon, rather than leaving it attached to a console session.
• Start and stop the factorio daemon.
• Check if Factorio is running or not.
• All of this via the standard rc componant of FreeBSD.

Further, thanks to the line # KEYWORD: shutdown, the Factorio service should be shutdown safely if the system is powered off through normal means (/sbin/shutdown).

Note that this script isn’t perfect by any means - this is my first BSD rc.d script, so I’ve probably missed some things. If you have a suggestion for how to improve this script, please send me an email!

## Configuring the Factorio Server

You can edit the file /opt/factorio/data/server-settings.json to configure Factorio. You can find some relevant information on this subject on the Factorio wiki, however, I have found the following modifications are particularly convienient:

• autosave_interval - should be set to a fairly low number (I suggest 3 minutes); raise it if it causes performance issues.
• autosave_slots - I prefer to set this to a high number. Combined with a short autosave interval, this will give you a highly granular, but also long-lived backup history (if you have the disk space to space!)

## Using the Factorio Server

The first time you start the server via service factorio onestart, you will probably get a nasty error like this:

started factorio, pidfile is: /var/run/factorio.pid, PID is 1234
factorio failed to start, check /var/log/factorio.log


If you consult the logfile, you will see that this error is caused by the server’s world save file not existing:

0.504 Error ServerMultiplayerManager.cpp:94: MultiplayerManager failed: "File /opt/factorio/serversave.zip does not exist."


Fortunately, this is very easy to rectify, simply run as the factorio user:

/opt/factorio/bin/x64/factorio --create /opt/factorio/serversave


Now you should be able to launch the server with service factorio onestart

You may have noticed that simply running service factorio start makes rc yell at you with an error like this:

Cannot 'start' factorio. Set factorio_enable to YES in /etc/rc.conf or use 'onestart' instead of 'start'.


This is because the service has not been enabled. To enable the service (which will also cause your factorio server to boot when your turn on your FreeBSD server), add the line factorio_enable=YES to /etc/rc.conf.

## Managing the Factorio Server with RCON

RCON is an extremely helpful tool for managing Factorio servers which run headlessly. It can be downloaded from a forum post. You can connect to your Factorio server with RCON via the information you configured in the rc script above.

Disappointingly, this tool does not run on UNIX systems, nor could I get it to run under WINE. However, running RCON via Parallels on my MacBook worked quite well.

For now, the main uses of RCON are to create additional saves on the server, send messages to and amdinistrate the connected players, and to terminate the server safely. This is valuable if you want to give operators access to administrate your Factorio server, but without giving them access to start and stop services on your FreeBSD host. Likewise, RCON is also useful for sending messages or otherwise interacting with players without launching the Factorio client first.

## Conclusion

Thus, with a little know how and some shell scripts, it is quite straightforward to run Factorio on FreeBSD thanks to FreeBSD’s excellent Linux emulation. Using the method outlined above, it can even be run as a background daemon, without requiring one to leave a console session attached. Furthermore, the RCON administration tool allows one to perform common administrative tasks on the Factorio server without requiring a Factorio game client to be running, or shell access on the FreeBSD host running the game server.