mirror of
https://github.com/Routstr/routstr-core.git
synced 2026-10-05 12:28:22 +00:00
docs: make clone + docker compose the preferred deployment path
The deployment page led with a third-party all-in-one Docker Hub image (`9qeklajc/routstr`) that is not published by this repo's release workflow, while the Tor and pre-config examples pulled `ghcr.io/routstr/proxy` and built from source — three different starting points for the same node. Lead with the supported path instead: clone the repo at a release tag, copy `.env.example` to `.env`, and `docker compose up -d`, which builds the node and dashboard from source. - Drop the all-in-one image section and its compose snippet. - Add the clone/release checkout steps, including `cp .env.example .env` (compose declares `env_file: .env`, so `up` fails without it). - Fold the duplicate Tor compose example into a pointer to `tor.md`, since the default `compose.yml` already runs Tor. - Correct the persistence table: with `.:/app` mounted, state lives in the clone (`keys.db`, `routstr_secret.key`, `.wallet/`), not `/app/data`. - Document `--build` on updates and the first-start build time. - README quick start: add the missing clone step to match.
This commit is contained in:
@@ -51,9 +51,25 @@ curl https://api.routstr.com/v1/chat/completions \
|
|||||||
|
|
||||||
## Quick Start (Docker)
|
## Quick Start (Docker)
|
||||||
|
|
||||||
If you are a node runner, start a Routstr Core instance using Docker Compose:
|
If you are a node runner, the recommended way to start Routstr Core is to clone
|
||||||
|
the repository at the latest release and run it with Docker Compose:
|
||||||
|
|
||||||
1. **Prepare your `.env`**:
|
1. **Clone the latest release**:
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/Routstr/routstr-core.git
|
||||||
|
cd routstr-core
|
||||||
|
git checkout v0.4.7 # current release — see https://github.com/Routstr/routstr-core/releases/latest
|
||||||
|
```
|
||||||
|
|
||||||
|
Docker Compose builds the node and the admin dashboard from source, so there
|
||||||
|
is no image to pull.
|
||||||
|
|
||||||
|
2. **Prepare your `.env`**:
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
```
|
||||||
|
|
||||||
|
Then edit it with your details:
|
||||||
```bash
|
```bash
|
||||||
# Optional: encrypts node secrets at rest. If unset, the node generates a key
|
# 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
|
# on first start, writes it to routstr_secret.key, and prints it once — back
|
||||||
@@ -76,12 +92,14 @@ If you are a node runner, start a Routstr Core instance using Docker Compose:
|
|||||||
uv run 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**:
|
3. **Start the services**:
|
||||||
```bash
|
```bash
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
3. **Get your admin password**:
|
The first start builds both images (the dashboard build takes a few minutes).
|
||||||
|
|
||||||
|
4. **Get your admin password**:
|
||||||
On first start the node generates an admin password and logs it once with the
|
On first start the node generates an admin password and logs it once with the
|
||||||
`/admin` URL. Read it from the logs:
|
`/admin` URL. Read it from the logs:
|
||||||
```bash
|
```bash
|
||||||
@@ -89,7 +107,7 @@ If you are a node runner, start a Routstr Core instance using Docker Compose:
|
|||||||
```
|
```
|
||||||
(Lost it? Reset with `docker compose exec routstr /.venv/bin/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**:
|
5. **Configure**:
|
||||||
Open [http://localhost:8000/admin/](http://localhost:8000/admin/) to connect your AI providers and set pricing.
|
Open [http://localhost:8000/admin/](http://localhost:8000/admin/) to connect your AI providers and set pricing.
|
||||||
|
|
||||||
For full instructions, see the **[Provider Quick Start Guide](https://docs.routstr.com/provider/quickstart/)**.
|
For full instructions, see the **[Provider Quick Start Guide](https://docs.routstr.com/provider/quickstart/)**.
|
||||||
|
|||||||
+79
-149
@@ -2,179 +2,97 @@
|
|||||||
|
|
||||||
Production deployment guide for Routstr Provider nodes.
|
Production deployment guide for Routstr Provider nodes.
|
||||||
|
|
||||||
## All-in-One Docker Image (Preferred)
|
## Quick Start (Recommended)
|
||||||
|
|
||||||
The easiest way to deploy Routstr is using the all-in-one Docker image from Docker Hub, which includes both the FastAPI backend and the Next.js admin dashboard in a single container.
|
The recommended way to run a provider node is to clone the repository at the
|
||||||
|
**latest release** and start the stack with Docker Compose. Compose builds both
|
||||||
### Quick Start
|
the node and the admin dashboard from source, so there is no image to pull and no
|
||||||
|
dashboard build to keep in sync with the node.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run -d \
|
git clone https://github.com/Routstr/routstr-core.git
|
||||||
--name routstr \
|
cd routstr-core
|
||||||
-p 8000:8000 \
|
|
||||||
-v routstr-data:/app/data \
|
|
||||||
-e DATABASE_URL="sqlite:////app/data/routstr.db" \
|
|
||||||
9qeklajc/routstr:latest
|
|
||||||
```
|
|
||||||
|
|
||||||
Access your node:
|
# Check out a release (v0.4.7 is current — see the releases page for the newest tag)
|
||||||
- **API & Admin Dashboard**: http://localhost:8000
|
git checkout v0.4.7
|
||||||
|
|
||||||
### Docker Compose Setup
|
# Compose reads its configuration from .env
|
||||||
|
cp .env.example .env
|
||||||
|
|
||||||
Create `docker-compose.yml`:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
version: '3.8'
|
|
||||||
|
|
||||||
services:
|
|
||||||
routstr:
|
|
||||||
image: 9qeklajc/routstr:latest
|
|
||||||
container_name: routstr
|
|
||||||
restart: unless-stopped
|
|
||||||
ports:
|
|
||||||
- "8000:8000"
|
|
||||||
volumes:
|
|
||||||
- routstr-data:/app/data
|
|
||||||
environment:
|
|
||||||
DATABASE_URL: "sqlite:////app/data/routstr.db"
|
|
||||||
LOG_LEVEL: "info"
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
routstr-data:
|
|
||||||
```
|
|
||||||
|
|
||||||
Start it:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
Then open your node:
|
||||||
|
- **API & Admin Dashboard**: <http://localhost:8000>
|
||||||
## Docker Compose (Recommended)
|
- **Admin login**: the password is generated and logged once on first start
|
||||||
|
|
||||||
For production, use Docker Compose with persistent storage and optional Tor support.
|
|
||||||
|
|
||||||
Use the included `compose.yml` for a flexible setup that handles both the UI and the node execution. This is useful for development or when you want to manage Tor as a separate service.
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose up -d
|
docker compose logs routstr | grep -i admin
|
||||||
```
|
```
|
||||||
|
|
||||||
This will:
|
!!! note "The first start takes a few minutes"
|
||||||
1. **Build the UI**: Compiles the frontend and copies it to a shared volume.
|
`docker compose up` builds both images locally, and the Next.js dashboard
|
||||||
2. **Start Routstr**: Runs the Python node, mounting the built UI.
|
build is the slow part. Later starts reuse the built images.
|
||||||
3. **Start Tor**: Provides anonymous access via a `.onion` address.
|
|
||||||
|
!!! tip "Always tracking the newest release"
|
||||||
|
To check out whatever `releases/latest` currently points at, use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/Routstr/routstr-core.git
|
||||||
|
cd routstr-core
|
||||||
|
git checkout "$(curl -sSL -o /dev/null -w '%{url_effective}' \
|
||||||
|
https://github.com/Routstr/routstr-core/releases/latest | sed 's|.*/tag/||')"
|
||||||
|
```
|
||||||
|
|
||||||
|
Omitting the `git checkout` entirely leaves you on `main` — newer, but not a
|
||||||
|
tested release.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## With Tor (Anonymous Access)
|
## What Docker Compose Starts
|
||||||
|
|
||||||
Add Tor to serve your node as a hidden service—no port forwarding needed.
|
`compose.yml` brings up three services:
|
||||||
|
|
||||||
```yaml
|
1. **ui** — builds the Next.js admin dashboard and copies the result into the
|
||||||
services:
|
shared `./ui_out` volume.
|
||||||
routstr:
|
2. **routstr** — the Python node, serving the API and the dashboard built above.
|
||||||
image: ghcr.io/routstr/proxy:latest
|
3. **tor** — serves the node as a `.onion` hidden service, so no port forwarding
|
||||||
container_name: routstr
|
is needed. See [Tor Support](tor.md) for how to read your `.onion` address.
|
||||||
restart: unless-stopped
|
|
||||||
ports:
|
|
||||||
- "8000:8000"
|
|
||||||
volumes:
|
|
||||||
- ./data:/app/data
|
|
||||||
- ./logs:/app/logs
|
|
||||||
environment:
|
|
||||||
- TOR_PROXY_URL=socks5://tor:9050
|
|
||||||
# Keep the database (and the key file generated beside it) on the volume.
|
|
||||||
- DATABASE_URL=sqlite:////app/data/routstr.db
|
|
||||||
depends_on:
|
|
||||||
- tor
|
|
||||||
|
|
||||||
tor:
|
|
||||||
image: ghcr.io/hundehausen/tor-hidden-service:latest
|
|
||||||
container_name: tor
|
|
||||||
restart: unless-stopped
|
|
||||||
volumes:
|
|
||||||
- ./tor-data:/var/lib/tor
|
|
||||||
environment:
|
|
||||||
- HS_ROUTER=routstr:8000:80
|
|
||||||
```
|
|
||||||
|
|
||||||
After starting, find your `.onion` address:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker exec tor cat /var/lib/tor/hidden_service/hostname
|
|
||||||
```
|
|
||||||
|
|
||||||
See [Tor Support](tor.md) for details.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Pre-Configuration (Optional)
|
## Pre-Configuration (Optional)
|
||||||
|
|
||||||
While everything can be configured via the dashboard, you can pre-configure settings with environment variables for automated deployments.
|
Everything can be configured from the dashboard after first start, but you can
|
||||||
|
pre-configure a deployment by editing the `.env` file you created above:
|
||||||
### Using Environment Variables
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
services:
|
|
||||||
routstr:
|
|
||||||
image: ghcr.io/routstr/proxy:latest
|
|
||||||
environment:
|
|
||||||
# Pre-configure upstream (optional)
|
|
||||||
- UPSTREAM_BASE_URL=https://api.openai.com/v1
|
|
||||||
- UPSTREAM_API_KEY=sk-proj-...
|
|
||||||
|
|
||||||
# The admin password is generated and logged once on first start; set
|
|
||||||
# ADMIN_PASSWORD here only as a legacy seed for an existing deployment.
|
|
||||||
|
|
||||||
# Node identity
|
|
||||||
- NAME=My Provider Node
|
|
||||||
- DESCRIPTION=Fast GPT-4 access via Lightning
|
|
||||||
|
|
||||||
# Lightning withdrawals
|
|
||||||
- RECEIVE_LN_ADDRESS=me@walletofsatoshi.com
|
|
||||||
|
|
||||||
# Keep the database (and the key file generated beside it) on the volume.
|
|
||||||
- DATABASE_URL=sqlite:////app/data/routstr.db
|
|
||||||
volumes:
|
|
||||||
- ./data:/app/data
|
|
||||||
```
|
|
||||||
|
|
||||||
### Using an .env File
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
services:
|
|
||||||
routstr:
|
|
||||||
image: ghcr.io/routstr/proxy:latest
|
|
||||||
env_file:
|
|
||||||
- .env
|
|
||||||
volumes:
|
|
||||||
- ./data:/app/data
|
|
||||||
```
|
|
||||||
|
|
||||||
Example `.env`:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# Upstream (optional — can also be set from the dashboard)
|
||||||
UPSTREAM_BASE_URL=https://api.openai.com/v1
|
UPSTREAM_BASE_URL=https://api.openai.com/v1
|
||||||
UPSTREAM_API_KEY=sk-proj-...
|
UPSTREAM_API_KEY=sk-proj-...
|
||||||
# Keep the database (and the key file generated beside it) on the mounted volume.
|
|
||||||
DATABASE_URL=sqlite:////app/data/routstr.db
|
|
||||||
# Encrypts node secrets at rest. Optional — if unset, a key is generated next to
|
# Encrypts node secrets at rest. Optional — if unset, a key is generated next to
|
||||||
# your database (on the same volume) and its file is named once for backup. Set
|
# your database (on the same volume) and its file is named once for backup. Set
|
||||||
# it explicitly to manage the key yourself.
|
# it explicitly to manage the key yourself.
|
||||||
ROUTSTR_SECRET_KEY=
|
ROUTSTR_SECRET_KEY=
|
||||||
|
|
||||||
|
# Node identity
|
||||||
NAME=My Provider Node
|
NAME=My Provider Node
|
||||||
|
DESCRIPTION=Fast GPT-4 access via Lightning
|
||||||
|
|
||||||
|
# Lightning withdrawals
|
||||||
RECEIVE_LN_ADDRESS=me@walletofsatoshi.com
|
RECEIVE_LN_ADDRESS=me@walletofsatoshi.com
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The admin password is generated and logged once on first start; set
|
||||||
|
`ADMIN_PASSWORD` only as a legacy seed for an existing deployment.
|
||||||
|
|
||||||
!!! note "Secret key persistence"
|
!!! note "Secret key persistence"
|
||||||
If you leave `ROUTSTR_SECRET_KEY` unset, the node generates one and stores it
|
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
|
as `routstr_secret.key` **next to your database**, so it persists alongside
|
||||||
volume as your data — just include that volume in your backups. For stronger
|
your data — just include that in your backups. For stronger isolation
|
||||||
isolation (keeping the key off the data volume), set `ROUTSTR_SECRET_KEY` from
|
(keeping the key off the data volume), set `ROUTSTR_SECRET_KEY` from a
|
||||||
a secrets manager instead.
|
secrets manager instead.
|
||||||
|
|
||||||
See [Configuration](configuration.md) for all available options.
|
See [Configuration](configuration.md) for all available options.
|
||||||
|
|
||||||
@@ -182,17 +100,21 @@ See [Configuration](configuration.md) for all available options.
|
|||||||
|
|
||||||
## Persistence
|
## Persistence
|
||||||
|
|
||||||
Point `DATABASE_URL` inside `/app/data` (as the examples above do) so everything
|
With the default `compose.yml` the repository directory is mounted into the
|
||||||
Routstr persists lands on the mounted volume:
|
container, so everything Routstr persists stays in the directory you cloned:
|
||||||
|
|
||||||
| Path | Contents |
|
| Path | Contents |
|
||||||
|------|----------|
|
|------|----------|
|
||||||
| `routstr.db` | SQLite database (settings, API keys, sessions) |
|
| `keys.db` | SQLite database (settings, API keys, sessions) |
|
||||||
| `routstr_secret.key` | Auto-generated master key, written beside the database when `ROUTSTR_SECRET_KEY` is unset |
|
| `routstr_secret.key` | Auto-generated master key, written beside the database when `ROUTSTR_SECRET_KEY` is unset |
|
||||||
| `.wallet/` | Cashu wallet data (your Bitcoin!) |
|
| `.wallet/` | Cashu wallet data (your Bitcoin!) |
|
||||||
|
| `logs/` | Node logs |
|
||||||
|
|
||||||
!!! warning "Back Up Your Data"
|
!!! warning "Back Up Your Data"
|
||||||
The `./data` volume contains your wallet. Losing it means losing funds. Back up regularly.
|
Your cloned directory holds your wallet and your master key. Losing it means
|
||||||
|
losing funds. Back it up regularly — and don't delete the checkout to
|
||||||
|
"start fresh" without copying `keys.db`, `routstr_secret.key` and `.wallet/`
|
||||||
|
first.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -233,27 +155,35 @@ server {
|
|||||||
|
|
||||||
## Updates
|
## Updates
|
||||||
|
|
||||||
Pull the latest image and restart:
|
Check out the new release and rebuild:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose pull
|
git fetch --tags
|
||||||
docker compose up -d
|
git checkout v0.4.7 # or the tag you are moving to
|
||||||
|
docker compose up -d --build
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`--build` is required: Compose reuses an existing image for a service unless you
|
||||||
|
ask it to rebuild.
|
||||||
|
|
||||||
|
!!! warning "Back up first"
|
||||||
|
Copy `keys.db`, `routstr_secret.key` and `.wallet/` before updating, and read
|
||||||
|
the release notes for the version you are moving to.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Building from Source
|
## Building Without Starting
|
||||||
|
|
||||||
### Using Docker Compose
|
`docker compose up -d` already builds from source. To build the images
|
||||||
The easiest way to build everything from source:
|
explicitly without starting them:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose build
|
docker compose build
|
||||||
```
|
```
|
||||||
|
|
||||||
### Individual Components
|
To build only the node image (the dashboard must already be built into
|
||||||
If you prefer building the node only (requires manual UI build first):
|
`./ui_out`):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker build -t routstr-node .
|
docker build -t routstr-node .
|
||||||
```
|
```
|
||||||
Reference in New Issue
Block a user