From f7316060ae61542255b65c8cc675b3b8fff87cf9 Mon Sep 17 00:00:00 2001 From: SkateSpots Date: Sun, 1 Nov 2026 12:14:17 +0700 Subject: [PATCH] feat: one-command crew coordinator installer --- AGENTS.md | 14 +++- deploy/cordn/README.md | 26 ++++++++ deploy/cordn/install.sh | 77 ++++++++++++++++++++++ src/components/CoordinatorSettingsCard.tsx | 6 +- src/lib/coordinator.ts | 4 ++ 5 files changed, 123 insertions(+), 4 deletions(-) create mode 100755 deploy/cordn/install.sh diff --git a/AGENTS.md b/AGENTS.md index 2e661b1..7f9557a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1418,7 +1418,9 @@ session with **no other memory of this project**. So: it in when known. **Profile discovery (built 2026-09-29):** the carrier is the existing kind-0 **`cordn`** field (app convention, documented in NIP.md — not a new kind). - **Crew-owned coordinator kit (2026-10-31):** `deploy/cordn/` is the + **Crew-owned coordinator kit (2026-10-31, install helper 2026-11-01):** + `deploy/cordn/install.sh` is the one-command installer (generates `.env`, + starts SQLite, prints nprofile/add link). `deploy/cordn/` remains the production hand-off for crews: Docker Compose, SQLite volume, `.env` template, backup/restore scripts and a runbook. Cordn connects **outbound** to ContextVM relays; no inbound port, domain or TLS terminator is required for the @@ -3489,6 +3491,16 @@ These components follow a consistent pattern using React's `forwardRef` and use The project includes a **`skills/`** directory containing specialized implementation guides for specific features. Each skill has a comprehensive `SKILL.md` file with complete patterns, code examples, and best practices. **Always reference the appropriate SKILL.md file when implementing related functionality.** +### Deferred: NIP-05 as a wallet address +**Do not set `lud16` to `name@skate-spots.org` until an LNURL-pay service exists.** +NIP-05 is a Nostr identity record; a Lightning address is a separate +`/.well-known/lnurlp/` service. A Minibits-style wallet address needs the +NIP-05 server **and** an LNURL/mint/claim service (plus rate limits, backups, +privacy copy and a clear mint-trust model). Optional future paths: +self-hosted LNURL + Cashu mint, or a deliberate npub.cash/Minibits-style +integration. Until then keep NIP-05 as identity and use NWC/built-in Cashu; +never overwrite a user's custom `lud16`. + ### Wallet Skills - **`skills/bitcoin-wallet/SKILL.md`**: Use when implementing Bitcoin wallet features - provides complete architecture for on-chain Bitcoin transactions, UTXO management, address derivation from Nostr keys, and transaction handling with proper security patterns. Read when building Bitcoin wallet functionality, adding on-chain transaction support, implementing UTXO management, or integrating Bitcoin with Nostr-based applications. diff --git a/deploy/cordn/README.md b/deploy/cordn/README.md index 11dab53..81eadb9 100644 --- a/deploy/cordn/README.md +++ b/deploy/cordn/README.md @@ -18,6 +18,21 @@ coordinator in the APK. ## 1. Install +### Easiest: one command + +```bash +curl -fsSL https://git.skate-spots.org/skatespots/SkateSpots/raw/branch/main/deploy/cordn/install.sh | bash +``` + +It checks Docker, generates the coordinator key, writes a private `.env`, starts +SQLite persistence, waits for the coordinator to announce, and prints the +`nprofile`/add link. + +No inbound port, domain or TLS setup is required. The coordinator connects +outbound to the ContextVM relays in `CORDN_RELAY_URLS`. + +### Manual: from this directory + ```bash cp .env.example .env chmod 600 .env @@ -40,6 +55,17 @@ 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. +### Can I run it on a phone? + +Not with this Docker kit. A phone can **administer** a coordinator, and Cordn's +own phone app is the hand-off path, but an always-on coordinator needs a machine +that stays awake and reachable. Android may suspend a foreground coordinator; +do not promise crew members that a phone is a reliable coordinator host. + +For a crew that wants ownership without a VPS, an old Raspberry Pi or a +small always-on home server is the simplest reliable option. The coordinator +still needs no inbound port. + ## 2. Adopt it in SkateSpots Either: diff --git a/deploy/cordn/install.sh b/deploy/cordn/install.sh new file mode 100755 index 0000000..4541e0b --- /dev/null +++ b/deploy/cordn/install.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +# One-command crew coordinator installer. +# +# curl -fsSL https://git.skate-spots.org/skatespots/SkateSpots/raw/branch/main/deploy/cordn/install.sh | bash +# +# Creates a persistent Cordn coordinator with SQLite storage, starts it, and +# prints the nprofile/add link when the server announces itself. The coordinator +# connects OUT to ContextVM relays; it needs no inbound port or TLS domain. +set -euo pipefail + +cd "$(dirname "$0")" 2>/dev/null || true +umask 077 + +need() { command -v "$1" >/dev/null || { echo "missing: $1" >&2; exit 1; }; } +need docker +need openssl +docker compose version >/dev/null 2>&1 || { echo "Docker Compose v2 is required (docker compose)." >&2; exit 1; } + +if [ ! -f docker-compose.yml ]; then + cat > docker-compose.yml <<'YAML' +name: cordn +services: + cordn: + image: ghcr.io/cordn-msg/cordn:latest + container_name: cordn + restart: unless-stopped + env_file: + - .env + environment: + CORDN_STORAGE_BACKEND: sqlite + CORDN_SQLITE_PATH: /data/cordn.sqlite + volumes: + - cordn-data:/data +volumes: + cordn-data: +YAML +fi + +if [ ! -f .env ]; then + NAME="${CORDN_SERVER_NAME:-skatespots-crew}" + RELAYS="${CORDN_RELAY_URLS:-wss://relay.contextvm.org,wss://relay2.contextvm.org}" + KEY="$(openssl rand -hex 32)" + cat > .env <&2 +echo "Inspect: docker compose logs --no-color" >&2 +exit 1 diff --git a/src/components/CoordinatorSettingsCard.tsx b/src/components/CoordinatorSettingsCard.tsx index 6b752d5..0613dfa 100644 --- a/src/components/CoordinatorSettingsCard.tsx +++ b/src/components/CoordinatorSettingsCard.tsx @@ -20,7 +20,7 @@ import { useTranslation } from '@/contexts/language'; import { toast } from '@/hooks/useToast'; import { CORDN_APP_URL, - CORDN_DOCKER_COMMAND, + CORDN_INSTALL_COMMAND, CORDN_DEPLOY_KIT_URL, CORDN_RELAY_URL, coordinatorAddUrl, @@ -315,11 +315,11 @@ export function CoordinatorSettingsCard() {

- {CORDN_DOCKER_COMMAND} + {CORDN_INSTALL_COMMAND}