Skip to main content

max / makenotwork

Install mt on testnot-1 as a Sando companion testnot-1 now runs the read-only demo multithreaded, so the companion block removed in 2fccc2d0 comes back. Provisioned on the box: postgres role and database (peer auth over the socket, matching prod), system user, /opt/multithreaded, .env, the unit, and a --seed run; plus the companion wrapper and sudoers grant. It serves on 127.0.0.1:3400 behind a forum.testnot.work Caddy vhost, pending the DNS record, and over tailscale serve meanwhile. Read-only is a property of the config rather than a flag: no OAuth client is registered there, every write path needs a session, and a session needs a completed login. Unauthenticated POSTs come back 403. The install path was exercised end to end as `deploy`, through the wrapper's own guards, before this block was uncommented — that step fails after the symlink swap, which is the expensive half, so proving it first is the point. mnw-companion.sudoers now names both deploy users, `makenotwork` for prod-1 and `deploy` for testnot-1, so it installs verbatim on any node. The old "edit the name to match ssh_target" step failed in the worst way: the grant looks present, visudo -c passes, and the denial only surfaces post-swap. sudoers accepts a user absent from the box, so the other node's line is inert. Docs pick up the testnot instance, drop the stale "no mt on testnot-1" text, and record the pg_ident trap: testnot has `local all all peer map=mnw` where prod has plain peer, and a map does not imply the identity pairing, so postgres:///multithreaded is refused with 28000 until the role is listed.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-08-06 22:40 UTC
Signed with PGP, not checked
Commit: 031e85ef7588bbba59ea667254b48ff1492846c6
Parent: 1633bfb
4 files changed, +89 insertions, -26 deletions
M sando/sando.toml +23 -10
@@ -145,17 +145,30 @@
145 145 # binary can satisfy between restarts. The node binds HOST=127.0.0.1 PORT=8080
146 146 # (/etc/mnw/makenotwork.env); verified serving 200 on 2026-07-21.
147 147 health_url = "http://127.0.0.1:8080/health"
148 - # NO multithreaded companion here, deliberately. Checked on the box 2026-08-03:
149 - # testnot-1 has no mt at all — no multithreaded.service, no /opt/multithreaded,
150 - # no database, and the deploy user's sudo grant covers only the three
151 - # makenotwork.service verbs. A companion block would therefore fail the install
152 - # step of every promote, and it fails AFTER the symlink swap, which is the
153 - # expensive half of the failure.
148 + # Companion: multithreaded. Re-enabled 2026-08-06, after the read-only demo was
149 + # provisioned on this box (GoingsOn multithreaded 34dc3ff6). It was removed in
150 + # 2fccc2d0 because testnot-1 had no mt at all, and a companion block for a node
151 + # that cannot install it fails the promote AFTER the symlink swap — the expensive
152 + # half of the failure. That is no longer the case; what is on the box now:
153 + # - postgres role + database `multithreaded`, peer auth over the unix socket
154 + # (DATABASE_URL=postgres:///multithreaded, matching prod)
155 + # - system user `multithreaded`, /opt/multithreaded, .env, and the unit from
156 + # multithreaded/deploy/multithreaded.service, enabled and running on
157 + # 127.0.0.1:3400, seeded via `--seed`
158 + # - /usr/local/lib/mnw/install-companion.sh + /etc/sudoers.d/mnw-companion
154 159 #
155 - # Standing an mt instance up here is real work with real secrets (role, database,
156 - # .env, unit, routing), not a config line, and it is not a prerequisite for
157 - # shipping mt to prod: mt is still built and gated on the host tier by the same
158 - # sha, and testnot still burns in the server. Tracked separately.
160 + # The install path was exercised end to end before this line was uncommented, as
161 + # `deploy`, through the wrapper's own guards — a staged binary under
162 + # */releases/*/companions/* installed to /opt/multithreaded and restarted the
163 + # unit, exit 0. It is not inferred from the grant being present.
164 + #
165 + # mt is on testnot FIRST, unlike mnw-cli, because this is the tier where the 48h
166 + # burn-in runs: a forum that fails to boot on the new binary should fail here,
167 + # not on prod. See multithreaded/deploy/README.md.
168 + [[tier.node.companion]]
169 + name = "multithreaded"
170 + install_path = "/opt/multithreaded/multithreaded"
171 + service_name = "multithreaded.service"
159 172
160 173 # ---- B: prod-1 ----
161 174 [[tier]]
@@ -4,12 +4,20 @@
4 4
5 5 | Instance | Host | Arch | Mechanism |
6 6 |----------|------|------|-----------|
7 + | staging demo | testnot-1 | x86_64 | Sando, as a companion of the MNW server |
7 8 | production | alpha-west-1 | x86_64 | Sando, as a companion of the MNW server |
8 9 | astra | astra | aarch64 | `deploy/deploy.sh` |
9 10
10 - There is no mt on testnot-1, so nothing installs there. The binary is still built
11 - and gated from the same sha as the server, and testnot still burns the server in;
12 - what testnot cannot do is exercise mt itself before prod sees it.
11 + testnot-1 carries a **read-only demo**, provisioned 2026-08-06. It is seeded from
12 + mt's own `--seed`, holds no prod data, and is read-only by construction rather
13 + than by a flag: every write path needs a session, a session needs a completed
14 + OAuth login, and no OAuth client is registered there. Unauthenticated POSTs come
15 + back 403.
16 +
17 + That is what makes mt browser-testable at all — the read half of it. Before this,
18 + every audit run skipped its browser axis, so mt template and frontend work shipped
19 + without the verification every other project gets. Write coverage still needs the
20 + astra harness instance below.
13 21
14 22 Sando builds only on its configured `build_host` (fw13, x86_64) and refuses to
15 23 compile anywhere else, so it cannot produce the aarch64 binary astra needs. That
@@ -50,11 +58,24 @@
50 58
51 59 ### One-time node setup
52 60
53 - None on prod-1. It already carries `/usr/local/lib/mnw/install-companion.sh` and
54 - the `/etc/sudoers.d/mnw-companion` grant, from mnw-cli, and the grant is on the
55 - script rather than on a particular companion.
61 + None outstanding. prod-1 has carried `/usr/local/lib/mnw/install-companion.sh`
62 + and the `/etc/sudoers.d/mnw-companion` grant since mnw-cli, and the grant is on
63 + the script rather than on a particular companion. testnot-1 got both on
64 + 2026-08-06, along with the postgres role and database, the system user,
65 + `/opt/multithreaded/.env`, and the unit.
56 66
57 - Any future node hosting mt needs both, as root, from `sando/deploy/`:
67 + One testnot-only wrinkle worth recording, because it cost a debugging round and
68 + will bite the next node set up the same way. testnot's `pg_hba.conf` has
69 + `local all all peer map=mnw`, where prod has a plain `local all all peer`. A map
70 + does **not** imply the identity pairing, so an OS user connecting as its own
71 + same-named role is refused (`28000 Peer authentication failed`) until it is
72 + listed in `pg_ident.conf`. `postgres:///multithreaded` therefore needed:
73 +
74 + ```
75 + mnw multithreaded multithreaded
76 + ```
77 +
78 + Any future node hosting mt needs both files, as root, from `sando/deploy/`:
58 79
59 80 ```
60 81 sudo install -d /usr/local/lib/mnw
@@ -63,9 +84,18 @@
63 84 sudo visudo -cf /etc/sudoers.d/mnw-companion
64 85 ```
65 86
66 - The sudoers file names `makenotwork` as the deploy user, matching prod-1's
67 - `ssh_target`. A node Sando reaches as a different user needs that name changed to
68 - match, or the install is denied.
87 + The sudoers file names every deploy user Sando SSHes as — `makenotwork` for
88 + prod-1, `deploy` for testnot-1 — so it installs verbatim and needs no hand-edit.
89 + A node Sando reaches as some other user needs that user added to the file, or the
90 + install is denied, and denied late: companions install after the symlink swap.
91 + Check the grant by hand before relying on it:
92 +
93 + ```
94 + ssh <deploy-user>@<node> sudo /usr/local/lib/mnw/install-companion.sh
95 + ```
96 +
97 + Exit 2 with the usage line means the grant works. A password prompt or a "not
98 + allowed" means it does not.
69 99
70 100 mt also needs what it has always needed on the box, none of which Sando touches:
71 101 the `multithreaded` postgres role and database, `/opt/multithreaded/.env`,
@@ -170,6 +170,12 @@
170 170 auditable script (it validates: src inside a release bundle, dst under `/opt`,
171 171 service a bare `*.service`) rather than a broad `install`/`systemctl` grant.
172 172
173 + The grant names every deploy user Sando SSHes as — `makenotwork` for prod-1,
174 + `deploy` for testnot-1 — so the file installs verbatim on any node and needs no
175 + hand-edit at install time. sudoers accepts a user that is not present on the box,
176 + so the other node's line is inert rather than an error. A node added later needs
177 + its `ssh_target` user added to `mnw-companion.sudoers`.
178 +
173 179 One-time per node that hosts a companion (currently prod-1), as root:
174 180
175 181 ```sh
@@ -1,13 +1,27 @@
1 1 # Sando companion-deploy grant. Install to /etc/sudoers.d/ on each node that
2 - # hosts a companion service (currently prod-1 / alpha-west-1):
2 + # hosts a companion service:
3 3 #
4 4 # sudo install -m 0440 mnw-companion.sudoers /etc/sudoers.d/mnw-companion
5 5 # sudo visudo -cf /etc/sudoers.d/mnw-companion # validate before trusting it
6 6 #
7 - # The deploy user (makenotwork on prod — the same user Sando's executor SSHes as)
8 - # may run ONLY the companion installer, with any args. The args are bounded by
9 - # the script itself (src must be inside a release bundle, dst under /opt, service
10 - # a bare *.service unit), so the wildcard is a script-guarded grant, not a broad
11 - # install/systemctl grant. This is the companion analogue of the existing
7 + # The deploy user — the user Sando's executor SSHes as, per that node's
8 + # `ssh_target` in sando.toml — may run ONLY the companion installer, with any
9 + # args. The args are bounded by the script itself (src must be inside a release
10 + # bundle, dst under /opt, service a bare *.service unit), so the wildcard is a
11 + # script-guarded grant, not a broad install/systemctl grant. This is the
12 + # companion analogue of the existing
12 13 # `makenotwork ... /bin/systemctl reload-or-restart makenotwork.service` line.
14 + #
15 + # Sando does not SSH as the same user everywhere: prod-1 is `makenotwork@alpha-west-1`
16 + # (a pre-existing service user, kept rather than renamed) and testnot-1 is
17 + # `deploy@testnot`. Both are named here rather than the file being edited per
18 + # node, because a hand-edit at install time is the failure mode this replaces:
19 + # the grant looks present, `visudo -c` passes, and the install is denied only on
20 + # the far side of the symlink swap. sudoers accepts a user that does not exist on
21 + # the box, so the line for the other node is inert, not an error — the file
22 + # installs verbatim everywhere.
23 + #
24 + # A node added later needs its deploy user added here. Keep this list and the
25 + # `ssh_target` values in sando.toml in step.
13 26 makenotwork ALL=(root) NOPASSWD: /usr/local/lib/mnw/install-companion.sh *
27 + deploy ALL=(root) NOPASSWD: /usr/local/lib/mnw/install-companion.sh *