Waving Hands moves to the shared hall host

The kit's shared setup, its own Caddy site file and access log (the
visitors, rollup and pulse read it), the gate taking a SITE override,
and the host's address everywhere. The old droplet forwards to hall
until the A record moves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
This commit is contained in:
Eric Wagoner
2026-09-25 17:04:35 -04:00
co-authored by Claude Opus 5.5
parent e1833e4e3c
commit f0d06db108
12 changed files with 142 additions and 133 deletions
+35 -36
View File
@@ -1,51 +1,50 @@
# Deploying Waving Hands
The single-player game runs entirely in the browser. Duels between people
go through a small Node process that keeps each room as an append-only
ledger of moves in /var/lib/waving-hands/rooms. Production is one
DigitalOcean droplet: Caddy terminates TLS with automatic certificates,
serves the static build from /opt/waving-hands/build, and proxies /api and
/ws to the duel server on port 8788, which runs as the `waving-hands` user
under systemd from /opt/waving-hands/app.
Every game is a room on a small Node process that keeps it as an
append-only ledger of moves in /var/lib/waving-hands/rooms (the unit names it with WH_DATA_DIR). Production is the
shared Kestrel's Hall host: Caddy terminates TLS with automatic
certificates, serves the static build from /opt/waving-hands/build, and proxies
/api and /ws to the game server on port 8788, which runs as the
`waving-hands` user under systemd from /opt/waving-hands/app.
## Sizing
## The shared host
The smallest droplet, `s-1vcpu-512mb-10gb` ($4 a month), carries both Caddy
and the duel server comfortably: the server is one small Node process capped
at 300 MB by its unit file, and a room is a few kilobytes of ledger.
The zero-cost alternative is a second site block in an existing Caddy
server's configuration pointing at a second directory; the deploy script
works unchanged against that host. A droplet of its own keeps this site's
uptime and upgrades independent of anything else.
The games of Kestrel's Hall share one droplet, `hall` (nyc3, s-1vcpu-1gb,
$6 a month, tag `kestrels-hall`, IP 159.203.115.252). Each game keeps its
own Caddy site file in /etc/caddy/sites/<slug>.caddy, its own port,
service user, /opt/<slug> and /var/lib/<slug> trees, access log
(/var/lib/caddy/<slug>-access.log), cron file and ops scripts;
/etc/caddy/Caddyfile only says `import sites/*.caddy`. A game server is one
small Node process capped at 300 MB by its unit file, and a room is a few
kilobytes of ledger, so the host carries several. Each game needs a port
of its own on the host: wizwar 8787, waving-hands 8788, hnefatafl 8789,
dip 8790.
## Current production
- Droplet: `waving-hands` (nyc3, s-1vcpu-512mb-10gb, tag `waving-hands`), IP 159.203.98.71
- URLs: https://hands.kestrelsnest.social (A record at Hover, where
kestrelsnest.social's DNS lives) and https://waving-hands.159.203.98.71.sslip.io
(always works, zero DNS). Caddy serves both from the first line of
/etc/caddy/Caddyfile.
- Everyday deploy: `deploy/deploy.sh 159.203.98.71`
- Host: 159.203.115.252
- URLs: https://hands.kestrelsnest.social (A record at Hover, where kestrelsnest.social's
DNS lives) and https://hands.159.203.115.252.sslip.io (always works, zero DNS).
- Everyday deploy: `SITE=https://hands.159.203.115.252.sslip.io deploy/deploy.sh 159.203.115.252`
(this Mac's resolver caches the old *.kestrelsnest.social wildcard, so the gate reads the sslip name).
- Moved here from its own droplet (159.203.98.71) on 2026-09-25.
- Players' reports: `deploy/pull-reports.sh` mirrors /var/lib/waving-hands/feedback.jsonl
and the screenshots to ~/Desktop/waving-hands-reports with a digest;
`deploy/report-reply.sh 159.203.98.71 <id> <status> "text"` answers one.
`deploy/report-reply.sh 159.203.115.252 <id> <status> "text"` answers one.
## New droplet from scratch
## Adding this game to the host
1. `doctl compute droplet create waving-hands --region nyc3 \
--size s-1vcpu-512mb-10gb --image ubuntu-24-04-x64 \
--ssh-keys <your-key-ids> --tag-name waving-hands --wait`
2. `scp deploy/setup-droplet.sh deploy/Caddyfile.tmpl root@<ip>:/root/ && ssh root@<ip> \
"bash /root/setup-droplet.sh 'hands.kestrelsnest.social, waving-hands.<ip>.sslip.io'"`
(point the A record at the new IP first, or leave the real name out until it is).
3. `scp deploy/setup-server.sh deploy/Caddyfile.tmpl root@<ip>:/root/ && ssh root@<ip> "bash /root/setup-server.sh"`
4. `deploy/deploy.sh <ip>`
1. `scp deploy/setup-droplet.sh deploy/Caddyfile.tmpl root@<ip>:/root/ && ssh root@<ip> \
"bash /root/setup-droplet.sh 'hands.kestrelsnest.social, hands.<ip>.sslip.io'"`
It installs Caddy and Node if the host lacks them, writes this game's
site file, and touches nothing of another game's. Point the A record at
the host first, or leave the real name out until it is; running it again
with the new line is how a name is added later.
2. `deploy/deploy.sh <ip>`
The sslip.io hostname works with no DNS at all. To add a real name, point an
A record at the droplet and add the name to the first line of
/etc/caddy/Caddyfile (space separated), then `systemctl reload caddy`; Caddy
fetches the certificate on first request.
A fresh host, when one is needed: `doctl compute droplet create hall --region nyc3 \
--size s-1vcpu-1gb --image ubuntu-24-04-x64 --ssh-keys <your-key-ids> \
--tag-name kestrels-hall --wait`, then step 1.
## Operations scripts on the droplet