Running a Dedicated Server
This article explains how to deploy a Voxel Turf Dedicated Server on a Linux VPS.
Deploying a VPS
You can grap a cheap VPS. A 1 core VPS will get you started but it is recommended that you have a 2 core VPS.
This article assumes that you have one. HOST can be substituted with the IP address of the server (eg 1.2.3.4).
SSH into the server
(enter this on your local linux termanal)
LOCAL MACHINE:
ssh root@HOST
Set up a user
useradd -m turf
passwd turf
adduser turf sudo
su - turf
Security (Optional)
Set up passwordless access via ssh (using keys and not passwords)
LOCAL MACHINE:
ssh-keygen
ssh-copy-id -i ~/.ssh/id_rsa turf@HOST
Set the ssh port to something other than the default (21). This will help stop people trying to brute force into your server. Also disable root login & password login. To do this, change:
sudo nano /etc/ssh/sshd_config
To:
Port <NEW PORT NUMBER>
PermitRootLogin no
ChallengeResponseAuthentication no
PasswordAuthentication no
UsePAM no
To login to your server you'll have to use:
ssh -p <NEW PORT NUMBER> turf@HOST
Tips
You can set the default shell to bash on the server. This enables tab completion and arrow keys.
sudo chsh -s /bin/bash USERNAME
Installing Voxel Turf
Installing Dependencies
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install libsdl2-2.0-0
sudo apt-get install libsdl2-net-2.0-0
Installing Steam and SteamCMD
sudo apt-get install lib32gcc1
mkdir Steam
cd Steam
wget http://media.steampowered.com/client/steamcmd_linux.tar.gz
tar -xvzf steamcmd_linux.tar.gz
Alternatively you can just copy the files from a linux installation of Voxel Turf onto the server
Using SteamCMD to install Voxel Turf
./steamcmd.sh
In Steam>
login anonymous
force_install_dir /home/<USER>/turf
app_update 526340
quit
You should be now able to run the server and play.
To install a beta branch use:
app_update 526340 -beta beta validate
Running The Server
Running vtserver --help
will give you a list of command line switches.
Start Command
An easy way to generate a start command is to run the game locally (on your machine) and extract the start command from the logs (GAMEFOLDER/logs/startserver.log
).
You should see something like this:
--serverName "YOUR Turf Server" --saveGame "Sora_Turf" --publicGame OFF --dedicated OFF --difficulty 1 --maxPlayers 8 --hostPlayer 36563646 --newGame ON --gameMode "Turf" --genmap 4096 4096 --randomSeed "46756168" --steam
Change it to
--serverName "NAME Turf Server" --saveGame "GAMESAVENAME" --publicGame ON --difficulty 1 --maxPlayers 8 --gameMode "Turf" --genmap 2048 2048
Permissions
Go to GAMEFOLDER/settings/globalpermissions.txt and make it look like:
%ADMINS
;UID
replace ;UID with the UID from steam (SteamID3) For example "[U:1:145678]" so I put ";145678" Can be found here: http://steamid.co/ or from "--HostPlayer" in startserver.log on the local machine.
Advanced Stuff
Installing Workshop Mods
You can use the following script (or similar) to install Steam Workshop mods
login anonymous
force_install_dir /home/<USER>/turf/workshop/
workshop_download_item 404530 1139738481
workshop_download_item 404530 1146791667
workshop_download_item 404530 1147901316
workshop_download_item 404530 1148991672
workshop_download_item 404530 1150505297
workshop_download_item 404530 1151247017
workshop_download_item 404530 1151814594
workshop_download_item 404530 1155491803
workshop_download_item 404530 1157290153
workshop_download_item 404530 1161093711
workshop_download_item 404530 1161805016
workshop_download_item 404530 1163198197
workshop_download_item 404530 1173209773
workshop_download_item 404530 1186472758
workshop_download_item 404530 1188474602
workshop_download_item 404530 1194894626
workshop_download_item 404530 1214171560
workshop_download_item 404530 1214209573
workshop_download_item 404530 1228209888
workshop_download_item 404530 1232559786
workshop_download_item 404530 1286749403
workshop_download_item 404530 1292765889
workshop_download_item 404530 1293667849
workshop_download_item 404530 1297767382
workshop_download_item 404530 1313810046
workshop_download_item 404530 1356700312
workshop_download_item 404530 1357159347
workshop_download_item 404530 1359235841
workshop_download_item 404530 1374585114
workshop_download_item 404530 1382550977
workshop_download_item 404530 1388371537
workshop_download_item 404530 1414621518
workshop_download_item 404530 1362695804
workshop_download_item 404530 1422753063
workshop_download_item 404530 1439594806
workshop_download_item 404530 1438699284
workshop_download_item 404530 1448258410
workshop_download_item 404530 1448258410
workshop_download_item 404530 1567312287
workshop_download_item 404530 1569424047
workshop_download_item 404530 1502040207
workshop_download_item 404530 1686359089
workshop_download_item 404530 1669912546
workshop_download_item 404530 1711533908
workshop_download_item 404530 1408356394
workshop_download_item 404530 1859938129
workshop_download_item 404530 2158310645
workshop_download_item 404530 1220858879
workshop_download_item 404530 1321497749
workshop_download_item 404530 1165605817
workshop_download_item 404530 1254858697
workshop_download_item 404530 1781089616
workshop_download_item 404530 2447555026
workshop_download_item 404530 2413865435
workshop_download_item 404530 2383133708
workshop_download_item 404530 1427795268
quit
And then you make vtserver "see" the mods using a symbolic link
cd ~/turf/
rm -rf mods
ln -s workshop/steamapps/workshop/content/404530/ mods
Running the Server Continuously
This allows you to auto-restart the server if it crashes. You can find this script in /linux_server_admin_scripts_and_instructions/runvtserver.sh
.
#!/bin/bash
BASE=/home/USER/
DIR=$BASE/turf/
while :; do
# Run the server
$DIR/vtserver --saveGame SAVE_FILE --publicGame ON --maxPlayers 8 --serverName "SERVER_NAME"
sleep 1
done
It is recommended that you run runvtserver.sh
through solo.pl
(which is provided in /linux_server_admin_scripts_and_instructions/solo.pl
. Solo.pl will ensure that only one instance of the script is running. Solo.pl binds to a port, not a lockfile so it won't break if your system randomly hard resets.
Use crontab (crontab -e
) to enter the following:
* * * * * /home/USER/solo.pl -port=3801 -verbose ./runvtserver.sh >/dev/null 2>&1
Port 3801 is the lock port for solo.pl, NOT the port that vtserver uses. vtserver uses port 5728 by default. The >/dev/null 2>&1
is to suppress crontab trying to log and email the console output of vtserver
This provides triple redundancy: When the server starts up crontab will run solo.pl which starts runvtserver.sh which runs vtserver. If vtserver crashes then runvtserver.sh will immediately restart it. Crontab will start runvtserver.sh if it is not running, and solo.pl prevents crontab spawning endless instances of runvtserver.sh.
Orderly Shutdown
vtserver accepts SIG_HUP interrupts. This will cause an orderly shutdown (save and exit). It will also instruct any connected clients to try and reconnect.
killall -s HUP vtserver
Polling Server Status
vtserver will create a file in the logs directory: logs/server_status.txt
. This file is updated every 30 seconds. You can use this, for example, to update a webpage indicating how many players are on the server.
Here is an example output:
# This file is updated every 30s while the server is running
# timestamp ; serverid ; players ; maxplayers ; public ; serverName ; gamemode ; serverversion
1520494242 ; 3837146104 ; 0 ; 8 ; false ; "" ; "Build" ; 1.1.0-Beta1-g76v
serverscript.lua
Placing a plaintext file serverscript.lua in the games save directory will cause the server to execute the script whenever that save is executed. You can use this to write custom mods for the server, give the players stuff when they log in or even redirect players to other servers (you can make stargates)!
Periodic Shutdown and Restart with serverscript.lua
This can be useful to clear the map of dumped vehicles and fix any bugs that may have creeped into the server's state. Here is an example script from the Lets Build A City server that shuts down the server every 6 hours. It also sets the Message Of The Day and shows some other hooks.
SERVER_RESET_PERIOD = 60*6;
--Worker functions
function timeTillNextServerReset ()
local NH = turf.NetworkHandler.getInstance();
local uptime = NH:getUptimeInSeconds();
return SERVER_RESET_PERIOD*60 - uptime, uptime;
end
function getFormatedTimeTillReset (timeTillReset)
local minutesRemaining = math.floor(timeTillReset/60);
if (minutesRemaining > 2) then return tostring(minutesRemaining) .. " minutes"; end
return tostring(math.max(0, timeTillReset)) .. " seconds!";
end
-- CustomFunc - code injection
customFunc.OnHour_extra = function (GMS, Net, W, timeOfDay)
local NH = turf.NetworkHandler.getInstance();
local timeToReset = timeTillNextServerReset ();
if (timeToReset > 10 and timeToReset < 600) then
NH:broadcastSM ("Server will be rebooting in "..getFormatedTimeTillReset(timeToReset), 0);
end
end
-- On new player login
customFunc.OnNewPlayer_extra = function (GMS, P, I, PCr, W)
-- Give them items, send a message, etc
end
-- Toggleable static bool for sending the "restart in X seconds" messages
customFunc.pollServerTick_extra_static_tickCount = 0;
-- This function is called every tile-entity tick (4Hz), not every server frame tick (variable, 15Hz/33Hz/67Hz depending on user configuration as defined in serverprefs_1000.txt)
customFunc.pollServerTick_extra = function (NH)
local timeToReset = timeTillNextServerReset ();
-- Send a "RESTARTING IN X" seconds if we are less than 10 seconds to go and this is the first of every 4 ticks.
if (timeToReset < 10 and timeToReset > 0 and customFunc.pollServerTick_extra_static_tickCount == 0) then
NH:broadcastSM ("Rebooting Server in ".. tostring(timeToReset) .. " seconds!", 0);
NH:playSoundToAllClients ("CLICK");
end
customFunc.pollServerTick_extra_static_tickCount = customFunc.pollServerTick_extra_static_tickCount+1;
if (customFunc.pollServerTick_extra_static_tickCount >= 4) then customFunc.pollServerTick_extra_static_tickCount = 0; end
if (timeToReset <= 0) then
NH:sendAllPlayersToServer ("", ""); -- Telling players to go to (empty string) server tells them to drop and reconnect to this server
NH:flagShutdown (); -- Showdown the server. You'll have to restart it with a shell script
end
end
-- No missions on this server!
--turf.MissionHandler.getInstance():removalAllMissions();
-- Set the MOTD
turf.NetworkHandler.getInstance():setMessageOfTheDay ("==============================\nWelcome to the Let's Build A City server!\n ~SnapperTheTwig\n==============================");