Skip to content

Raspberry Pi Host

A Raspberry Pi 4 or 5 with 4 GB runs several game servers comfortably. The scripts in crates/jengine-server/pi/ do everything from a Windows machine: build for the Pi, install the host, deploy the servers, and operate them. Commands below are PowerShell, run from the repository root.

What you get: every game server behind one address, ws://<pi>:9000/<game>, a list of them at http://<pi>:9000/, and a management console at http://<pi>:9000/manage.

  • A Raspberry Pi with a 64-bit OS that uses systemd (Raspberry Pi OS or Ubuntu), on your network, with SSH enabled.
  • Your SSH key accepted by your account there (ssh you@<pi> works without a password).
  • Give the Pi a fixed address in your router. Ubuntu Server does not announce <name>.local, so the scripts use the IP address.
  • Put the Pi’s address in crates/jengine-server/pi/fleet.json (the pi machine’s url and console), or pass it to setup-pi.ps1 -Address.
  1. Make the account the servers run as - once, on the Pi, with your sudo password:

    Terminal window
    scp crates/jengine-server/pi/prepare-pi.sh you@<pi>:
    ssh -t you@<pi> "sudo bash ~/prepare-pi.sh"

    This creates the user jengine (no password, no sudo), lets your SSH keys sign in as it, and turns on linger so its services start at boot. The host tool runs whatever builds are uploaded to it, so a separate account with no sudo is all a leaked token could reach. Everything after this is done as jengine, without sudo.

  2. Install the host:

    Terminal window
    ./crates/jengine-server/pi/setup-pi.ps1

    It builds jengine-fleet for the Pi, makes the tokens (crates/jengine-server/pi/secrets.json - gitignored, on your machine only), installs the systemd user service jengine-host, makes the Pi’s certificate and fetches it into pi-cert.pem, and checks the Pi answers. Run it again any time to upgrade the host tool.

  3. Deploy the game servers:

    Terminal window
    ./crates/jengine-server/pi/deploy-pi.ps1 # every service in fleet.json
    ./crates/jengine-server/pi/deploy-pi.ps1 -Services kotodama # just one
  4. Connect a game. In its server field, type ws://<pi>:9000/<service> - for example ws://192.168.1.50:9000/kotodama.

WhatCommand (./crates/jengine-server/pi/pi.ps1 ...)
Every server’s version, players, uptimestatus
Open the console, signed inconsole
A server’s loglogs kotodama
Restart, stop, start, roll backrestart kotodama (or stop, start, rollback)
The host tool’s own loghost-log
The list players seeopen
A shell on the Pi as jenginessh
The console token, to sign in from a phonetokens
Live ops settings for a gameliveops
Publish a game build’s packs to live opspublish <build folder> -Channel dev
Back up the key and tokensbackup

A deploy is safe with players online: the old server drains, saves everyone and stops, the new one starts, and if it never answers the old one is put back.

A new server is one more entry in fleet.json: a free port, its build’s path, and "args": ["127.0.0.1:{port}", ...] so only the gateway reaches it. Its name is its path.

To restore the key on a new Pi: deploy liveops once, copy the backed-up key over the new one, and restart it:

Terminal window
scp liveops-signing-<date>.key jengine@<pi>:jengine/data/services/liveops/liveops/signing.key
./crates/jengine-server/pi/pi.ps1 restart liveops

If secrets.json is lost, run setup-pi.ps1 again: it makes new tokens and installs them on the Pi.

Terminal window
./crates/jengine-server/pi/setup-pi.ps1 -Address 192.168.1.60

fleet.json follows, and the Pi’s certificate is made again for the new address. Games need the new address in their server field (and in their live ops settings, which means a rebuild - another reason for a fixed address).

~jengine/jengine/jengine-fleet the host tool
~jengine/jengine/host.env its tokens (readable by jengine only)
~jengine/jengine/tls/ its certificate and key
~jengine/jengine/data/ builds, and each service's folder (its database, its log)
~jengine/jengine/data/console/ the console's fleet file, jobs, history, uploaded builds
~jengine/jengine/data/services/liveops/liveops/signing.key the live ops key - back it up
~jengine/.config/systemd/user/jengine-host.service
  • Plain HTTP on the LAN. The agent’s port (9900) is HTTPS; the gateway and console (9000) are not, so the console token - and the admin token, when publishing to live ops - can be read by someone watching your network. What games receive from live ops is signed, so it cannot be changed.
  • Nothing alerts you. A dead server or a full disk shows on the console when somebody looks.
  • Every known limit is listed in crates/jengine-server/LIMITS.md, rows H1 to H7 for the host.