Gnosis Multiplayer and Server Wiki
This page has been reviewed against the current terminal/server build and the latest portal documentation surfaces. For exact live catalogs and tuning values, use the source-driven...
Gnosis Multiplayer and Server Wiki
Documentation Freshness (2026-04-19)
- This page has been reviewed against the current terminal/server build and the latest portal documentation surfaces.
- For exact live catalogs and tuning values, use the source-driven portal compendiums:
/bestiary/spell-omnibus/technique-omnibus/item-omnibus/recipe-omnibus
- In-game references are available through the
Wwiki menu (including generated spell/component compendiums). - World/floor map reference is in-game via
P; the website map page is intentionally hidden. - Multiplayer host/deployment details live in
docs/multiplayer_server_wiki.mdanddocs/server_portal_setup.md.
Current Build Delta (2026-04-19)
- Deep floors now have a depth-scaled chance to spawn Lizard Kingdom Gates (
FeatureLizardKingdomGate). - Using a Lizard Kingdom Gate enters Lizard Kingdom side sites (
SiteLizardKingdom) with lizard society-biased populations. - Lizard Kingdom floors use dedicated cave themes (
Outer Warrens->Royal Sinkhalls) and integrate with map/examine/senses/clairvoyance text. - This update is live in terminal mode and server mode; hosted clients inherit the behavior from the game build.
This page documents the implemented multiplayer host model (gnosisd) and observer turn synchronization.
1. Scope
Primary code:
cmd/gnosisd/main.gointernal/server/server.gointernal/game/turnsync.godocs/server_portal_setup.md
2. Runtime Model
gnosisd hosts the game and starts one game process per player session.
Supported clients:
- SSH terminal sessions
- browser terminal sessions (websocket + xterm.js)
The actual game remains the same Go terminal binary; server mode wraps process/session management around it.
3. Network Endpoints
Default listeners:
- SSH
:2222 - HTTP
:8080
Docker compose publishing used by the portal stack:
- Portal HTTP
127.0.0.1:9004-> container8000 - Browser websocket host
127.0.0.1:9005->gnosisdcontainer8080 - SSH host
127.0.0.1:2222->gnosisdcontainer2222
Production public host:
https://gnosis.cordine.site- browser websocket should resolve to
wss://gnosis.cordine.site/ws - portal production env starts from
webapp/.env.production.example
Main HTTP routes:
/healthz/api/provision/api/ssh-public-key/api/token/ws/play
4. Accounts and Authentication
Server stores account hashes in server data dir.
Auth modes:
- SSH password auth
- SSH public-key auth synced from the Laravel portal
- optional SSH key-identity mode (
GNOSIS_SERVER_SSH_KEY_IDENTITY=1) where profile identity is derived from the SSH key instead of the SSH username - optional auto-registration from SSH login (can be disabled)
- HTTP provisioning endpoint for portal registration
- signed websocket token flow for browser sessions
The portal stores one OpenSSH public key per SSH username and pushes updates to gnosisd through /api/ssh-public-key.
5. Per-User Save Isolation
Each account gets separate campaign persistence roots:
data/server/users/<username>/campaign/(chunked runtime store).../backups/(manual backup copies)
Session env wiring injects per-user save paths plus profile/session ids.
In dedicated locked-world mode (GNOSIS_SERVER_WORLD_CONFIG set), sessions are forced onto one configured world id/seed/setup and runtime world creation/selection menus are disabled.
6. Observer Turn Synchronization
Turn sync file path is configured by server and passed to game sessions.
Mechanic:
- each player writes presence: region/floor/plane/position/vision/turn
- if two players can mutually observe each other, they become synchronized
- acting player waits until observed player resolves a turn
- UI status line/log shows waiting state text
This applies the “observer makes state shared” rule in active sight overlap.
7. Time and Independent Simulation
When players are not mutually observing:
- each session proceeds independently
- normal background simulation still runs for loaded worlds
So synchronization is localized to overlapping perception, not global lockstep.
8. Browser Play
Browser path:
- client obtains signed token
- websocket connects
/ws?token=... - PTY bytes are bridged bidirectionally
- resize control messages update terminal geometry
/play provides a local lightweight xterm bootstrap page.
9. Config and Environment
Key server settings:
GNOSIS_SERVER_SSH_ADDRGNOSIS_SERVER_HTTP_ADDRGNOSIS_SERVER_DATA_DIRGNOSIS_SERVER_HOST_KEYGNOSIS_SERVER_REPO_DIRGNOSIS_SERVER_GAME_CMDGNOSIS_SERVER_SSH_KEY_IDENTITY(bind SSH session identity to SSH key fingerprint account)GNOSIS_PROVISION_SECRETGNOSIS_WS_SECRETGNOSIS_SERVER_TURN_SYNCGNOSIS_SERVER_TURN_SYNC_TTLGNOSIS_SERVER_DISABLE_AUTO_USERSGNOSIS_SERVER_ALLOW_INSECURE_DEFAULTS(set1only for local throwaway testing; production should keep this unset)GNOSIS_SERVER_WORLD_CONFIG(world JSON used to lock world id/seed/setup for dedicated host mode)
Steam bundle note:
steam/build.shpackagesgnosisdalongside the client binary.host-server.shin the bundle launches the dedicated server with save data under XDG data directories.- The bundled server uses the packaged
gnosisbinary automatically as its session game command.
Standalone Docker host note:
docker compose -f docker-compose.server.yml up -d --buildstarts a dedicatedgnosisdhost from this repo.- It publishes
2222(SSH) and8080(HTTP/WebSocket) by default. - Root compose enables
GNOSIS_SERVER_SSH_KEY_IDENTITY=1so players are keyed by SSH public key identity. - Root compose defaults
GNOSIS_SERVER_WORLD_CONFIG=/var/lib/gnosis-server/world-config.json. - If world config is missing/invalid,
/healthzis not ready and sessions are refused. - A template is available at
docker/world-config.example.jsonand copied into data dir asworld-config.json.example.
Session/game-side turn sync envs:
GNOSIS_TURN_SYNCGNOSIS_TURN_SYNC_TTL_SEC
10. Operational Notes
- PTY is required for SSH sessions.
- Host key is auto-generated if missing.
- Token signing uses HMAC; keep websocket secret private.
- Provision endpoint should be protected with strong secret and network policy.
- Public-key updates use the same secret-protected portal-to-server channel as provisioning.
11. Laravel Integration
Portal/auth integration details are in:
That doc covers registration provisioning and browser play wiring.
The portal compose stack is in webapp/docker-compose.yml and expects the shared postgres_db container from /workspace/container-pgsql/ on dev-net.
Related pages: