max / makenotwork
- Co-Authored-By
- Claude Opus 5 (1M context) <noreply@anthropic.com>
4 files changed,
+89 insertions,
-26 deletions
| @@ -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 * |