Skip to content

Installation ​

GsKnora supports Docker Compose, Kubernetes Helm, a Lite single binary, and a desktop app. Use Compose or Helm on servers, Lite locally, and a separate dev stack for development. Dependencies, start commands, and data directories for each mode are below.

Deployment options ​

ModeEntryDatabaseQueue / streamsUse case
Docker Compose (standard)docker-compose.ymlParadeDB (PostgreSQL)Redis + AsynqProduction / team self-host (recommended)
Docker Compose (dev)docker-compose.dev.ymlSame (infra only in containers)SameLocal dev: app / frontend on host
Helmhelm/ParadeDB (in chart)Redis (in chart)Kubernetes >= 1.25
Lite binarymake build-lite / scripts/package-lite.shSQLite (FTS5 + sqlite-vec)In-memory (no Redis)Personal / offline / low resources
Desktop app (not officially released)cmd/desktop (Wails v2) + scripts/package-mac-app.shSQLiteIn-memoryDesktop single-user, GUI and local data dir

Hardware and dependencies ​

  • Standard Docker: Docker 20.10+ and Docker Compose v2 (v1 docker-compose also works; scripts/start_all.sh auto-detects). Start with 4 CPU cores / 8 GB RAM (docreader includes LibreOffice and Playwright and is memory-heavy). Disk for Postgres volume + /data/files. Optional Milvus / OpenSearch / Langfuse need more RAM.
  • Models: Local inference needs Ollama (default http://host.docker.internal:11434; with OLLAMA_OPTIONAL=true, unavailable Ollama warns but does not block), or any OpenAI-compatible API (DeepSeek, Tongyi, Zhipu, SiliconFlow, etc.). The 8 GB baseline excludes Ollama model weights. Neo4j is off by default (enable neo4j profile).
  • Build from source: Go 1.26 (docker/Dockerfile.app builder golang:1.26-bookworm), CGO (libsqlite3-dev), Node.js + npm, Python 3.10 + uv (docreader).
  • Kubernetes: >= 1.25.0 (helm/Chart.yaml).

Default ParadeDB images from v0.22.6-pg17 use x86 baseline x86-64-v2 (SSE4.2, POPCNT), not AVX2; see ParadeDB release notes for newer tags. Not all ARM CPUs or optional services are guaranteed compatible.

1. Standard Docker Compose (docker-compose.yml) ​

Fastest path:

bash
git clone https://github.com/Tencent/WeKnora.git && cd WeKnora
cp .env.example .env              # Edit required: DB_USER/DB_PASSWORD/DB_NAME, REDIS_PASSWORD, JWT_SECRET, SYSTEM_AES_KEY
make start-all                # Same as ./scripts/start_all.sh (pulls latest images by default)
# Or directly:
docker compose pull           # Images matching WEKNORA_VERSION
docker compose up -d
docker compose ps                 # Wait until healthy/running

JWT_SECRET and SYSTEM_AES_KEY in .env.example are empty—generate once on first deploy and store safely: JWT_SECRET with openssl rand -hex 32, SYSTEM_AES_KEY must be 32 bytes (openssl rand -hex 16). On upgrade, keep the same SYSTEM_AES_KEY or encrypted credentials cannot decrypt. Key roles: Configuration.

Stop with docker compose down (-v deletes volumes—use with care). make start-all wraps the same flow (scripts/start_all.sh, plus Ollama check, .env fallback, sandbox image pre-pull)—pick one.

Open http://localhost for the frontend (FRONTEND_PORT, default 80); first visit shows registration. Nginx proxies /api/ to the backend, so APIs use http://localhost/api/v1; port 8080 is also mapped—curl http://localhost:8080/health checks readiness.

Note: app uses env_file: [.env]; missing .env breaks compose parse. make docker-run / start_all.sh copies .env.example or touch .env.

Version upgrade ​

For an existing deploy with a newer release:

If the database is still ParadeDB v0.22.2-pg17, follow ParadeDB upgrade: stop writes, backup, keep the volume, change image, upgrade pg_search, then restore app. Image swap alone does not update extension SQL; migration 000099 handles GsKnora DB 0.22.2–0.22.5 when eligible—check other databases separately.

bash
# Set WEKNORA_VERSION in .env (e.g. 0.9.0) or keep latest
docker compose pull
docker compose up -d

docker compose up -d alone may reuse cached images and show a UI version mismatch with the downloaded release.

Core services (default) ​

ServiceImagePort (host:container)Depends onNotes
frontendwechatopenai/weknora-ui:${WEKNORA_VERSION:-latest}${FRONTEND_PORT:-80}:80app (healthy)Nginx SPA + proxy to app; APP_HOST/APP_BACKEND_PORT/APP_SCHEME for remote backend
appwechatopenai/weknora-app${APP_PORT:-8080}:8080postgres (healthy), redis, docreader (healthy)Go backend; mounts ./config/config.yaml, data-files; health GET /health
docreaderwechatopenai/weknora-docreaderexpose: 50051 only—gRPC parsing; grpc_health_probe; shares docreader-tmp with app for images
postgresparadedb/paradedb:v0.25.11-pg17not published to host—PostgreSQL 17 + BM25/vector; default retrieval
redisredis:7.0-alpinenot published—--appendonly yes --requirepass ${REDIS_PASSWORD}

Optional services and profiles ​

Enable with docker compose --profile <name> up -d:

profileServicesPortsPurpose
searxng (in full)searxng-init + searxng127.0.0.1:8888 (SEARXNG_BIND/SEARXNG_PORT)Self-hosted web search; loopback by default; rotate SEARXNG_SECRET before exposure
minio (in full)minio9000 (S3) / 9001 (console)S3 storage (STORAGE_TYPE=minio); default minioadmin/minioadmin
neo4j (in full)neo4j7474 / 7687Graph (NEO4J_ENABLE=true); default neo4j/password
qdrant (in full)qdrant6333 REST / 6334 gRPCVectors (RETRIEVE_DRIVER=qdrant)
milvusmilvus19530 / 9091Vectors (standalone, embedded etcd)
weaviateweaviate9035 HTTP / 50052 gRPCVectors
dorisdoris-fe + doris-be8030 / 9030 / 8040Apache Doris 4.1 (>= 3.0, HNSW ANN)
dex (in full)dex5556OIDC test IdP (misc/dex-config.yaml)
langfuse (in full)langfuse stack3000 UI / 9100–9101 MinIOSelf-hosted Langfuse; shares GsKnora postgres (langfuse DB) and redis (DB 1)
odl-hybridodl-hybridexpose 5002OpenDataLoader/Docling PDF hybrid (local build; DOCREADER_ODL_HYBRID)
fullsandbox, mcp, and services marked fullmcp ${MCP_PORT:-8082}:8000sandbox for build/pull only (command: ["true"]). Docker sandbox off by default—WEKNORA_SANDBOX_DOCKER_ENABLED=true + docker.sock (host root). Cube/E2B need no local daemon. mcp = MCP Server

Full app environment list (DB, vectors, storage, docreader, tenant, OIDC, etc.): 04-configuration.md.

2. Dev mode (docker-compose.dev.yml + scripts/dev.sh) ​

Dev compose runs infrastructure in containers (postgres, redis, docreader ports on host); app and frontend run on the host with hot reload:

bash
make dev-start          # ./scripts/dev.sh start; DEV_ARGS=--odl-hybrid / --minio / --qdrant / --neo4j / --dex / --full
make dev-app            # Go backend on host (DB_HOST/REDIS_ADDR → localhost)
make dev-frontend       # Vue dev server
make dev-logs / dev-status / dev-stop / dev-restart

Differences from production:

  • postgres 5432, redis 6379, docreader 50051 published for local processes;
  • optional single-node opensearch (9200) and dashboards (5601, profile opensearch-ui, security off);
  • dev.sh loads .env and .env.local (override); DEV_REMOTE_HOST for remote infra.

3. Image build (docker/) ​

DockerfileImageNotes
docker/Dockerfile.appwechatopenai/weknora-appThree stages: BrowserSkill bsk + Chrome extension (/opt/weknora/browserskill/, local browser); golang:1.26-bookworm build (make build-prod, WITH_ANYDOC=1, DuckDB ext); debian:12.12-slim runtime (migrate, python3/node/uvx, ffmpeg, gosu, licenses). Entry scripts/docker-entrypoint.sh: fix mount ownership; docker.sock GID group for appuser; run ./WeKnora as appuser. EXPOSE 8080
docker/Dockerfile.docreaderwechatopenai/weknora-docreaderPython 3.10 + uv; protobuf; LibreOffice, OpenJDK 17, antiword, Playwright webkit, grpc_health_probe. Lite build without PaddleOCR. Build args APT_MIRROR, PLAYWRIGHT_*
docker/Dockerfile.odl-hybridweknora-odl-hybrid:localopendataloader-pdf[hybrid], port 5002, default --no-ocr; local only
docker/Dockerfile.sandboxwechatopenai/weknora-sandboxAgent sandbox: Python 3.12-slim + Node 20; targets sandbox, cube, desktop; see Sandbox deployment
frontend/Dockerfilewechatopenai/weknora-uiMulti-stage Node 24 build + pinned nginx:1.30.3-alpine; no host dist/ required

Build all from source:

bash
make build-images        # ./scripts/build_images.sh --app/--docreader/--frontend/--sandbox/--clean
make docker-build-app
make docker-build-docreader
make docker-build-frontend

For docreader behind mirrors:

bash
APT_MIRROR=https://your-apt-mirror.example.com \
PLAYWRIGHT_WEBKIT_DOWNLOAD_HOST=https://your-playwright-mirror.example.com \
./scripts/build_images.sh --docreader

APT_MIRROR must preserve /debian and /debian-security layout; Playwright mirrors must preserve artifact paths. PLAYWRIGHT_WEBKIT_DOWNLOAD_HOST overrides PLAYWRIGHT_DOWNLOAD_HOST for WebKit.

4. Makefile deployment targets ​

TargetPurpose
make start-all / stop-allscripts/start_all.sh full stack (Ollama check, .env, sandbox pull)
make start-ollama / start-dockerOllama only / Docker only
make docker-run / docker-stop / docker-restartcompose up/down/restart (.env fallback)
make build-images* / clean-images / pull-imagesBuild / clean / pull
make check-env / list-containers / show-platformEnv check / containers / amd64
make migrate-*DB migrations (AUTO_MIGRATE=true in container)
make dev-*Dev mode
make build / run / build-prodLocal cmd/server
make build-lite / run-lite / package-liteLite (.env.lite)
make package-mac-appmacOS desktop bundle
make docs / install-swaggerSwagger at :8080/swagger (debug only)
make clean-dbDelete postgres/minio/redis volumes (destructive)

5. scripts/ helpers ​

ScriptRole
scripts/start_all.shOne-shot start/stop; compose v1/v2 detect; PLATFORM; sandbox pre-pull
scripts/dev.shDev orchestration
scripts/check-env.shRequired .env and toolchain
scripts/build_images.shVersioned image build, multi-arch
scripts/build_frontend_dist.shHost frontend/dist for Lite/desktop
scripts/migrate.shgolang-migrate wrapper
scripts/docker-entrypoint.shApp container entry
scripts/package-lite.sh / package-mac-app.shLite tarball / macOS .app

6. Helm (helm/) ​

helm/Chart.yaml: apiVersion v2, name weknora, appVersion e.g. v0.9.0, Kubernetes >= 1.25.0.

Chart: app, frontend, docreader, postgresql (default ParadeDB v0.18.9-pg17, differs from Compose), redis; optional minio, neo4j.

Key helm/values.yaml:

yaml
app:
  replicaCount: 1
  env:
    GIN_MODE: release
    RETRIEVE_DRIVER: postgres      # postgres / elasticsearch_v7 / elasticsearch_v8 / qdrant ...
    STORAGE_TYPE: local            # local / minio / cos / tos / s3
    STREAM_MANAGER_TYPE: redis
postgresql:
  enabled: true
  persistence: { enabled: true, size: 10Gi }
redis:
  enabled: true
  persistence: { enabled: true, size: 1Gi }
dataFiles:
  persistence: { enabled: true, size: 10Gi }
global:
  maxFileSizeMB: 50                 # Upload limit (frontend / app / docreader)
secrets:                            # Required, or existingSecret
  dbPassword: ""
  redisPassword: ""
  jwtSecret: ""
  systemAesKey: ""                  # 32-byte AES-256 master key

global.maxFileSizeMB matches Compose MAX_FILE_SIZE_MB. Optional MinIO image: community pgsty/minio.

bash
helm install weknora ./helm -n weknora --create-namespace \
  --set secrets.dbPassword=xxx --set secrets.redisPassword=xxx \
  --set secrets.jwtSecret=xxx --set secrets.systemAesKey=$(openssl rand -hex 16)

7. Desktop (Lite / desktop app) ​

Same Lite runtime (single process + SQLite + in-memory queue); distribution differs: binary (CLI/background) vs desktop app (GUI). Knowledge-base features match; skip registration, local sandbox, and project bind only in the desktop app.

Lite runtime (zero external deps) ​

Compile EDITION=lite + runtime .env.lite:

  • DB: DB_DRIVER=sqlite, DB_PATH=./data/weknora.db, -tags "sqlite_fts5";
  • Retrieval: RETRIEVE_DRIVER=sqlite, FTS5 + sqlite-vec, no vector DB;
  • Queue/streams: STREAM_MANAGER_TYPE=memory; Asynq in-memory/no-op;
  • Frontend: make build-lite copies frontend/dist to web/; served via WEKNORA_WEB_DIR / embedded static;
  • Docreader: optional DOCREADER_ADDR=127.0.0.1:50051;
  • Sandbox: configure per workspace in settings (Docker, CubeSandbox, E2B); desktop uses OS sandbox when no remote sandbox—Desktop client.
bash
cp .env.lite.example .env.lite      # SYSTEM_AES_KEY (openssl rand -hex 16) and JWT_SECRET
make run-lite
make package-lite

Browser access to the binary still requires register/login. Desktop app uses native bridge + POST /auth/auto-setup (no anonymous HTTP).

Desktop app (cmd/desktop, Wails v2) ​

GUI, embedded backend/SQLite, app data directory, port/LAN/update settings. Same runtime as Lite runtime.

Not officially released

No release installers yet—build locally. release-lite.yml has cross-platform jobs but tag trigger is disabled; latest release has no artifacts.

  • Entry cmd/desktop/main.go, wails.json; app.go exposes GetAPIBaseURL, port, LAN bind, CheckForUpdates.
  • scripts/package-mac-app.sh: frontend → web/, wails build -tags "sqlite_fts5", .app with embedded config/migrations/web; data under ~/Library/Application Support/WeKnora Lite/data/.
bash
make package-mac-app

8. Build and run from source ​

bash
# Backend (needs local postgres/redis/docreader — dev mode)
go mod download
make build && ./WeKnora                       # or make build-prod

# Frontend
cd frontend && npm ci && npm run dev

# docreader
cd docreader && uv sync --locked && bash scripts/generate_proto.sh && uv run -m docreader.main

Config search order (LoadConfig): cwd → ./config → $HOME/.appname → /etc/appname/, file config.yaml.

Optional embedded frontend (standard edition) ​

Standard edition serves API only by default. Set WEKNORA_WEB_DIR to a built frontend directory (must contain index.html) to serve Web UI from the same process:

bash
(cd frontend && npm ci && npm run build)
make build-prod
SERVER_HOST=127.0.0.1 WEKNORA_WEB_DIR="$PWD/frontend/dist" ./WeKnora

Visit http://127.0.0.1:8080 (default SERVER_PORT). Only static build output in WEKNORA_WEB_DIR—no secrets. API routes (including /mcp/) take precedence over SPA fallback.

This does not replace DB/Redis dependencies. For minimal no-Docker deploy, see Lite runtime.

Common topologies ​

Next steps ​

After deploy, read 03-quickstart.md for setup and first Q&A.