Workload · Hosting a Space Station 14 server

Hosting a Space Station 14 server that stays up, updates itself and keeps your players

To host a Space Station 14 server properly, run the game's headless server under SS14.Watchdog, the helper the SS14 team recommends for real deployments. It downloads official builds, brings the station back when it stops answering, and lets you trigger updates and restarts. Players reach you on port 1212, UDP for the game and TCP for the launcher's status check. This guide takes a Linux machine of your own from empty to a listed server with nightly backups.

The short version
  1. The official watchdog, built from source
  2. Only SSH and port 1212 (UDP and TCP) open
  3. Host rights tied to your own SS14 account
  4. Updates wait for the round to end
  5. Nightly backups with a restore script

How big a machine does a station need?

The SS14 team states no minimum, but their page about their own Wizard's Den hardware helps. A 6-core Ryzen 5 5600X with 16 GB of memory runs two of their game servers, and a virtual machine given six dedicated CPUs and 16 GB runs another two. Their busiest box moves at most about 5 TB a month.

  • The world ticks 30 times a second by default (net.tickrate in CVars.cs), already what the hosting guide suggests, so the config leaves it alone. The guide's speed tweaks go in as YAML lines under EnvironmentVariables in the station entry of appsettings.yml (open it with sudo), each value a quoted string, giving DOTNET_TieredPGO and DOTNET_TC_QuickJitForLoops the value "1", DOTNET_ReadyToRun "0" and ROBUST_NUMERICS_AVX "true" (that one can hurt on some processors). Run sudo systemctl restart ss14-watchdog afterwards when nobody is on, since it drops players.
  • Player data sits in one small SQLite file, preferences.db, which the docs call enough for small servers. PostgreSQL is worth it mainly for a big server or for several servers sharing one database; MySQL and MariaDB are not supported.

The server that fits

Each processor our game server page lists reaches 2,000 or more in PassMark's one-thread ranking, a threshold that page credits to Satisfactory's guide, not to SS14. One community fits the E3-1585L v5 (quad-core, NVMe, 32 GB as built) in all five cities. Two or three stations suit the E-2286M, eight cores in Bucharest, or the 72F3 EPYC in New York and Bucharest. We have not load-tested SS14.

  • Choose x86, not ARM; the steps build for linux-x64.
  • Host close to most of your crew, and time each city from your browser first.
  • A machine already in the rack is yours about 30 minutes once your order is approved; the payment check comes first. Built to your spec, it is 4 to 24 hours when we hold the parts, longer when one has to be bought in.
  • Monthly with no contract, on a port nobody meters.

Up and running in an evening

Order the machine with Ubuntu 24.04, one of the Linux systems offered at checkout, and connect over SSH as a user with sudo.

Step 1, build the watchdog. This block installs Ubuntu's own .NET 10 SDK, which Microsoft says already carries the runtimes SS14 needs, plus ufw. It creates a locked-down ss14 account, compiles and registers the watchdog, adds a helper called station, and opens the firewall for SSH and port 1212 (UDP and TCP, IPv6 too). The SSH rule covers port 22 only; if you moved SSH, let your port in first with sudo ufw allow PORT/tcp. Wait for BUILD OK.

if sudo apt-get update && sudo apt-get install -y dotnet-sdk-10.0 git sqlite3 curl ufw; then
  getent passwd ss14 >/dev/null || sudo useradd --system --create-home --shell /usr/sbin/nologin ss14
  if sudo test -e /home/ss14/SS14.Watchdog || sudo test -e /home/ss14/watchdog; then echo "STOP - built before"
  else
    sudo -u ss14 -H bash -c 'cd ~ && git clone --recursive https://github.com/space-wizards/SS14.Watchdog && dotnet publish SS14.Watchdog/SS14.Watchdog -c Release -r linux-x64 --no-self-contained -o /home/ss14/watchdog' &&
    sudo tee /etc/systemd/system/ss14-watchdog.service >/dev/null <<'EOF' &&
[Unit]
Wants=network-online.target
After=network-online.target
[Service]
User=ss14
WorkingDirectory=/home/ss14/watchdog
ExecStart=/home/ss14/watchdog/SS14.Watchdog
Restart=on-failure
OOMPolicy=continue
[Install]
WantedBy=multi-user.target
EOF
    sudo tee /usr/local/sbin/station >/dev/null <<'EOF' &&
c=$*; if [ "$c" = ready ]; then for i in $(seq 60); do curl -fso /dev/null 127.0.0.1:1212/info && echo READY && exit; sleep 5; done; echo STOP; exit 1; fi
[ "$c" = versions ] && m=GET || m=POST
curl -fsS -X $m --netrc-file /root/ss14-api.netrc "127.0.0.1:5000/instances/station/$c"; echo
EOF
    sudo sed -i 's/^IPV6=.*/IPV6=yes/' /etc/default/ufw && sudo ufw allow OpenSSH && sudo ufw --force enable && sudo ufw allow 1212/udp && sudo ufw allow 1212/tcp &&
    sudo systemctl daemon-reload && echo "BUILD OK" || echo "STOP - see above"
  fi
else echo "STOP - apt did not finish"; fi

Where we depart from the docs. The build output goes straight into /home/ss14/watchdog (the -o option) instead of being copied there. The service is called ss14-watchdog rather than the docs' SS14.Watchdog, so use our name in systemctl commands. It runs as ss14, not root, starts after network-online.target, belongs to multi-user.target, skips the Description line and leaves out DOTNET_CLI_HOME=/tmp, which only Git updates need. If a new box stops after cloning, clear both folders with sudo rm -rf /home/ss14/watchdog /home/ss14/SS14.Watchdog and try again.

Step 2, name your station and yourself. Only if you saw BUILD OK, edit the top line of the next block. NAME is what players see in the launcher and ADMIN is your SS14 login name; it will not run while either still says CHANGE_ME. It writes the station's settings (lobby on, real SS14 logins required, you as host), then adds the station to the watchdog's appsettings.yml, locked to mode 600 because it holds a random API token. The token's copy in /root/ss14-api.netrc keeps it away from ps and your history, and the control API listens on 127.0.0.1:5000 only. Wait for CONFIG OK.

W=/home/ss14/watchdog; NAME="CHANGE_ME"; ADMIN="CHANGE_ME"
if sudo test -x $W/SS14.Watchdog && [ "$NAME" != CHANGE_ME ] && [ "$ADMIN" != CHANGE_ME ] && ! sudo grep -q '^Servers:' $W/appsettings.yml && T=$(openssl rand -hex 24) && [ -n "$T" ]; then
  sudo install -m 600 /dev/null /root/ss14-api.netrc && echo "machine 127.0.0.1 login station password $T" | sudo tee /root/ss14-api.netrc >/dev/null &&
  sudo -u ss14 mkdir -p $W/instances/station && printf '[game]
hostname = "%s"
lobbyenabled = true
[auth]
mode = 1
[console]
login_host_user = "%s"
' "$NAME" "$ADMIN" | sudo -u ss14 tee $W/instances/station/config.toml >/dev/null &&
  sudo chmod 600 $W/appsettings.yml && sudo tee -a $W/appsettings.yml >/dev/null <<EOF &&
BaseUrl: "http://127.0.0.1:5000/"
Urls: "http://127.0.0.1:5000"
Servers:
  Instances:
    station:
      Name: "Station"
      ApiToken: "$T"
      ApiPort: 1212
      UpdateType: "Manifest"
      Updates:
        ManifestUrl: "https://wizards.cdn.spacestation14.com/fork/wizards/manifest"
      TimeoutSeconds: 60
EOF
  sudo systemctl enable --now ss14-watchdog && echo "CONFIG OK" || echo "STOP - see the first error above"
else echo "STOP - no build, a CHANGE_ME left, or already configured"; fi

Step 3, wait, then join. The first launch is preceded by a download of the current official build (ServerInstance.Actor.cs), so run sudo bash /usr/local/sbin/station ready, which waits up to five minutes and says READY or STOP. Then use Direct Connect in the launcher with the server's IP.

Once the Servers section is in appsettings.yml, the second block refuses a rerun. If it stopped after that point, start things by hand (sudo systemctl start ss14-watchdog), then look at journalctl -u ss14-watchdog. A station rebooting every 30 seconds means, per the docs, that the game can't reach BaseUrl.

Making yourself the station's host

A fresh server has no admins, so the second block put your account name in console.login_host_user; when that account joins from home, it gets full host rights. Because only real SS14 logins get in (auth.mode = 1), nobody else can use your name, in our reading of the two settings. Host rights hand over the server and the machine under it, the docs warn, so keep host to yourself and give moderators smaller rights in game.

Getting your station on the public list

Advertising is off until you turn it on, which counts as agreeing to the hub rules; read those first. Give instances/station/config.toml a [hub] section holding advertise = true and a line of standard tags, then sudo bash /usr/local/sbin/station restart applies it, disconnecting anyone playing at once, so pick a quiet moment. If the hub then reports "Unable to contact status address", the internet can't reach your TCP 1212.

New builds without ending anyone's round

The watchdog looks for a new version only when you ask, or when its own service restarts; the game recovering from a crash does not count. Back up with the script below, then type sudo bash /usr/local/sbin/station update. If there is a newer build, the game waits for a calm moment, round end or an empty server, before restarting (ServerUpdateManager.cs). The download only begins once the old build has stopped, so your station is down until it has downloaded and started; sudo bash /usr/local/sbin/station ready tells you when it is back.

Want the old one back? sudo bash /usr/local/sbin/station revert steps back one build at the next calm restart, using the watchdog's revert call (InstanceController.cs, new in September 2026, Manifest updates only). Add 'revert?immediate=true' in quotes for right away, or 'revert?version=NAME' with a NAME from sudo bash /usr/local/sbin/station versions. If the newer build already changed your database, restore your backup as well. For a new watchdog program, back up and wait until nobody is on, then paste `if sudo rm -r -f /home/ss14/watchdog.new && sudo -Hu ss14 git -C /home/ss14/SS14.Watchdog pull --recurse-submodules && sudo -Hu ss14 dotnet publish /home/ss14/SS14.Watchdog/SS14.Watchdog -r linux-x64 -c Release --no-self-contained -o /home/ss14/watchdog.new && sudo rm -f /home/ss14/watchdog.new/appsettings.yml; then sudo systemctl --quiet stop ss14-watchdog.service && sudo -u ss14 cp -r -t /home/ss14/watchdog /home/ss14/watchdog.new/. && sudo systemctl start ss14-watchdog.service && sudo bash /usr/local/sbin/station ready || echo "STOP - service may be down, check journalctl -u ss14-watchdog"; else echo "STOP - build did not finish, nothing changed"; fi. It builds in its own folder and drops that build's stock appsettings.yml while the old program keeps running, and only after that halts the service (a running program can't be overwritten), copies the files in as ss14 and starts it. "Build did not finish" means your station was never touched. "Service may be down" means sudo systemctl start ss14-watchdog` should bring it up; if the copy damaged it, go back to your backup.

Keeping your players' characters safe

Characters and playtime are in preferences.db in the instance's data folder, settings in that instance's config.toml, the token in the watchdog-wide appsettings.yml. Each nightly run of the third block's script copies the database consistently while the game runs (sqlite3 .backup), checks it, packs the watchdog folder around it without the live logs (tolerating tar's changed-file warning), proves the copy made it in, and only then removes archives past two weeks. A restore script comes with it, and each night's log replaces the last.

sudo install -d -m 700 /var/backups/ss14 && sudo tee /usr/local/sbin/station-backup.sh >/dev/null <<'EOF' &&
set -o pipefail; umask 077; H=/home/ss14; B=/var/backups/ss14; S=$(date +%F-%H%M%S); P=prefs-$S.db
sqlite3 $H/watchdog/instances/station/data/preferences.db ".backup '$B/$P'" &&
[ "$(sqlite3 $B/$P 'PRAGMA integrity_check;')" = ok ] &&
{ tar -czf $B/ss14-$S.tar.gz --warning=no-file-changed --exclude='*/data/preferences.db*' --exclude='*/bin/logs' -C $H watchdog -C $B $P; [ $? -le 1 ]; } &&
tar -tzf $B/ss14-$S.tar.gz | grep -cx $P >/dev/null && rm -f $B/$P &&
find $B -name 'ss14-*.tar.gz' -mtime +14 -delete && echo "backup OK $S" || { echo "backup FAILED, see above"; exit 1; }
EOF
sudo tee /usr/local/sbin/station-restore.sh >/dev/null <<'EOF' &&
A=$*; H=/home/ss14; T=$(mktemp -d -p $H) || exit 1
[ ! -e $H/watchdog.previous ] && tar -tzf "$A" | grep -q '^watchdog/appsettings.yml$' && tar -xzf "$A" -C $T && ls $T/prefs-*.db >/dev/null &&
echo "ARCHIVE OK" && systemctl stop ss14-watchdog && mv $H/watchdog $H/watchdog.previous &&
mv $T/watchdog $H/ && mv $T/prefs-*.db $H/watchdog/instances/station/data/preferences.db && chown -R ss14: $H/watchdog &&
systemctl start ss14-watchdog && bash /usr/local/sbin/station ready || echo "STOP - roll back if ARCHIVE OK showed"
rm -rf $T
EOF
echo '17 4 * * * root umask 077; /bin/bash /usr/local/sbin/station-backup.sh > /var/backups/ss14/backup.log 2>&1' | sudo tee /etc/cron.d/station-backup >/dev/null && echo "SCRIPTS OK"

Only if you saw SCRIPTS OK, try sudo bash /usr/local/sbin/station-backup.sh once; it should finish with backup OK. You look after the server and its data while we keep the machine running, so copy the archives somewhere off this machine too.

Bringing a backup back. Pass the full path of an archive from /var/backups/ss14 to sudo bash /usr/local/sbin/station-restore.sh. It won't start while an older watchdog.previous exists. It unpacks and checks the archive first (ARCHIVE OK), then stops the station, renames today's folder to watchdog.previous, restores the database copy under the name preferences.db, fixes ownership and waits for READY.

Saw ARCHIVE OK but no READY, or the data looks wrong? This undoes it. `sudo bash -c 'cd /home/ss14 && [ -e watchdog.previous ] && [ ! -e watchdog.failed ] && systemctl stop ss14-watchdog.service && { [ ! -e watchdog ] || mv watchdog watchdog.failed; } && mv watchdog.previous watchdog && systemctl start ss14-watchdog.service && echo UNDONE || echo "STOP - nothing to undo, or watchdog.failed is in the way"' Once you are happy, delete watchdog.previous (and watchdog.failed, if any) so the next restore can run. Moving to fresh hardware? Run the first block (same firewall included), the third, then the restore. After READY, this turns the service on at boot and writes the token file again, readable by root only. sudo bash -c 'T=$(grep -m1 ApiToken /home/ss14/watchdog/appsettings.yml | cut -d\" -f2) && [ -n "$T" ] && systemctl enable ss14-watchdog && umask 077 && echo "machine 127.0.0.1 login station password $T" > /root/ss14-api.netrc && echo TOKEN FILE OK'`

When this is not the right setup

  • If you want your own rules, maps or content, look elsewhere first. Per the hosting guide, only the config file of a packaged build may be edited, so custom content needs you to fork the game and package it yourself.
  • Licences, in our general view and not legal advice. The game code and the watchdog are MIT, which only asks that the copyright notice and licence go with any copies. The bulk of the assets use CC-BY-SA 3.0, meaning credit plus that licence on changed assets you hand out, and the README flags some as non-commercial (CC-BY-NC-SA 3.0, for example), to be removed before commercial use.

Questions people ask

Will an update kick players in the middle of a round?
Not an ordinary update; the game waits for round end or an empty server. Your own restarts, and immediate=true reverts, happen at once.
Why use the watchdog instead of starting the server by hand?
Started by hand, it stays down after a crash and never updates, as the hosting guide says. The watchdog restarts it and installs new builds at a quiet moment.
Can I run a second station on the same machine?
Yes. Give it its own instance with a different ApiPort, use that number as net.port in its config (the docs warn the watchdog won't match them up for you), and let that port through for UDP and TCP.

Give your crew a station that stays up

Pick a fast machine near your players, monthly with no contract, and install SS14 the moment it is handed over.

Start your station

Read next