nikola and frootmig are flagging power events and drive warnings on the iLO interface and need drive replacement. Move both moments components onto anjie.kosherinata.internal until those hosts are back in service. Update the nginx upstream and the readme topology table to match; the postgres pg_ident.conf on magrathea now needs to map anjie's cert CN to both moments_ro and moments_rw (two lines for the same cert_cn). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
76 lines
3.9 KiB
Markdown
76 lines
3.9 KiB
Markdown
# moments
|
|
|
|
Personal activity timeline for [rob.tn](https://rob.tn). Polls public sources (GitHub, Gitea, hg-edge.mozilla.org, bugzilla.mozilla.org), stores raw payloads in Postgres, and serves a reshaped timeline to a static React frontend.
|
|
|
|
Successor to the now-defunct [grenade-events-react](https://github.com/grenade/grenade-events-react), which depended on MongoDB Stitch (retired by MongoDB in September 2022).
|
|
|
|
## Layout
|
|
|
|
```
|
|
crates/
|
|
moments-entities/ # types and DTOs
|
|
moments-core/ # ingestion + reshape logic
|
|
moments-data/ # postgres adapter + migrations
|
|
moments-api/ # axum read-only HTTP API (binary)
|
|
moments-worker/ # ingestion daemon (binary)
|
|
ui/ # vite + react + swc + ts frontend
|
|
asset/ # systemd, nginx, firewalld, manifest.yml
|
|
script/deploy.sh
|
|
```
|
|
|
|
Architectural conventions follow [grenade/architecture/generic.md](https://git.lair.cafe/grenade/architecture/src/branch/main/generic.md).
|
|
|
|
## Local development
|
|
|
|
```sh
|
|
cargo build --workspace
|
|
cargo run -p moments-api # serves on 127.0.0.1:8080
|
|
cargo run -p moments-worker # one-shot ingest tick (until --interval is wired up)
|
|
```
|
|
|
|
The API expects a Postgres reachable at `DATABASE_URL`. For magrathea, that's an mTLS connection using the host cert. For local dev against a throwaway database:
|
|
|
|
```sh
|
|
DATABASE_URL=postgres://localhost/moments cargo run -p moments-api
|
|
```
|
|
|
|
Migrations live in `crates/moments-data/migrations/` and run automatically on worker startup. The API connects as `moments_ro` and never runs migrations — the worker (as `moments_rw`) is the schema owner.
|
|
|
|
## Deployment
|
|
|
|
```sh
|
|
./script/deploy.sh prod all # api + worker + web
|
|
./script/deploy.sh prod api worker # subset
|
|
./script/deploy.sh prod default # api + web only (worker untouched)
|
|
./script/deploy.sh prod all --dry-run
|
|
```
|
|
|
|
Topology:
|
|
|
|
| Component | Host | Notes |
|
|
| --------- | --------------------------------- | ------------------------------------------------------------------ |
|
|
| api | `anjie.kosherinata.internal` | binds `0.0.0.0:42424`; firewalld service `moments-api` |
|
|
| worker | `anjie.kosherinata.internal` | no listening port; pollers only |
|
|
| web | `oolon.kosherinata.internal` | per-site nginx ingress for rob.tn; `/api/*` → anjie across the WG |
|
|
| db | `magrathea.kosherinata.internal` | postgres mTLS, passwordless |
|
|
|
|
api and worker are co-located on `anjie` while `nikola` and `frootmig` are out for drive replacement.
|
|
|
|
Postgres roles `moments_rw` and `moments_ro` must exist on the primary, with `pg_ident.conf` mapping `anjie.kosherinata.internal` to **both** roles (one cert_cn line per mapping). See `asset/sql/bootstrap-moments.sql` and `asset/postgres/ident.conf.tmpl`.
|
|
|
|
Inter-host traffic over the WG mesh: oolon's nginx connects to `http://anjie.kosherinata.internal:42424` in plaintext. The mesh provides the encryption layer; per-hop TLS for an internal HTTP read-only API on already-public data is deferred. If that changes, swap the api binary to rustls + the host cert pair, and update the nginx upstream to `https://`.
|
|
|
|
Secrets resolved by `deploy.sh` via `pass`:
|
|
|
|
- `github.com/grenade/admin-token` — GitHub PAT for events + search APIs (worker only).
|
|
|
|
Optional, set if needed in `worker.env`: `GITEA_TOKEN`, `BUGZILLA_API_KEY`.
|
|
|
|
### DNS cutover
|
|
|
|
`rob.tn` currently resolves to GitHub Pages. After the first successful prod deploy:
|
|
|
|
1. Update Cloudflare DNS for `rob.tn` to the WAN IP that fronts `oolon` (unproxied — see architecture doc §11).
|
|
2. Confirm `curl -fsS https://rob.tn/api/v1/healthz` returns `ok`.
|
|
3. Add an archival notice to the top of [grenade-events-react/readme.md](https://github.com/grenade/grenade-events-react) pointing at this repo, and archive the GitHub repo.
|