Skip to main content
Version: Next

Docker Quick Start

Prerequisites

SeaweedFS Compatibility Note (April 16, 2026)

OpenReader currently pins embedded SeaweedFS to 4.18 in CI and Docker builds. 4.19 introduced intermittent InternalError responses on S3 PutObject in our upload flow.

1. Start the Docker container

Persistent storage, embedded SeaweedFS weed mini, optional auth, optional library mount:

docker run --name openreader \
--restart unless-stopped \
-p 3003:3003 \
-p 8333:8333 \
-v openreader_docstore:/app/docstore \
-v /path/to/your/library:/app/docstore/library:ro \
-e API_BASE=http://host.docker.internal:8880/v1 \
-e API_KEY=none \
-e BASE_URL=http://localhost:3003 \
-e AUTH_SECRET=$(openssl rand -hex 32) \
-e ADMIN_EMAILS=you@example.com \
ghcr.io/richardr1126/openreader:latest

What this command enables:

  • -p 3003:3003: exposes the OpenReader web app/API.
  • -p 8333:8333: exposes embedded SeaweedFS S3 endpoint for direct browser presigned upload/download.
  • -v openreader_docstore:/app/docstore: persists SQLite metadata, SeaweedFS blob data, and migration/runtime state.
  • -v /path/to/your/library:/app/docstore/library:ro: mounts a read-only importable library source.
  • -e API_BASE=... / -e API_KEY=...: first-boot seed only. On the first container start, these are auto-migrated into a default-openai admin shared provider stored in the DB (key encrypted at rest). After that, the running app no longer reads them — manage the provider from Settings → Admin → Shared providers. See Admin Panel.
  • -e BASE_URL=... and -e AUTH_SECRET=...: together they turn on auth/session mode for local sign-in flows.
  • -e ADMIN_EMAILS=...: (optional, requires auth) comma-separated emails auto-promoted to admin. Admins see the Admin tab in Settings.
Quick Tips
  • Set API_BASE on first boot to a TTS endpoint the container can reach (host.docker.internal works for host-local services). After first boot, manage providers in Settings → Admin → Shared providers.
  • Auth is enabled only when both BASE_URL and AUTH_SECRET are set. The admin panel requires auth.
  • Set ADMIN_EMAILS to your email if you want the Admin tab in Settings.
  • restrictUserApiKeys controls shared-provider-only mode. For per-user BYOK in auth-enabled setups, toggle it off in Settings → Admin → Site features. Legacy first-boot seed via NEXT_PUBLIC_RESTRICT_USER_API_KEYS=false is still supported.
  • Use a /app/docstore mount if you want data to survive container/image replacement.
  • Startup automatically runs DB/storage migrations via the shared entrypoint.
Port 8333 Exposure

Expose 8333 for direct browser presigned upload/download with embedded SeaweedFS.

If 8333 is not reachable from the browser, direct presigned access is unavailable. Uploads can still fall back to /api/documents/blob/upload/fallback, and document reads/downloads continue through /api/documents/blob.

2. Configure settings in the app UI

Visit http://localhost:3003 after startup.

  • If you set ADMIN_EMAILS, sign in with that email and open Settings → Admin to manage shared TTS providers and site feature flags for all users.
  • Per-user: set TTS provider/model in Settings → TTS Provider. API key/base URL inputs are shown only when restrictUserApiKeys=false.
  • Select the model voice from the voice dropdown.

3. Update Docker image

Legacy image compatibility: ghcr.io/richardr1126/openreader-webui:latest remains available as an alias.

docker stop openreader || true && \
docker rm openreader || true && \
docker image rm ghcr.io/richardr1126/openreader:latest || true && \
docker pull ghcr.io/richardr1126/openreader:latest
tip

If you use a mounted volume for /app/docstore, your persisted data remains after image updates.