A "seats" button beside "transfer seat" opens the host's panel. In a game under way, "give to the clockwork" lets an automaton play a person's seat from the next beat, with their hand, treasures and place untouched; a standIn line on the ledger records it, the chronicle says so, the stand-in never talks under the person's name, and the person's token opens nothing after. "Make a phrase" mints the four-word phrase for any person's seat; claiming it re-seats on a new token, and a seat the clockwork stood in for goes back to its person mid-turn. A rematch holds a stood-in seat for its person. The gallery now has its own claim box, for a player who opens the invite link in a fresh browser. The client's watchdog pinged and then closed a socket quiet for 45 seconds. A background tab's timers run about once a minute, so the last pong was always a minute old when it looked, and idle tabs reconnected every 58 seconds. It now closes only when its own ping went unanswered. The server pings every socket at the protocol level every 30 seconds and drops one that left the last ping unanswered, so a crashed browser's socket no longer lingers until TCP gives up. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141G6xqLeNRYEtviLWSB5Up
72 lines
3.6 KiB
Markdown
72 lines
3.6 KiB
Markdown
# Deploying Wiz-War
|
|
|
|
The game runs on a single DigitalOcean droplet: one Node process serves the
|
|
built client and the websocket on port 8787; Caddy in front terminates TLS
|
|
with automatic certificates. Room files persist in /var/lib/wizwar/rooms and
|
|
survive deploys and reboots.
|
|
|
|
## Current production
|
|
|
|
- Host: `hall` (nyc3, tag `kestrels-hall`), IP 159.203.115.252, shared with
|
|
the other games of Kestrel's Hall since 2026-09-29; Wiz-War keeps its own
|
|
service user, port 8787, site file and access log there.
|
|
- URLs: https://wizwar.kestrelsnest.social
|
|
and https://wizwar.159.203.115.252.sslip.io (always works, zero DNS).
|
|
Caddy serves both; NOTE: kestrelsnest.social's authoritative DNS is at
|
|
HOVER (ns1/ns2.hover.com), not DigitalOcean — records must be added there.
|
|
A matching record also sits in the DO zone in case nameservers ever move.
|
|
|
|
## Everyday deploys
|
|
|
|
deploy/deploy.sh 159.203.115.252
|
|
|
|
Builds the client locally, rsyncs the repo (minus node_modules, data/, .git,
|
|
research), installs dependencies on the droplet, and restarts the service.
|
|
Games in progress survive: state lives in room files, and clients reconnect
|
|
automatically.
|
|
|
|
Before any deploy that touches the engine, run the determinism gate:
|
|
|
|
deploy/verify-ledgers.sh 159.203.115.252
|
|
|
|
It fetches every production ledger and strictly replays it against the local
|
|
engine; a single refused command fails the check. A room whose ledger no
|
|
longer replays becomes unreachable after restart, so this is not optional.
|
|
|
|
## New droplet from scratch
|
|
|
|
1. `doctl compute droplet create wizwar --region nyc3 --size s-1vcpu-1gb \
|
|
--image ubuntu-24-04-x64 --ssh-keys <your-key-ids> --tag-name wizwar --wait`
|
|
2. `scp deploy/setup-droplet.sh deploy/Caddyfile.tmpl root@<ip>:/root/ && ssh root@<ip> \
|
|
"bash /root/setup-droplet.sh 'wizwar.<ip>.sslip.io'"` (the host's Caddyfile
|
|
gathers each game's site from /etc/caddy/sites/, so the host can be shared)
|
|
3. `deploy/deploy.sh <ip>`
|
|
|
|
## Operations
|
|
|
|
- Logs: `ssh root@<ip> journalctl -u wizwar -f`
|
|
- Restart: `ssh root@<ip> systemctl restart wizwar`
|
|
- Nightly backups: `wizwar-backup.sh` runs from root's crontab at 07:17 UTC,
|
|
pushing /var/lib/wizwar to the `kestrel-wizwar-backups` Space (nyc3) via
|
|
rclone. It is installed at /usr/local/bin/wizwar-backup.sh on the droplet;
|
|
`setup-droplet.sh` does NOT install it — on a fresh droplet, copy the
|
|
script, configure rclone (the script refuses to run while the config still
|
|
holds its CHANGE_ME placeholder), and add the cron entry by hand.
|
|
- A player whose browser lost their seat (Safari's seven days, an app's own
|
|
browser, cleared data) asks the host, whose "seats" button makes a
|
|
four-word phrase that re-seats them on a new token. The same panel lets the
|
|
host give a seat to the clockwork in a game under way, for a player who
|
|
cannot take their turns; a `standIn` line on the ledger records it, and a
|
|
later reseat gives the seat back. Failing the host, they write to the
|
|
keeper. On the droplet,
|
|
`wizwar-reseat.sh ROOM` lists who sits at the table and when each last
|
|
moved or spoke; `wizwar-reseat.sh ROOM NAME` gives that wizard's seat a new
|
|
token and prints a link carrying it in the fragment. The old token opens
|
|
nothing after. The script answers through the game server's keeper door,
|
|
a listener of its own on 127.0.0.1:9787 that Caddy never reaches, which
|
|
opens only to the key in /etc/wizwar/keeper.key (root and the wizwar user
|
|
alone can read it, so the other services on the host cannot use the door).
|
|
The first deploy makes the key, and every deploy installs the script at
|
|
/usr/local/bin.
|
|
- One-off backup: `scp -r root@<ip>:/var/lib/wizwar/rooms ./rooms-backup`
|