Move the gateway to junior.gib: CI deploy, compose copy, renewal script, docs
Gateway / check (push) Successful in 7s
Gateway / image (push) Successful in 19s

This commit is contained in:
gib committed 2026-11-01 13:07:18 -05:00
1 parent 27469dbc77
commit f46c803ad4
7 files changed
+62 -47

No files matched your search

+17 -15
View File
@@ -10,7 +10,7 @@ builds on it.
## Shape
```
watchOS app --HTTPS + device token--> gateway (Bun, server-gib) --WebSocket + bearer--> T3 server x N
watchOS app --HTTPS + device token--> gateway (Bun, junior.gib) --WebSocket + bearer--> T3 server x N
|
+--HTTP/2--> APNs --> watch notifications
```
@@ -51,8 +51,8 @@ recommends. It needs no Effect and no vendored contracts.
```sh
# on the T3 host
t3 auth pairing create --scope orchestration:read --scope orchestration:operate --label "WristCode gateway"
# on server-gib
docker exec -it wristcode-gateway wristcode host add https://t3mac.gbrown.org <pairing credential>
# on junior.gib
podman exec -it wristcode-gateway wristcode host add https://t3mac.gbrown.org <pairing credential>
```
The gateway exchanges the credential at `POST /oauth/token` for a 30 day bearer session and stores
@@ -124,15 +124,16 @@ to end check is a manual run against server-gib's own T3 before deploying.
typecheck and tests on the `build` runner. On `main`, it also builds the image and pushes
`git.gbrown.org/gib/wristcode-gateway:<sha>` and `:latest`. It needs the repo secrets
`REGISTRY_USER` and `REGISTRY_PASSWORD`.
- On server-gib the stack lives in `~/Server/Wristcode/compose.yml`, modeled on `~/Server/Gbrown`.
It joins `nginx-bridge`, publishes no host ports, bind mounts `./data`, and carries the watchtower
label. The APNs key and other config come from a mode 600 `.env`.
- Nginx Proxy Manager gets a proxy host for `wristcode.gbrown.org` that points at
`wristcode-gateway:8080`, using the `*.gbrown.org` certificate. DNS and the Cloudflare tunnel
already cover the subdomain.
- Deploys: after pushing the image, CI calls `~/Server/ci-deploy.sh wristcode` on server-gib over
SSH with a deploy key, which pulls and restarts the stack. Watchtower's nightly pull is the
fallback.
- The stack runs under rootless podman on junior.gib, the VPS, beside Gitea and most other
services. Its compose file and systemd user unit live in gib/Panama under
`server/vps/Wristcode/` and are symlinked into `~/Server/Wristcode/` and
`~/.config/systemd/user/`. It joins `nginx-bridge`, publishes no host ports, and bind mounts
`./data`. The APNs key and other config come from a mode 600 `.env`.
- junior's Nginx Proxy Manager serves `wristcode.gbrown.org` and forwards to
`wristcode-gateway:8080`. The Cloudflare record is proxied, as every VPS hostname must be.
- Deploys: after pushing the image, CI SSHes to junior's WireGuard address with a deploy key
pinned to `~/Server/ci-deploy.sh`, which pulls and restarts the stack. The nightly
`update-containers` timer is the fallback.
- Local development: `bun --watch src/main.ts` against real T3 hosts, with no local image builds.
## Watch app
@@ -181,7 +182,7 @@ Each phase ends with something usable.
pairing, and `GET /v1/feed`. Checked against server-gib's T3 from the Fedora desktop.
2. **Gateway write path and pairing.** Send, respond, stop, launch, the projects route, watch
pairing codes, and device tokens. Checked with curl against a real thread.
3. **Ship the gateway.** Containerfile, CI, registry, the compose stack on server-gib, and the NPM
3. **Ship the gateway.** Containerfile, CI, registry, the compose stack on junior.gib, and the NPM
proxy host. All four hosts are added.
4. **Watch app MVP.** Pair, feed, thread, reply, approvals, and new thread, running in the simulator
against the deployed gateway.
@@ -198,8 +199,9 @@ they push to `docs/`.
- Threads started from the watch inherit the host's default runtime mode (`full-access` on these
hosts).
- CI deploys right away through a `wristcode` entry in `~/Server/ci-deploy.sh`, with Watchtower's
nightly pull as the fallback.
- The gateway runs on junior.gib, the VPS, which is more reliable than the home server. CI deploys
right away through junior's `~/Server/ci-deploy.sh`, with the nightly update timer as the
fallback.
- The App Store record uses `org.gbrown.wristcode`, an empty iOS wrapper the App Store requires
around a watch-only app. The watch app itself is `org.gbrown.wristcode.watchkitapp`, which is also
its APNs topic.