| 1 |
# Sando deploy units |
| 2 |
|
| 3 |
systemd units and scripts that run on the Sando host (fw13) and on deploy |
| 4 |
targets. Host-specific secrets, certs, and tailnet IPs are **not** here — they |
| 5 |
live in the Syncthing private layer (`_private/infra/`, `_private/deploy`). |
| 6 |
|
| 7 |
## Files |
| 8 |
|
| 9 |
|
| 10 |
|
| 11 |
| `sandod.service` | Sando host | The Sando daemon (`sandod`). | |
| 12 |
| `bootstrap-sandod-host.sh` | Sando host | One-time host setup for the daemon. | |
| 13 |
| `bootstrap-node.sh` | a deploy target | One-time node setup (release dirs, deploy user, service). | |
| 14 |
| `sando-daemon.toml.example` | Sando host | Template for the daemon config (`sando.toml`). | |
| 15 |
| `post-receive` | git remote | Push-to-deploy hook. | |
| 16 |
| `sandod-backup-fetch.{service,timer}` | Sando host | Daily pull of the prod backup to `/srv/sando/backups/latest.sql.gz` (04:00 UTC). | |
| 17 |
| `mnw-testnot-refresh.{sh,service,timer}` | Sando host | Daily refresh of the testnot.work staging mirror (05:00 UTC). | |
| 18 |
|
| 19 |
## testnot.work staging mirror |
| 20 |
|
| 21 |
testnot is a read-only mirror of production, gated app-side to Fan+/creator |
| 22 |
accounts (`ACCESS_GATE=fan_plus_or_creator`). It exists so creators and Fan+ |
| 23 |
members can preview upcoming features, and to back the pre-cutover migration |
| 24 |
dry-run. |
| 25 |
|
| 26 |
**Daily refresh** (`mnw-testnot-refresh.timer` → `.service` → `.sh`): reloads |
| 27 |
testnot's database from the backup `sandod-backup-fetch` already pulls, so the |
| 28 |
mirror tracks live. The script stops the app, resets the schema (recreating |
| 29 |
`public` owned by the app role — PG15+ otherwise blocks the app role's boot |
| 30 |
migrations), restores the dump as the postgres superuser over Tailscale SSH, |
| 31 |
and restarts the app, which applies any newer migrations on boot. Writes |
| 32 |
between refreshes are non-durable by design. |
| 33 |
|
| 34 |
Install on the Sando host: |
| 35 |
|
| 36 |
```sh |
| 37 |
sudo install -m 0755 mnw-testnot-refresh.sh /usr/local/bin/mnw-testnot-refresh.sh |
| 38 |
sudo install -m 0644 mnw-testnot-refresh.service /etc/systemd/system/ |
| 39 |
sudo install -m 0644 mnw-testnot-refresh.timer /etc/systemd/system/ |
| 40 |
sudo systemctl daemon-reload |
| 41 |
sudo systemctl enable --now mnw-testnot-refresh.timer |
| 42 |
``` |
| 43 |
|
| 44 |
Run a refresh manually: `sudo /usr/local/bin/mnw-testnot-refresh.sh` |
| 45 |
|
| 46 |
**Redeploy the binary** (no Sando integration yet — manual): build the release |
| 47 |
on the Sando host, then over Tailscale SSH as root on the target, copy the |
| 48 |
current release dir to a new one, stream the new `makenotwork` binary in, stream |
| 49 |
a tar of `static/` + `docs/` (`docs/` = `server/site-docs/{public,examples}` + |
| 50 |
`server/docs/business/assumptions.toml`, mirroring `server/deploy/deploy.sh`), |
| 51 |
flip the `current` symlink, and `systemctl restart makenotwork.service` (which |
| 52 |
boot-migrates). Old release dirs are kept for rollback. |
| 53 |
|
| 54 |
Cert, the makenotwork Postgres password, the Caddyfile, and the operator |
| 55 |
runbook for the root-level node setup are in `_private/infra/testnot/`. |
| 56 |
|