When the nsec lives only in the encrypted Secret store (env carries no NSEC) and the settings blob holds no npub, bootstrap_secrets decrypted the nsec and derived the npub into memory, but SettingsService.initialize then re-derived settings from the npub-less blob and overwrote the live npub back to empty — leaving a private key with no matching public key, so the node silently stopped announcing a usable Nostr identity. Derive npub from the live nsec during initialize when the merged settings carry none, so the public key stays consistent with the identity and is persisted to the blob. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Routstr Payment Proxy
Routstr is a decentralized protocol for permissionless, private, and censorship-resistant AI inference. It combines Nostr for discovery and Cashu for private Bitcoin micropayments.
This repo contains Routstr Core: a FastAPI-based reverse proxy that sits in front of OpenAI-compatible APIs and handles pay-per-request billing.
Start Here
- Overview: https://docs.routstr.com/overview/
- Provider Guide: https://docs.routstr.com/provider/quickstart/
- User Guide: https://docs.routstr.com/user-guide/introduction/
Basic Usage
If you are a user/developer, you just point an OpenAI-compatible SDK at a Routstr node and pay with a Cashu token.
OpenAI SDK
from openai import OpenAI
client = OpenAI(
base_url="https://api.routstr.com/v1",
api_key="cashuBo2FteCJodHRwczovL21...",
)
response = client.chat.completions.create(
model="gpt-5-nano",
messages=[{"role": "user", "content": "hello"}],
)
print(response.choices[0].message.content)
cURL
curl https://api.routstr.com/v1/chat/completions \
-H "Content-Type: application/json" \
-H "x-cashu: cashuBo2FteCJodHRwczovL21..." \
-d '{
"model": "gpt-5-nano",
"messages": [{"role": "user", "content": "hello"}]
}'
Quick Start (Docker)
If you are a node runner, start a Routstr Core instance using Docker Compose:
-
Prepare your
.env:# Required: encrypts secrets at rest. The node won't start without it. ROUTSTR_SECRET_KEY=<generated-key> NAME="My AI Node" DESCRIPTION="Fast access to models" NSEC=yournsec RECEIVE_LN_ADDRESS=yourname@wallet.comGenerate
ROUTSTR_SECRET_KEYonce and keep it stable — changing it makes previously encrypted secrets unreadable:python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())" -
Start the services:
docker compose up -d -
Get your admin password: On first start the node generates an admin password and logs it once with the
/adminURL. Read it from the logs:docker compose logs routstr | grep -i admin(Lost it? Reset with
python scripts/reset_admin_password.py --regenerate.) -
Configure: Open http://localhost:8000/admin/ to connect your AI providers and set pricing.
For full instructions, see the Provider Quick Start Guide.
Development
make setup
cp .env.example .env
fastapi run routstr