Replace Redis and BullMQ with NATS JetStream and KV for job queuing and state management in the compute worker service. Update environment variables, Docker Compose, and documentation to reflect the new message queue backend. Adjust dependencies and code to use NATS-based work queue and key-value storage for durable job processing. This change improves scalability and reliability of distributed compute workloads by leveraging NATS JetStream's work queue and persistence features. Documentation and configuration examples are updated to guide deployments using the new backend.
323 lines
8.3 KiB
Markdown
323 lines
8.3 KiB
Markdown
---
|
|
title: Local Development
|
|
---
|
|
|
|
import Tabs from '@theme/Tabs';
|
|
import TabItem from '@theme/TabItem';
|
|
|
|
## Prerequisites
|
|
|
|
<details>
|
|
<summary><strong>Node.js + pnpm (required)</strong></summary>
|
|
|
|
<Tabs groupId="local-dev-node-pnpm-os">
|
|
<TabItem value="macos" label="macOS" default>
|
|
|
|
```bash
|
|
brew install nvm pnpm
|
|
mkdir -p ~/.nvm
|
|
echo 'export NVM_DIR="$HOME/.nvm"' >> ~/.zshrc
|
|
echo '[ -s "$(brew --prefix nvm)/nvm.sh" ] && . "$(brew --prefix nvm)/nvm.sh"' >> ~/.zshrc
|
|
source ~/.zshrc
|
|
nvm install --lts
|
|
nvm use --lts
|
|
node -v
|
|
pnpm -v
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem value="linux" label="Linux">
|
|
|
|
```bash
|
|
# Debian/Ubuntu example
|
|
sudo apt update
|
|
sudo apt install -y curl
|
|
curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
|
|
export NVM_DIR="$HOME/.nvm"
|
|
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
|
|
nvm install --lts
|
|
nvm use --lts
|
|
corepack enable
|
|
corepack prepare pnpm@latest --activate
|
|
node -v
|
|
pnpm -v
|
|
```
|
|
|
|
</TabItem>
|
|
</Tabs>
|
|
|
|
</details>
|
|
|
|
<details>
|
|
<summary><strong>SeaweedFS <code>weed</code> binary (required unless using external S3)</strong></summary>
|
|
|
|
<Tabs groupId="local-dev-seaweed-os">
|
|
<TabItem value="macos" label="macOS" default>
|
|
|
|
```bash
|
|
brew install seaweedfs
|
|
weed version
|
|
```
|
|
|
|
:::warning SeaweedFS Compatibility Note (April 16, 2026)
|
|
If you see intermittent S3 `InternalError` upload failures with embedded storage, use SeaweedFS `4.18`.
|
|
OpenReader currently pins `4.18` in CI and Docker builds while `4.19` compatibility is investigated.
|
|
:::
|
|
|
|
</TabItem>
|
|
<TabItem value="linux" label="Linux">
|
|
|
|
```bash
|
|
# Linux amd64 example (pin 4.18)
|
|
mkdir -p "$HOME/.local/bin"
|
|
curl -fsSL -o /tmp/seaweedfs.tar.gz \
|
|
https://github.com/seaweedfs/seaweedfs/releases/download/4.18/linux_amd64.tar.gz
|
|
tar -xzf /tmp/seaweedfs.tar.gz -C /tmp weed
|
|
install -m 0755 /tmp/weed "$HOME/.local/bin/weed"
|
|
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
|
|
export PATH="$HOME/.local/bin:$PATH"
|
|
weed version
|
|
```
|
|
|
|
:::warning SeaweedFS Compatibility Note (April 16, 2026)
|
|
If you see intermittent S3 `InternalError` upload failures with embedded storage, use SeaweedFS `4.18`.
|
|
OpenReader currently pins `4.18` in CI and Docker builds while `4.19` compatibility is investigated.
|
|
:::
|
|
|
|
</TabItem>
|
|
</Tabs>
|
|
|
|
</details>
|
|
|
|
<details>
|
|
<summary><strong>LibreOffice (optional, for DOCX conversion)</strong></summary>
|
|
|
|
<Tabs groupId="local-dev-libreoffice-os">
|
|
<TabItem value="macos" label="macOS" default>
|
|
|
|
```bash
|
|
brew install libreoffice
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem value="linux" label="Linux">
|
|
|
|
```bash
|
|
# Debian/Ubuntu example
|
|
sudo apt update
|
|
sudo apt install -y libreoffice
|
|
```
|
|
|
|
</TabItem>
|
|
</Tabs>
|
|
|
|
</details>
|
|
|
|
<details>
|
|
<summary><strong>Word-by-word highlighting (optional)</strong></summary>
|
|
|
|
No extra native Whisper CLI build step is required.
|
|
|
|
Set `COMPUTE_MODE=local` to enable built-in ONNX word alignment in-process.
|
|
|
|
If you need mirrors or pinned artifact locations, set `WHISPER_MODEL_BASE_URL` in `.env`.
|
|
|
|
</details>
|
|
|
|
<details>
|
|
<summary><strong>External compute worker dev stack (optional)</strong></summary>
|
|
|
|
Use this when you want durable compute with NATS JetStream + KV while keeping Next.js on native host `pnpm dev`.
|
|
Full worker deployment details are in [Compute Worker (NATS JetStream)](./compute-worker).
|
|
|
|
Start only NATS + compute-worker via compose watch:
|
|
|
|
```bash
|
|
docker compose --env-file compute/worker/.env -f compute/worker/docker-compose.yml up --watch
|
|
# or: pnpm compute:dev:watch
|
|
```
|
|
|
|
`compute/worker/.env.example` contains a starter config. Copy it to `compute/worker/.env` and adjust values for your environment.
|
|
|
|
Run the main app separately on the host:
|
|
|
|
```bash
|
|
pnpm dev
|
|
```
|
|
|
|
For app server worker mode, set:
|
|
|
|
```env
|
|
COMPUTE_MODE=worker
|
|
COMPUTE_WORKER_URL=http://localhost:8081
|
|
COMPUTE_WORKER_TOKEN=<same-token-used-by-worker>
|
|
```
|
|
|
|
Worker mode requires worker-reachable shared object storage (S3-compatible endpoint).
|
|
Non-exposed embedded `weed mini` is not a supported topology for external worker mode.
|
|
|
|
</details>
|
|
|
|
## Steps
|
|
|
|
### Required flow
|
|
|
|
1. Clone the repository.
|
|
|
|
```bash
|
|
git clone https://github.com/richardr1126/openreader.git
|
|
cd openreader
|
|
```
|
|
|
|
2. Install dependencies.
|
|
|
|
```bash
|
|
pnpm i
|
|
```
|
|
|
|
3. Configure the environment.
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
```
|
|
|
|
Then edit `.env`.
|
|
|
|
Use one of these `.env` mode templates:
|
|
|
|
<Tabs groupId="local-env-modes">
|
|
<TabItem value="no-auth" label="No Auth (simple)" default>
|
|
|
|
```env
|
|
API_BASE=http://host.docker.internal:8880/v1
|
|
API_KEY=none
|
|
COMPUTE_MODE=local
|
|
# Leave BASE_URL and AUTH_SECRET unset to keep auth disabled.
|
|
# (Admin panel is unavailable without auth.)
|
|
# API_BASE/API_KEY seed a shared default provider if you want shared mode.
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem value="auth-enabled" label="Auth Enabled">
|
|
|
|
```env
|
|
API_BASE=http://host.docker.internal:8880/v1
|
|
API_KEY=none
|
|
COMPUTE_MODE=local
|
|
BASE_URL=http://localhost:3003
|
|
AUTH_SECRET=<generate-with-openssl-rand-hex-32>
|
|
# Optional when you need multiple local origins:
|
|
# AUTH_TRUSTED_ORIGINS=http://localhost:3003,http://127.0.0.1:3003
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem value="auth-with-admin" label="Auth + Admin Panel">
|
|
|
|
```env
|
|
# API_BASE / API_KEY are seeded into the admin "default-openai" shared provider
|
|
# on first boot, then no longer read. Manage them in Settings → Admin afterwards.
|
|
API_BASE=http://host.docker.internal:8880/v1
|
|
API_KEY=none
|
|
COMPUTE_MODE=local
|
|
BASE_URL=http://localhost:3003
|
|
AUTH_SECRET=<generate-with-openssl-rand-hex-32>
|
|
# Comma-separated emails to auto-promote to admin on signin.
|
|
ADMIN_EMAILS=you@example.com
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem value="external-s3" label="External S3">
|
|
|
|
```env
|
|
API_BASE=http://host.docker.internal:8880/v1
|
|
API_KEY=none
|
|
COMPUTE_MODE=local
|
|
USE_EMBEDDED_WEED_MINI=false
|
|
S3_BUCKET=your-bucket
|
|
S3_REGION=us-east-1
|
|
S3_ACCESS_KEY_ID=your-access-key
|
|
S3_SECRET_ACCESS_KEY=your-secret-key
|
|
# Optional for non-AWS providers:
|
|
# S3_ENDPOINT=https://your-s3-compatible-endpoint
|
|
# S3_FORCE_PATH_STYLE=true
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem value="worker-mode" label="External Worker + NATS">
|
|
|
|
```env
|
|
API_BASE=http://host.docker.internal:8880/v1
|
|
API_KEY=none
|
|
COMPUTE_MODE=worker
|
|
COMPUTE_WORKER_URL=http://localhost:8081
|
|
COMPUTE_WORKER_TOKEN=<same-token-used-by-worker>
|
|
USE_EMBEDDED_WEED_MINI=false
|
|
S3_BUCKET=your-bucket
|
|
S3_REGION=us-east-1
|
|
S3_ACCESS_KEY_ID=your-access-key
|
|
S3_SECRET_ACCESS_KEY=your-secret-key
|
|
# Optional for non-AWS providers:
|
|
# S3_ENDPOINT=https://your-s3-compatible-endpoint
|
|
# S3_FORCE_PATH_STYLE=true
|
|
```
|
|
|
|
</TabItem>
|
|
</Tabs>
|
|
|
|
:::note Env vars vs. admin panel
|
|
On first boot, `API_KEY` / `API_BASE` and any `RUNTIME_SEED_*` flags you've set get auto-seeded into the admin-managed runtime config (DB-backed, keys encrypted at rest). After that, the admin UI is authoritative and editing those env vars no longer changes app behavior. See [Admin Panel](../configure/admin-panel).
|
|
:::
|
|
|
|
:::note User BYOK restriction default
|
|
If you want each user to enter personal provider credentials, set `restrictUserApiKeys=false` (from **Settings → Admin** when auth/admin is enabled, or via legacy first-boot seed `RUNTIME_SEED_RESTRICT_USER_API_KEYS=false` for no-admin bootstrap flows).
|
|
:::
|
|
|
|
:::info
|
|
For all environment variables, see [Environment Variables](../reference/environment-variables).
|
|
:::
|
|
|
|
See [Auth](../configure/auth) for app/auth behavior.
|
|
See [Admin Panel](../configure/admin-panel) for the shared-provider and feature-flag management UI.
|
|
Storage configuration details are in [Object / Blob Storage](../configure/object-blob-storage).
|
|
Refer to [Database](../configure/database) for database modes.
|
|
Learn about migration behavior and commands in [Migrations](../configure/migrations).
|
|
|
|
4. Start the app.
|
|
|
|
<Tabs groupId="local-run-mode">
|
|
<TabItem value="dev" label="Dev (recommended)" default>
|
|
|
|
```bash
|
|
pnpm dev
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem value="prod" label="Build + Start">
|
|
|
|
```bash
|
|
pnpm build
|
|
pnpm start
|
|
```
|
|
|
|
</TabItem>
|
|
</Tabs>
|
|
|
|
:::warning API Base Reachability
|
|
`API_BASE` must be reachable from the Next.js server process, not just your browser.
|
|
:::
|
|
|
|
Visit [http://localhost:3003](http://localhost:3003).
|
|
|
|
### Optional workflows
|
|
|
|
Run manual DB migrations only for troubleshooting or explicit migration workflows:
|
|
|
|
- Migrations run automatically on startup through the shared entrypoint for both `pnpm dev` and `pnpm start`.
|
|
|
|
```bash
|
|
pnpm migrate
|
|
```
|
|
|
|
:::info
|
|
If `POSTGRES_URL` is set, migrations target Postgres; otherwise local SQLite is used. To disable automatic startup migrations, set `RUN_DRIZZLE_MIGRATIONS=false` and/or `RUN_FS_MIGRATIONS=false`. You can run storage migration manually with `pnpm migrate-fs`.
|
|
:::
|