docs: reflect the optional, auto-generated secret key

The secret-key docs still said ROUTSTR_SECRET_KEY was required and that
the node would not start without it. Update the README, .env.example, and
the provider docs (configuration, quickstart, deployment) to the current
behaviour: the key is optional; when unset the node generates one beside
the database, so it persists on the same volume as the data, and prints a
one-time back-it-up notice; set it explicitly to manage the key yourself.
Switch the generation and reset snippets to `uv run python`, and add the
containerised reset variant.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Jeroen Ubbink
2026-07-23 10:51:20 +02:00
co-authored by Claude Opus 4.8
parent 7106dfe330
commit d4657dca5a
5 changed files with 51 additions and 8 deletions
+6 -3
View File
@@ -5,9 +5,12 @@ UPSTREAM_API_KEY=your-upstream-api-key
# Tinfoil (confidential inference enclaves, EHBP)
# TINFOIL_API_KEY=your-tinfoil-api-key
# Secret key used to encrypt secrets at rest (REQUIRED). The node refuses to
# start without it. Generate one with:
# python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
# Secret key used to encrypt node secrets at rest (optional). If unset, the node
# generates one on first start, writes it to routstr_secret.key (override the path
# with ROUTSTR_SECRET_KEY_FILE), and prints it once — back that file up, because
# losing the key makes previously encrypted secrets unreadable. Set it explicitly
# to manage the key yourself (recommended in production). Generate one with:
# uv run python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
ROUTSTR_SECRET_KEY=
# The admin password and the Nostr identity (nsec) are NOT set here. The admin
+9 -5
View File
@@ -55,7 +55,10 @@ If you are a node runner, start a Routstr Core instance using Docker Compose:
1. **Prepare your `.env`**:
```bash
# Required: encrypts secrets at rest. The node won't start without it.
# 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"
@@ -63,10 +66,11 @@ If you are a node runner, start a Routstr Core instance using Docker Compose:
RECEIVE_LN_ADDRESS=yourname@wallet.com
```
Generate `ROUTSTR_SECRET_KEY` once and keep it stable — changing it makes
previously encrypted secrets unreadable:
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:
```bash
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
uv run python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
```
2. **Start the services**:
@@ -80,7 +84,7 @@ If you are a node runner, start a Routstr Core instance using Docker Compose:
```bash
docker compose logs routstr | grep -i admin
```
(Lost it? Reset with `python scripts/reset_admin_password.py --regenerate`.)
(Lost it? Reset with `docker compose exec routstr /.venv/bin/python scripts/reset_admin_password.py --regenerate`.)
4. **Configure**:
Open [http://localhost:8000/admin/](http://localhost:8000/admin/) to connect your AI providers and set pricing.
+21
View File
@@ -15,6 +15,11 @@ Before running your node, you should create a `.env` file in the project root. T
```bash
ADMIN_PASSWORD=your-secure-password
# Encrypts node secrets at rest. Optional — if unset, the node generates a key on
# first start and prints it once (back it up). Set it to manage the key yourself
# (recommended in production). See "Secrets at Rest" below.
ROUTSTR_SECRET_KEY=
# Node Identity
NAME="My AI Node"
DESCRIPTION="Fast access to models"
@@ -124,6 +129,8 @@ Use environment variables for:
| `UPSTREAM_BASE_URL` | Upstream API endpoint | — |
| `UPSTREAM_API_KEY` | Upstream API key | — |
| `ADMIN_PASSWORD` | Dashboard password | (none) |
| `ROUTSTR_SECRET_KEY` | Master key encrypting node secrets at rest. Auto-generated to a key file if unset | (auto-generated) |
| `ROUTSTR_SECRET_KEY_FILE` | Path to the generated key file (used when `ROUTSTR_SECRET_KEY` is unset) | `routstr_secret.key` beside the database |
| `DATABASE_URL` | Database connection string | `sqlite+aiosqlite:///keys.db` |
| `NAME` | Node display name | `ARoutstrNode` |
| `DESCRIPTION` | Node description | `A Routstr Node` |
@@ -142,6 +149,20 @@ Use environment variables for:
Environment variables are read on startup. Dashboard settings override them and persist in the database. Once you change a setting in the dashboard, the env var is ignored for that setting.
### Secrets at Rest
The node's Nostr private key (`nsec`) is encrypted in the database using
`ROUTSTR_SECRET_KEY`. You don't have to set it: if it's unset, the node generates a
key on first start, writes it **beside the database** (the file named by
`ROUTSTR_SECRET_KEY_FILE`, default `routstr_secret.key`) so it persists on the same
volume as your data, and prints it once.
**Back up that key** — it lives on the same volume as your database, so include it
in your backups. If it is lost or changed, previously encrypted secrets can't be
decrypted and must be re-entered — there is no rotation. To keep the key off the
data volume, set `ROUTSTR_SECRET_KEY` explicitly (an env value always takes
precedence over the file). See also [Deployment](deployment.md).
---
## Models
+11
View File
@@ -156,10 +156,21 @@ Example `.env`:
UPSTREAM_BASE_URL=https://api.openai.com/v1
UPSTREAM_API_KEY=sk-proj-...
ADMIN_PASSWORD=change-me
# Encrypts node secrets at rest. Optional — if unset, a key is generated next to
# your database (on the same volume) and printed once. Set it explicitly to
# manage the key yourself.
ROUTSTR_SECRET_KEY=
NAME=My Provider Node
RECEIVE_LN_ADDRESS=me@walletofsatoshi.com
```
!!! note "Secret key persistence"
If you leave `ROUTSTR_SECRET_KEY` unset, the node generates one and stores it
as `routstr_secret.key` **next to your database**, so it persists on the same
volume as your data — just include that volume in your backups. For stronger
isolation (keeping the key off the data volume), set `ROUTSTR_SECRET_KEY` from
a secrets manager instead.
See [Configuration](configuration.md) for all available options.
---
+4
View File
@@ -32,6 +32,10 @@ Create a `.env` file in the root of the project to store your secrets:
# Initial Admin Password
ADMIN_PASSWORD=mysecretpassword
# Encrypts node secrets at rest. Optional — if unset, the node generates a key on
# first start and prints it once (back it up).
ROUTSTR_SECRET_KEY=
# Node Identity
NAME="My AI Node"
DESCRIPTION="Fast access to models"