Skip to content

Installation

Spielstand has two parts: the server, one container on a machine that is always on (home server, NAS, Raspberry Pi), and the agent, one small program on every PC you play on.

1. The server

services:
  spielstand:
    image: tristanteu/spielstand:latest
    container_name: spielstand
    restart: unless-stopped
    ports:
      - "8467:8467"
    volumes:
      - ./data:/data
    environment:
      SPIELSTAND_PUBLIC_URL: http://homeserver:8467
      SPIELSTAND_MIRROR: gdrive:Spielstand
docker compose up -d

Save as ~/.config/containers/systemd/spielstand.container:

[Container]
Image=docker.io/tristanteu/spielstand:latest
ContainerName=spielstand
PublishPort=8467:8467
Volume=spielstand-data:/data:Z
Environment=SPIELSTAND_PUBLIC_URL=http://homeserver:8467
Environment=SPIELSTAND_MIRROR=gdrive:Spielstand
AutoUpdate=registry
HealthCmd=spielstand-server health

[Service]
Restart=always

[Install]
WantedBy=default.target
systemctl --user daemon-reload && systemctl --user start spielstand

The image is also on ghcr.io/firsttris/spielstand and runs on amd64 and arm64. Both files are in deploy/.

Set SPIELSTAND_PUBLIC_URL to the address your PCs reach the server under; it goes into the install command. Then open http://homeserver:8467 and choose the password for the web UI.

2. Google Drive as the offsite copy

The image contains rclone. Set up a remote called gdrive once:

docker compose run --rm --entrypoint rclone spielstand config

Choose Google Drive. Scope drive.file is enough for the mirror; to take over Ludusavi backups that another program put on the Drive, choose the full drive scope. The configuration lands in /data/rclone/rclone.conf, inside the volume. With SPIELSTAND_MIRROR=gdrive:Spielstand every new version is copied there within seconds; Settings shows when the mirror was last current.

Any other rclone remote works the same way, and so does a plain folder (SPIELSTAND_MIRROR=/backup/spielstand).

3. Every PC

In the web UI, Devices → Add device shows a command with a pairing code that is valid for 15 minutes. Run it in a terminal on the PC, as your normal user:

curl -fsSL http://homeserver:8467/install.sh | sh -s -- K7Q-2MX

It needs no root and works on Bazzite, SteamOS (Steam Deck desktop mode), Fedora, Ubuntu, Arch and every other distribution with systemd:

  1. puts spielstand-agent into ~/.local/bin,
  2. pairs the PC with the server and asks for a name ("Steam Deck", "Wohnzimmer-PC"),
  3. sets up and starts the systemd user service spielstand-agent.

The device shows up in the web UI right away. Its first scan finds every game with saves on that PC and uploads them.

Steam launch option (optional)

Without it, the agent notices a game ending within seconds and syncs then. With it, the newest state is loaded right before the game starts as well. In Steam: Properties → Launch options:

spielstand-agent launch %command%

Updating

The server: pull the new image (docker compose pull && docker compose up -d; the Quadlet updates itself with podman auto-update). The agent: run the install command again with a new pairing code, or copy the new binary from http://homeserver:8467/download/agent/x86_64 to ~/.local/bin/spielstand-agent.