Configuration reference
Questi contenuti non sono ancora disponibili nella tua lingua.
The engine is configured entirely through environment variables, and it validates them at boot: a malformed value fails loudly with the variable’s name rather than quietly falling back to a default. If it starts, the config it read is the config you meant.
Most of what follows is optional. Two variables are not. A third is not if a browser embeds the widget.
The minimum
Section titled “The minimum”MONGO_CONNECTION_STRING=mongodb://user:password@host:27017/cap_importIMPORT_LICENSE_PUBLIC_KEY=<from the Self-hosting page of your account>ALLOWED_ORIGINS=https://app.example.com # required to embed the widget; skip for API-onlyThat is a working engine — in-memory blob storage, no decode sidecars, everything else at its default. Add storage and sidecars as you need them.
| Variable | Default | What it does |
|---|---|---|
MONGO_CONNECTION_STRING |
— | Required. Connection string for MongoDB — or for FerretDB, a verified experimental backend. The database name comes from the URI path. Missing this is a crash at boot, not a warning. |
IMPORT_LICENSE_PUBLIC_KEY |
— | Required. The public key licenses are verified against, base64-encoded PEM. Never a secret. Missing this is 403/503 on every import. |
PORT |
8090 |
HTTP port for the API. |
ALLOWED_ORIGINS |
— | Comma-separated browser origins allowed to call the API. The production image refuses all cross-origin browser calls when this is empty — including localhost. Required if you embed the widget; skip only for server-to-server callers. |
Blob storage
Section titled “Blob storage”Large files stream to object storage rather than living in memory. Compose defaults to
memory so docker compose up works as a first look. The Helm chart defaults to s3
because a cluster pod that loses files on every restart is not a deploy — you must set the
bucket (and endpoint / credentials, or IRSA) or helm test fails. Empty S3 credentials with
backend=s3 is a misconfiguration, not a working default.
| Variable | Default | What it does |
|---|---|---|
UNP_BLOB_BACKEND |
memory |
memory for dev and smoke tests, s3 for production. |
S3_ENDPOINT |
— | S3 or MinIO endpoint. Required when the backend is s3. |
S3_BUCKET |
— | Bucket name. Required when the backend is s3. |
S3_REGION |
us-east-1 |
Region. |
S3_ACCESS_KEY_ID |
— | Access key id. |
S3_SECRET_ACCESS_KEY |
— | Secret access key. |
S3_FORCE_PATH_STYLE |
— | Set true for MinIO and most S3-compatible stores that need path-style. |
memory keeps uploads in the process, so they vanish on restart and cap out at whatever RAM
you gave the container. Use it to prove the wiring works, then switch.
Decode sidecars
Section titled “Decode sidecars”Each sidecar handles one family of file formats. Leave a URL unset and the engine simply declines those files — it degrades rather than breaks.
| Variable | Default | What it does |
|---|---|---|
UNP_PDF_PROBE_URL |
— | PDF table extraction. Unset: PDFs are not accepted. |
UNP_XLSX_DECODE_URL |
— | Spreadsheet decoding. Unset: XLSX files are not accepted. |
UNP_OCR_URL |
— | Scans and photos. Unset: image files are not accepted. |
UNP_EMBED_URL |
— | Semantic-matching support pass. Unset: the feature is off. |
Running the all-in-one image? The three decode sidecars (PDF, spreadsheets, scans) are
wired internally — you can ignore those three URLs. Semantic matching still needs
UNP_EMBED_URL pointing at a reachable embed service; leave it unset and that pass
stays off.
Licensing
Section titled “Licensing”| Variable | Default | What it does |
|---|---|---|
IMPORT_LICENSE_REVOKED_IDS |
— | Comma-separated license ids to refuse, even if otherwise valid. |
IMPORT_LICENSE_DEVELOPMENT_MODE |
false |
Accepts any non-empty key as a synthetic dev license. Never set in production. |
Development mode exists so you can run the engine before you have a key. It is ignored the
moment IMPORT_LICENSE_PUBLIC_KEY is set, and the preflight flags it — so it cannot quietly
survive into a real deployment.
Behaviour and limits
Section titled “Behaviour and limits”| Variable | Default | What it does |
|---|---|---|
ALLOWED_ORIGINS |
— | Comma-separated browser origins allowed to call the API. Unset in production refuses cross-origin calls. Also listed under The minimum — do not skip it if you embed the widget. |
THROTTLE_IMPORT_LIMIT |
2000 |
Global requests-per-minute ceiling. Per-tenant limits come from the license itself. |
IMPORT_INGEST_JOB_CONCURRENCY |
2 |
How many uploads parse at once. Large files peak at several hundred MB each. |
IMPORT_INGEST_LEASE_SECONDS |
600 |
How long a parsing job may run before it is considered stalled and re-queued. |
IMPORT_DATASET_FETCH_HOST_ALLOWLIST |
— | Host suffixes allowed for reference-dataset fetches. Empty leaves only the built-in guard. |
UNP_EVENT_SINK_BACKEND |
noop |
noop for self-hosting. The alternative is for our hosted deployment. |
The concurrency cap is about memory, not throughput: raising it multiplies peak RAM per pod. It is only worth raising once you have measured your own file sizes and have the headroom to match.
Observability
Section titled “Observability”| Variable | Default | What it does |
|---|---|---|
IMPORT_METRICS_PORT |
0 |
Prometheus /metrics on a separate internal port. 0 disables it. Never expose it publicly. |
Metrics deliberately live on their own listener so you can expose them to your monitoring stack without widening the public API surface.
Not environment variables
Section titled “Not environment variables”Some things are configured elsewhere on purpose:
- AI settings live in the engine’s database, not in env vars — provider, endpoint, model and the encrypted API key are set once at runtime. Configure nothing and the importer stays fully deterministic.
- Tuning constants — matching thresholds, sidecar timeouts, webhook retry schedules and retention windows — are fixed in the release rather than operator-configurable. They change through upgrades, so behaviour stays reproducible between deployments running the same tag.
Check before you go live
Section titled “Check before you go live”pnpm import:self-host-check # from a source checkoutdocker run --rm --env-file .env ghcr.io/capitality-io/mildport-aio \ bun dist/cli/self-host-check.js # from the imageIt reports the resolved licensing, Mongo, CORS, storage, sidecar and metering setup, and exits
non-zero on anything blocking — no Mongo URI, no public key with development mode off, s3
selected without a bucket. Empty ALLOWED_ORIGINS in production is a warning (the widget will
fail CORS; API-only deploys are valid). On Kubernetes, helm test mildport runs the same
check in-cluster.
Next: Licensing · FerretDB (experimental) · Air-gapped deployment