isputnik-games

isputnik-games

Docker app from isputnik-games' Repository

Overview

Family games for isputnik.home, in a container of their own. Board games: Dots, Star Battle, Chess, Dominoes and Checkers (Russian draughts), played two on one screen, against the computer, or online between family members, who invite each other and play from any device, phone included. Arcade games: Sputnik Catch and Torpedo Run, with a family high-score table. Everything runs on your server; nothing is sent anywhere. This is an add-on for isputnik.home and does nothing on its own: it has no sign-in and no pages of its own. Install it beside the isputnik container; the family signs in once, in isputnik.home, and finds Games in its menu, at /games on the same address. Set it up from isputnik.home, on Control panel, Settings, Apps, Games. Before installing, press Generate secret there and copy it (it is shown once); paste it into the Gateway Secret field below, which is required. Once the container runs, enter its address on the same page (http://[your Unraid IP]:4200 as installed here) and press Test connection, which then says Paired. Who may play, and from where (home network only, or anywhere), is chosen on Security, App access. Needs isputnik.home 4.38 or newer.

isputnik.games

An add-on for isputnik.home: family games in a project and container of their own. It requires the isputnik.home container, is installed beside it and is reached only through home's /games gateway; on its own it does nothing. Board games: Dots, Star Battle, Chess, Dominoes, and Checkers (Russian draughts). Arcade games: Sputnik Catch and Torpedo Run.

Alpha. Two on one screen, against the computer, and online between family members (invite, accept, play from any device; the page polls for the other side's moves).

How it fits together

The games container never faces the network. The home app proxies /games/* to it over the Docker network and forwards who is signed in, so the family signs in once, in isputnik.home, and every control it has (two-factor, trusted networks, rate limits) applies to the games too. The full design and the contract between the two projects is in docs/plan.md.

browser ──► isputnik.home (:4000) ──► isputnik.games (:4200, internal only)

Running it

With Docker, beside the home app — see docker-compose.yml. Generate one secret (openssl rand -hex 32) and set it as GAMES_GATEWAY_SECRET on the home container and GATEWAY_SECRET on this one; point the home container's GAMES_URL at this container. A "Games" entry then appears in the home app.

The two containers must share a user-defined Docker network. The home container reaches this one by name (http://isputnik-games:4200), and names resolve only on a network you created — Docker's default bridge has no DNS between containers. Compose makes such a network for every project, so the compose file above needs nothing more. With plain docker run, or on Unraid, create it once and start both containers on it:

docker network create isputnik

The image is ghcr.io/isputnikdotnet/isputnik.games (what the compose file and the Unraid template pull) and, the same bytes, isputnikdotnet/isputnik.games on Docker Hub. Both are published by every release tag; latest is the newest release.

Unraid — the repository carries a Community Applications template, isputnik-games.xml, listed in CA as isputnik-games. It publishes port 4200 on bridge, maps /config to /mnt/user/appdata/isputnik-games, runs as 99:100 to match a default appdata share, and asks for one thing: the gateway secret. Pair it from the home app (Control panel → Settings → Apps → Games): the address is http://<unraid IP>:4200, Generate secret makes the secret to paste into this container's Gateway Secret field, and Test connection says Paired. A shared user-defined network (address http://isputnik-games:4200) or br0 with a fixed IP work too; the port mapping is then simply unused. Publishing the port gives nothing away: without the secret every request is answered 401. How the listing was made, for the next companion container: docs/publishing-checklist.md.

Variable Default What it does
GATEWAY_SECRET unset The secret the home gateway signs forwarded requests with. Required in the image, at least 32 characters (openssl rand -hex 32); without one, with a short one, or with the compose example's placeholder the server refuses to start.
PORT 4200 The port to listen on.
HOST 0.0.0.0 in the image, 127.0.0.1 from source The address to listen on.
STATIC_PATH /app/web in the image The built web app, served under /games/.
DB_PATH /config/games.sqlite in the image, data/games.sqlite from source The SQLite file with the online matches. Mount /config as a volume.
PUID / PGID 1000 / 1000 The user the server runs as; the entrypoint takes ownership of /config for it (Unraid: usually 99 / 100).
DEV_USER dev:Developer:admin:en:minimalist Source checkouts only, with no secret set: who the server pretends is signed in (id:name:role:lang:theme).
LOG_LEVEL info trace … silent. At info every request is a line, including each poll for the other side's move; warn keeps only problems.

Logs. The container logs to stdout as usual (docker logs isputnik-games), and the home app shows the same from Control panel → Settings → Games: the newest lines of the server log, and a table of events — who was refused at the gateway check, who invited whom, how a match ended, which move was thrown out, what broke — kept for 90 days in the games database. Every log line names the member and the browser's address the home server forwarded, and carries the home server's request id, so the two containers' logs can be read side by side.

Developing

npm install
npm run dev        # engine (tsc --watch) + server on :4200 + Vite on :5174

Open http://127.0.0.1:5174/games/. With no GATEWAY_SECRET the server treats every request as the developer identity, so the app runs on its own, and the invite dialog offers a made-up family (Mum, Dad, Kid). To play an online match against yourself, set DEV_USER=dad:Dad:member on a second server (another port) or simply accept the invitation through the API. To run it behind a real home app instead, start the home app with GAMES_URL pointing at http://127.0.0.1:4200 and a shared secret, and open /games/ on the home app's address.

  • npm run typecheck — builds the engine, then typechecks the server and the web app
  • npm run lint
  • npm test — engine rules and AI, server identity, web pages
  • npm run build — everything the image ships

Layout

packages/engine/   pure TypeScript game rules shared by server and web
  src/game.ts        the GameDefinition every game implements
  src/registry.ts    the list of games
  src/dots/          rules, computer opponent
apps/server/       Fastify: identity from the gateway, /games/api, static web
apps/web/          React + Vite with base /games/: lobby + one page per game

Adding a game: a folder in packages/engine/src/<game>/ implementing GameDefinition, a line in the registry, a page under apps/web/src/games/<game>/ and an entry in the lobby catalog.

Licence

AGPL-3.0-only, like isputnik.home.

Requirements

Needs the isputnik (isputnik.home) container, version 4.38 or newer, installed on the same server. The games are reached only through it.

Categories

Download Statistics

83
Total Downloads

Related apps

Explore more like this

Explore all

Details

Repository
ghcr.io/isputnikdotnet/isputnik.games:latest
Last Updated2026-11-09
First Seen2026-11-10

Runtime arguments

Network
bridge
Shell
sh
Privileged
false
Extra Params
--stop-timeout=30

Template configuration

Games PortPorttcp

The port the isputnik container reaches the games on: enter http://[your Unraid IP]:[this port] as the Games address in isputnik.home (Control panel, Settings, Apps). Not for browsers: the games open inside isputnik.home. On br0 with a fixed IP, or on a user-defined network shared with the isputnik container, this mapping is not used and the address is the container's own IP or name with port 4200.

Target
4200
Default
4200
Value
4200
Config &amp; DataPathrw

Stores the online matches, scores and the games' own log of events (a small SQLite database). Keep it apart from the isputnik container's appdata. isputnik.home's backups include a copy of it.

Target
/config
Default
/mnt/user/appdata/isputnik-games
Value
/mnt/user/appdata/isputnik-games
Gateway SecretVariable

The secret isputnik.home signs its requests with, so this server knows who is signed in. Make it first, in isputnik.home on Control panel, Settings, Apps, Games (Generate secret; it is shown once), and paste it here. Required: the server refuses to start without one, or with one shorter than 32 characters. Nothing else is set on this container; everything about the games is managed inside isputnik.home.

Target
GATEWAY_SECRET
PUIDVariable

User ID the server runs as. It runs unprivileged (not root); on first start it takes ownership of the Config &amp; Data path as this user. 99 (nobody) matches the default owner of an Unraid appdata share - leave it unless your share is owned by a different user.

Default
99
Value
99
PGIDVariable

Group ID the server runs as. 100 (users) matches the default group of an Unraid appdata share - leave it unless your share uses a different group.

Default
100
Value
100
Log LevelVariable

trace, debug, info, warn, error, fatal or silent. At info every request is logged, including each poll for the other side's move; warn keeps only problems. isputnik.home shows this log and the games' own event record under Control panel, Overview, Logs.

Target
LOG_LEVEL
Default
info
Value
info