Co-authored-by: Claude (Opus 4.6) <claude@hermes.local> Co-committed-by: Claude (Opus 4.6) <claude@hermes.local>
This commit was merged in pull request #58.
This commit is contained in:
45
OPERATOR.md
Normal file
45
OPERATOR.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# Operator Setup Guide
|
||||
|
||||
## Timmy's Nostr Identity
|
||||
|
||||
Timmy uses a secp256k1 Nostr keypair for his on-chain identity. Without a
|
||||
persisted key, Timmy generates a new ephemeral identity on every restart —
|
||||
losing continuity with anyone who knew his previous `npub`.
|
||||
|
||||
### One-time setup
|
||||
|
||||
1. **Generate a keypair:**
|
||||
|
||||
```bash
|
||||
bash scripts/generate-timmy-nsec.sh
|
||||
```
|
||||
|
||||
This prints the `nsec1...` (private key), `npub1...` (public key), and an
|
||||
`export` line you can copy-paste.
|
||||
|
||||
2. **Set the environment variable** in your deployment environment:
|
||||
|
||||
- **Replit:** Add `TIMMY_NOSTR_NSEC` in the Secrets tab (padlock icon).
|
||||
- **VPS (systemd):** Add to `/opt/timmy-tower/.env`:
|
||||
```
|
||||
TIMMY_NOSTR_NSEC=nsec1...
|
||||
```
|
||||
- **Local dev:** Export in your shell or add to a `.env` file:
|
||||
```bash
|
||||
export TIMMY_NOSTR_NSEC="nsec1..."
|
||||
```
|
||||
|
||||
3. **Restart the API server.** On startup you should see an `INFO` log:
|
||||
|
||||
```
|
||||
timmy-identity INFO timmy identity loaded from env { npub: "npub1..." }
|
||||
```
|
||||
|
||||
If you see a `WARN` instead, the env var is missing or malformed.
|
||||
|
||||
### Security
|
||||
|
||||
- The `nsec` is a private key — treat it like a password.
|
||||
- Never commit it to version control.
|
||||
- Never log it or expose it in API responses.
|
||||
- If compromised, generate a new keypair and update all references to the old `npub`.
|
||||
@@ -67,6 +67,7 @@ Every package extends `tsconfig.base.json` which sets `composite: true`. The roo
|
||||
|---|---|---|
|
||||
| `LNBITS_URL` | Base URL of your LNbits instance | `https://legend.lnbits.com` |
|
||||
| `LNBITS_API_KEY` | Invoice/Admin API key from your LNbits wallet | `a3f...` |
|
||||
| `TIMMY_NOSTR_NSEC` | Timmy's persistent Nostr private key (run `bash scripts/generate-timmy-nsec.sh` to generate) | `nsec1...` |
|
||||
|
||||
> **Note:** If `LNBITS_URL` and `LNBITS_API_KEY` are absent, `LNbitsService` automatically runs in **stub mode** — invoices are simulated in-memory and can be marked paid via `svc.stubMarkPaid(hash)`. This is intentional for development without a Lightning node.
|
||||
|
||||
|
||||
18
scripts/generate-timmy-nsec.sh
Executable file
18
scripts/generate-timmy-nsec.sh
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env bash
|
||||
# =============================================================================
|
||||
# Generate a fresh Nostr keypair for Timmy's persistent identity.
|
||||
#
|
||||
# Usage:
|
||||
# bash scripts/generate-timmy-nsec.sh
|
||||
#
|
||||
# Requires: pnpm, Node.js, nostr-tools (installed via pnpm install)
|
||||
#
|
||||
# Output: nsec1... private key, npub1... public key, and an export line
|
||||
# to copy-paste into your deployment environment.
|
||||
# =============================================================================
|
||||
set -euo pipefail
|
||||
|
||||
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
exec pnpm --filter @workspace/scripts run generate-timmy-nsec
|
||||
@@ -7,8 +7,12 @@
|
||||
"hello": "tsx ./src/hello.ts",
|
||||
"timmy-watch": "tsx ./src/timmy-watch.ts",
|
||||
"timmy-report": "tsx ./src/timmy-report.ts",
|
||||
"generate-timmy-nsec": "tsx ./src/generate-timmy-nsec.ts",
|
||||
"typecheck": "tsc -p tsconfig.json --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"nostr-tools": "^2.23.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "catalog:",
|
||||
"tsx": "catalog:"
|
||||
|
||||
28
scripts/src/generate-timmy-nsec.ts
Normal file
28
scripts/src/generate-timmy-nsec.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* generate-timmy-nsec.ts — Generate a fresh Nostr keypair for Timmy.
|
||||
*
|
||||
* Outputs the nsec (private) and npub (public) keys, plus a ready-to-paste
|
||||
* export line for setting the TIMMY_NOSTR_NSEC environment variable.
|
||||
*
|
||||
* Usage:
|
||||
* pnpm --filter @workspace/scripts run generate-timmy-nsec
|
||||
* # or via the wrapper:
|
||||
* bash scripts/generate-timmy-nsec.sh
|
||||
*/
|
||||
import { generateSecretKey, getPublicKey, nip19 } from "nostr-tools";
|
||||
|
||||
const sk = generateSecretKey();
|
||||
const pubkeyHex = getPublicKey(sk);
|
||||
const nsec = nip19.nsecEncode(sk);
|
||||
const npub = nip19.npubEncode(pubkeyHex);
|
||||
|
||||
console.log("=== Timmy Nostr Identity ===");
|
||||
console.log("");
|
||||
console.log(` npub: ${npub}`);
|
||||
console.log(` nsec: ${nsec}`);
|
||||
console.log("");
|
||||
console.log("Add this to your deployment environment:");
|
||||
console.log("");
|
||||
console.log(` export TIMMY_NOSTR_NSEC="${nsec}"`);
|
||||
console.log("");
|
||||
console.log("⚠ Keep the nsec secret — anyone with it can impersonate Timmy.");
|
||||
Reference in New Issue
Block a user