Skip to content

mlimarenko/IronRAG.BookStack

Repository files navigation

IronRAG ↔ BookStack connector

Sync a BookStack wiki into IronRAG: periodic polling + webhook intake, multimodal (pages + attachments + images).

Release License Docker pulls Python


Built on the IronRAG Connector Template — this repo only owns BookStack-specific code (REST client, markdown image collector, shelf reverse index, webhook verifier).

What it pushes into IronRAG

kind external key source
page bookstack:page:<id> /api/pages/{id}/export/markdown
attachment bookstack:attachment:<id> /api/attachments/{id} (base64 decoded)
image bookstack:image:<sha256-prefix-16> inline <img> URLs in page markdown (content-addressed dedup)

Pages, attachments, and inline images all carry their original BookStack URL via document_hint, which IronRAG surfaces in MCP citations.

Page attachments and inline images now ingest as attached context of their source page instead of as peer documents. Each dependent is auto-linked to its page via the framework's parent_external_key; no config change is required.

Sync loop runs every SYNC_INTERVAL_SECONDS (default 1800s) and ships only the diff: pages whose updated_at advanced since the last successful push. Webhook endpoint /webhook/bookstack (HMAC-SHA256 + admin bearer) routes through the same orchestrator.

Full sweeps collect routing facts from the /api/pages summary first. The connector fetches full page context and refreshes the shelf index only when routing.yaml rules require facts that are missing from the summary, such as shelf or tag matches.

Quick start (Docker)

docker run -d \
    --name ironrag-bookstack \
    --env-file .env.local \
    -v $(pwd)/routing.yaml:/app/routing.yaml:ro \
    -v ironrag_bookstack_state:/var/lib/ironrag-connector \
    -p 8088:8088 \
    pipingspace/ironrag.bookstack:latest

Minimal .env.local:

BOOKSTACK_BASE_URL=https://wiki.example.com
BOOKSTACK_TOKEN_ID=...
BOOKSTACK_TOKEN_SECRET=...
BOOKSTACK_WEBHOOK_SECRET=...
IRONRAG_BASE_URL=https://ironrag.example.com
IRONRAG_API_TOKEN=...
ADMIN_BEARER_TOKEN=...
RUN_MODE=both

routing.yaml (human-readable IronRAG catalog reference):

default:
  library: knowledge/wiki

policies:
  page:       { on_missing: delete }
  attachment: { on_missing: delete }
  image:      { on_missing: ignore }   # content-addressed; may be shared across pages

Routing targets use the same canonical <workspace-slug>/<library-slug> references shown by IronRAG and its MCP catalog. UUID targets and a separate workspace field are not accepted. Rules can route one connector instance to multiple libraries or workspaces; see routing.yaml.example for the complete schema, every supported policy value, and the exact BookStack facts and kinds available to match.

Quick start (dev)

git clone git@github.com:mlimarenko/IronRAG.BookStack.git
cd IronRAG.BookStack
cp .env.example .env.local            # fill in BookStack + IronRAG creds
cp routing.yaml.example routing.yaml

uv sync --all-extras
uv run pytest
uv run bookstack-connector

Operational notes

  • See docs/ARCHITECTURE.md for the page → external_key mapping and failure modes.
  • Manual sweep trigger: curl -X POST http://localhost:8088/sync/run -H "Authorization: Bearer $ADMIN_BEARER_TOKEN".
  • First sweep against a library that already contains BookStack docs: optionally run uv run python -m bookstack_connector.seed_cursor once to populate the SQLite cursor from existing IronRAG documents (avoids re-uploading on first pass).
  • OPERATION_POLL_INTERVAL_SECONDS / OPERATION_POLL_BUDGET_SECONDS tune how the framework polls asynchronous IronRAG mutations (revisions and deletes hand back an operation that is polled to a terminal state). A poll-budget timeout leaves the cursor on the previous source version so the next sweep retries instead of marking the version as handled.
  • REWALK_CONCURRENCY bounds the fan-out of a post-upgrade full re-walk of IronRAG documents; keep it within the BookStack instance's rate limit.
  • REAPER_LIST_TIMEOUT_SECONDS bounds post-sweep IronRAG document-list requests so cleanup cannot hold the manual sync request after source enumeration has finished.

Deploy with Docker Compose

cp .env.example .env.local             # BOOKSTACK_* + IRONRAG_* + ADMIN_BEARER_TOKEN
cp routing.yaml.example routing.yaml   # map shelves/books → workspace/library refs
docker compose up -d
docker compose logs -f

docker-compose.yml pulls the released image, mounts routing.yaml read-only, and persists the SQLite cursor in a named volume. With the default RUN_MODE=both it also serves /webhook/bookstack on port 8088 (published on localhost) — front it with a TLS reverse proxy for public delivery.

Related

License

MIT — see LICENSE.

About

A connector between BookStack and IronRAG for updating and automatically populating the agent database

Resources

Stars

1 star

Watchers

0 watching

Forks

Packages

 
 
 

Contributors