9qeklajc c2b807bb20 fix: keep spendable credentials out of the structured logs
The dated JSON log files were a credential store. Structured `extra`
fields bypass the message-level regex scrubbing entirely — the JSON
formatter reads them straight off the record dict — and the only pass
they received was organization-ID redaction. So a full Cashu refund
token, and the `hashed_key` that `sk-<hashed_key>` auth accepts as a
live reusable API key, were written verbatim, as were all request query
values. Anyone able to read a log file could spend from it.

Fixed at both ends so neither alone is load-bearing. The call sites stop
handing over the values: balance logs a token length and an eight-char
key prefix, and the request middleware logs query parameter names
without their values. The SecurityFilter then refuses to emit them
anyway, walking every extra recursively and stripping both secret-shaped
keys and secret-shaped values (Cashu tokens, bearer values, `sk-` keys,
nsec keys, full SHA-256 hashes, secret-ish query parameters) wherever
they are nested. The walk is depth-limited and cycle-safe so a malformed
payload degrades to `[REDACTED]` instead of failing the log call, and
numeric values are never touched, which keeps the usage-analytics fields
the dashboard parses intact.

Retention is also wired up: `backupCount` never expired anything here
because the base filename moves with the date, so the inherited rollover
found no siblings and every day of logs was kept forever. Rollover now
prunes explicitly.
2026-08-24 01:48:16 +02:00
2026-08-23 11:06:06 +02:00
2025-10-22 12:18:00 +08:00
2026-08-23 11:19:41 +02:00
2026-08-06 22:58:44 +02:00
2026-08-14 21:48:29 +02:00
2025-10-16 16:03:39 +08:00
2025-06-09 23:46:19 +02:00
2025-08-12 15:02:22 -03:00
2026-07-07 17:22:48 +02:00
2025-04-08 21:42:32 +08:00
2026-01-24 17:55:45 +08:00
2025-08-01 22:31:18 -03:00
2026-08-17 00:23:15 +02:00
2026-08-17 00:23:15 +02:00

Routstr Payment Proxy

License Stars Issues Release

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

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:

  1. Prepare your .env:

    # Optional: encrypts node secrets at rest. If unset, the node generates a key
    # on first start, writes it to routstr_secret.key, and prints it once — back
    # up that file. Set it explicitly to manage the key yourself (recommended in
    # production).
    ROUTSTR_SECRET_KEY=<generated-key>
    NAME="My AI Node"
    DESCRIPTION="Fast access to models"
    RECEIVE_LN_ADDRESS=yourname@wallet.com
    

    Your Nostr identity (nsec) is not set in .env — configure it from the admin UI after first start, where it's stored encrypted in the database. (NSEC in .env is still read once as a legacy seed for existing deployments.)

    If you don't set one, a key is generated and printed on first start — save it somewhere safe (losing it makes previously encrypted secrets unreadable). To supply your own, generate it once and keep it stable:

    uv run python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
    
  2. Start the services:

    docker compose up -d
    
  3. Get your admin password: On first start the node generates an admin password and logs it once with the /admin URL. Read it from the logs:

    docker compose logs routstr | grep -i admin
    

    (Lost it? Reset with docker compose exec routstr /.venv/bin/python scripts/reset_admin_password.py --regenerate.)

  4. 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
S
Description
Routstr is a decentralized protocol for permissionless, private, and censorship-resistant AI inference.
Readme GPL-3.0
33 MiB
Languages
Python 79.8%
TypeScript 18.3%
HTML 1.2%
JavaScript 0.2%
Makefile 0.2%
Other 0.3%