Self-hosted document search and grounded answers for teams and AI agents.
curl -fsSL https://raw.githubusercontent.com/mlimarenko/IronRAG/master/install.sh | bashOr from source:
git clone https://github.com/mlimarenko/IronRAG.git
cd IronRAG
# First start only: the API and workers refuse to start without a credential
# master key, and .env.example ships it empty. Add
# IRONRAG_AI_PROVIDER_API_KEYS_JSON_B64 to the same file.
if [ ! -f .env ]; then
sed "s|^IRONRAG_CREDENTIAL_MASTER_KEY=.*|IRONRAG_CREDENTIAL_MASTER_KEY=$(openssl rand -base64 32)|" \
.env.example > .env
fi
docker compose up -dThe install.sh wizard writes such a key for a fresh .env on its own. Never
overwrite an existing .env, and never regenerate its key while the deployment's
PostgreSQL volume persists: the stored credentials would stay undecryptable. To
change the port, resource profile, provider keys or bootstrap admin on an
existing install, re-run install.sh, which keeps the stored secrets.
Open http://127.0.0.1:19000, create an admin account, upload a document, and ask a question.
Wizard details, non-interactive CI installs, provider keys, and telemetry: docs/en/INSTALL.md · docs/ru/INSTALL.md
- Self-hosted runtime — Docker Compose (PostgreSQL + pgvector, Redis, backend, worker, frontend) or Helm on Kubernetes; data stays on your servers
- Typed knowledge graph — entities, typed relations, and chunk-level citations; hybrid retrieval across vector, lexical, graph, and technical-fact lanes
- Native MCP server — 23 tools for documents, graph, web ingest, and grounded
grounded_answer; works with Claude Desktop / Code, Cursor, Codex, VS Code (Continue / Cline / Roo), Zed, OpenClaw, Hermes, and custom HTTP MCP clients - Provider-agnostic AI — OpenAI, DeepSeek, Qwen / DashScope, GPTunnel, OpenRouter, RouterAI, MiniMax, Ollama, LiteLLM / OpenAI-compatible gateways; eight binding purposes (
extract_text,extract_graph,graph_entity_type,embed_chunk,query_compile,query_rerank,query_answer,agent) with per-currency cost rollups in the UI - Code-aware + CPU-first ingest — 15-language tree-sitter AST; JSON / YAML / TOML / CSV / XLSX parsers; technical facts (paths, endpoints, env vars, error codes); Docling CPU OCR for PDF / DOCX / PPTX without a GPU
- Multi-tenant IAM — principals, scoped tokens (system / workspace / library), permission groups, audit log
- Durable ops — restart-safe document jobs with page-range checkpoints; durable assistant turns that recover after stream drops; streaming
tar.zstbackup / restore - Pluggable connectors — BookStack, Confluence, YouTrack, Git repos, or build your own; see connectors/. They live in this repository and ship on this version (poll + webhook intake)
Put provider keys in IRONRAG_AI_PROVIDER_API_KEYS_JSON_B64 and keep
IRONRAG_CREDENTIAL_MASTER_KEY set (generated by install.sh on fresh installs).
Then bind models under Admin → AI → Bindings.
- Provider catalog and binding purposes → AI-BINDINGS.md
- Credential encryption and key rotation → CREDENTIAL-ENCRYPTION.md
- Ingest — files, web, API / MCP → recognition → structured chunks → PostgreSQL
- Build memory — embeddings, technical facts, entities and typed relations
- Query — hybrid retrieval (vector, lexical, graph, facts) → grounded answer with citations
- Route providers — each LLM stage uses its binding; switch models without rewriting the pipeline
Deep dive: docs/en/PIPELINE.md · docs/en/README.md
| Topic | English | Russian |
|---|---|---|
| Install & bootstrap | INSTALL.md | INSTALL.md |
| Architecture | README.md | README.md |
| Pipeline | PIPELINE.md | PIPELINE.md |
| MCP | MCP.md | MCP.md |
| AI bindings | AI-BINDINGS.md | AI-BINDINGS.md |
| Credential encryption | CREDENTIAL-ENCRYPTION.md | CREDENTIAL-ENCRYPTION.md |
| Capacity & Compose / Helm | CAPACITY-PLANNING.md | CAPACITY-PLANNING.md |
| IAM | IAM.md | IAM.md |
| Changelog | CHANGELOG.md | — |
More topics (CLI, frontend, webhooks, benchmarks, Ollama) live under docs/en/ and docs/ru/.
Vector dimension is a property of a library, not a constant of the product.
It comes from the active EmbedChunk/EmbedQuestion binding. Do not add a
product-wide const VECTOR_DIM. PostgreSQL shards
(knowledge_chunk_vector_d{dim}, knowledge_entity_vector_d{dim}) are created
and configured through infra/postgres/pg_vector_config.rs in both the search
store and snapshot restore, including constraints on existing shards. Changing
dimension requires re-embedding into a new shard. Test vector storage with at
least two dimensions.
No hardcoded user-facing strings in apps/web/. Every visible text is
t('namespace.key'), with the key present in both locales
(shared/i18n/ru.json, en.json). Interpolating values is fine; the template
lives in the locale file. make frontend-i18n-audit (part of frontend-check)
walks the TypeScript AST and understands dynamic keys and plural forms.
The audit rejects defaultValue on static keys: translations belong in the
locale files. Dynamic keys may use an API-produced runtime token as a fallback.
A change to the answer pipeline is verified through both channels. The
built-in assistant is an MCP-client-shaped agent over the same tool surface an
external MCP client gets, and grounded_answer stays the one high-level
grounded-answer tool — the contract is apps/api/tests/MCP_PARITY.md. After a
change in retrieve, answer or the MCP tools, run the regression through the UI
and through an external MCP client. One channel healthy and the other
degraded is not a release; a tool reachable only from the UI is a defect.
CLI— maintenance commands and schema rollout.INSTALL,PIPELINE, andAI-BINDINGS— setup and runtime behavior.CHANGELOG— release changes.
-
Your own database on your own port. The default in
apps/api/src/app/config/loading.rsispostgres://postgres:postgres@127.0.0.1:5432/ironrag, andTempPostgresDatabasestarts withdrop database if exists. PointIRONRAG_DATABASE_URLat a PostgreSQL you own — settings are read with theIRONRAG_prefix, and a bareDATABASE_URLis ignored. -
Integration tests are one crate,
apps/api/tests/it, not a set of binaries. The required suites areBACKEND_INTEGRATION_SUITESin theMakefile, and a full run needs--all-targets— without it the binaries undertests/are skipped along with their compliance gates. -
The criterion is the
N passedline, not the exit code. A suite with no matching test printstest result: ok. 0 passedand exits zero. Some tests sit behind#[cfg(feature = "test-support")], so a run without--features test-supportproduces an empty green binary. -
A wedged ingest queue looks like ordinary load. A poisoned job (a terminal
ops_async_operationbehind a claimableingest_job) holdsleasedrows, and those count againstingestion_max_parallel_jobs_per_library. The tell is the samejob_idin "claimed ingest job" dozens of times in a row and no other. Check with:select j.queue_state, o.status, count(*) from ingest_job j left join ops_async_operation o on o.id = j.async_operation_id where j.queue_state in ('queued', 'leased') group by 1, 2;
The poisoned ones are those whose
o.statusis terminal. -
CI checks merge requests and protected default-branch pushes. Migration checks and ops self-tests run in both. Protected default pushes build backend, frontend, Confluence, YouTrack and BookStack images; backend and BookStack have separate image security gates. Other local checks use the Make targets.
-
Release publication is opt-in. Set the pipeline input
release=trueand run the manualreleasejob on a protected default-branch push. It requires the version, four deployed image producers, migration/ops checks and both image security gates.release-bumpselects patch (default), minor or major.release:promoteverifies reservation and source identity, promotes the four deployed image digests and publishes the GitLab release;deploy:gitopsfollows. BookStack is built separately from that four-image promotion set. Schema-rollout fences guard release, promotion and GitOps deployment. -
A snapshot import answers
202. The terminal status lives inGET /v1/ops/operations/{id};curl --failis green on an operation that failed afterwards.


