127 lines
4 KiB
Markdown
127 lines
4 KiB
Markdown
# Crew-owned Cordn coordinator
|
||
|
||
This kit runs a **Cordn MLS delivery-service coordinator** that a crew owns. It
|
||
is transport only: the coordinator sees ciphertext and routing metadata (who,
|
||
when, which group), never message plaintext. It can withhold or delay messages;
|
||
it cannot forge members' messages.
|
||
|
||
This is a **server** kit. SkateSpots remains a Cordn *client*; it does not embed a
|
||
coordinator in the APK.
|
||
|
||
## What you need
|
||
|
||
- A small Linux server or always-on home machine with Docker + Compose.
|
||
- Outbound HTTPS/WSS access. **No inbound port is required** — the coordinator
|
||
connects out to its ContextVM relay(s).
|
||
- A domain is **not** required for the coordinator itself.
|
||
- A crew willing to trust the operator with availability and metadata.
|
||
|
||
## 1. Install
|
||
|
||
```bash
|
||
cp .env.example .env
|
||
chmod 600 .env
|
||
openssl rand -hex 32
|
||
```
|
||
|
||
Put the generated value into `CORDN_SERVER_PRIVATE_KEY`. Set
|
||
`CORDN_RELAY_URLS` to the relay(s) you want; the default is ContextVM’s public
|
||
relay. Set a useful `CORDN_SERVER_NAME`.
|
||
|
||
```bash
|
||
docker compose up -d
|
||
docker compose logs -f cordn
|
||
```
|
||
|
||
The server prints its coordinator public identity/add link. It may show an
|
||
`nprofile` or a `cordn.net/chat/coordinators?c=…` link.
|
||
|
||
If your build does not print an add link, derive the public key from the private
|
||
key using the Cordn CLI or `nostr-tools`, then encode an `nprofile` with the same
|
||
relay hints. Keep the private key on the server.
|
||
|
||
## 2. Adopt it in SkateSpots
|
||
|
||
Either:
|
||
|
||
- Settings → **Coordinator** → paste the `nprofile`/add-link → **Add**; or
|
||
- Crew edit → **Coordinator** → paste it and save; or
|
||
- scan the coordinator QR.
|
||
|
||
Use exactly the relay hints from the server. A mismatch produces an honest
|
||
“Not seen” health state even when the server is actually running.
|
||
|
||
The coordinator should show **Online** (or “Stale” if its heartbeat is old).
|
||
“Offline” means presence was not found, not necessarily that the service is
|
||
broken.
|
||
|
||
## 3. What the crew should know
|
||
|
||
- The coordinator can **censor or drop messages**.
|
||
- It cannot **read** MLS plaintext.
|
||
- It can see **who, when and which group**.
|
||
- It can disappear; local messages remain on members' devices, but delivery
|
||
pauses until the coordinator returns or the crew switches.
|
||
- The operator should **not** also become a crew admin automatically.
|
||
- A loss of the database is a loss of delivery history; back it up.
|
||
|
||
## 4. Backup
|
||
|
||
```bash
|
||
./backup.sh
|
||
```
|
||
|
||
Backups land in `./backups/` as a compressed copy of the coordinator volume.
|
||
Store them off the server, encrypted.
|
||
|
||
## 5. Restore
|
||
|
||
Stop the coordinator, restore the archive into the `cordn-data` volume, start it
|
||
again:
|
||
|
||
```bash
|
||
docker compose stop cordn
|
||
./restore.sh backups/cordn-YYYYMMDD-HHMMSS.tgz
|
||
docker compose start cordn
|
||
```
|
||
|
||
## 6. Upgrade
|
||
|
||
```bash
|
||
docker compose pull
|
||
docker compose up -d
|
||
```
|
||
|
||
The image is pinned only by the `latest` tag. If you need reproducible upgrades,
|
||
pin a digest and record it in your crew runbook.
|
||
|
||
## 7. Move to a new coordinator
|
||
|
||
MLS delivery state is tied to the coordinator’s database and identity. Before
|
||
switching:
|
||
|
||
1. back up the current coordinator;
|
||
2. export/retain the crew’s local chat state on members’ devices;
|
||
3. start the new coordinator;
|
||
4. paste its `nprofile` into the crew record;
|
||
5. have members reopen the private chat and re-establish delivery;
|
||
6. update the crew operator/notice.
|
||
|
||
Do not claim the switch is seamless unless the old and new coordinator state
|
||
have actually been migrated.
|
||
|
||
## Security notes
|
||
|
||
- Never commit `.env`; it contains the coordinator signing key.
|
||
- The coordinator key is **not** a crew admin key and must not be reused as one.
|
||
- Run it behind a trusted host/network; outbound relay traffic is metadata.
|
||
- Keep Docker and the image current.
|
||
- Do not expose an OpenCode or coordinator admin port publicly.
|
||
- This is **not** a BFT or multi-coordinator system. One coordinator is a
|
||
delivery service under the crew's social trust.
|
||
|
||
## Files
|
||
|
||
- `docker-compose.yml` — persistent SQLite deployment.
|
||
- `.env.example` — required environment.
|
||
- `backup.sh` / `restore.sh` — volume snapshots.
|