Zum Inhalt springen
Loslegen

Air-gapped deployment

Dieser Inhalt ist noch nicht in deiner Sprache verfügbar.

Mildport is built to run with zero egress. Licenses verify offline, your data stays in your stores, and the decode sidecars run beside the engine — so a network with no route to the internet is a supported deployment, not a workaround.

Three things will reach out if you let them. Close all three and nothing else phones home.

An honest inventory of every outbound surface:

Surface Default In an air-gap
License check verified locally against your public key ✅ no egress — nothing to configure
Database and blob storage your stores ✅ in your network
Decode sidecars (PDF/XLSX/OCR) services beside the engine ✅ no egress
Container images pulled from our registry ⚠️ mirror them (below)
PDF viewer worker loaded from a public CDN by the widget ⚠️ serve it yourself (below)
AI assist off — the importer is deterministic ⚠️ leave off, or point at a model inside your network
Reference datasets off; fetched only from URLs you pass in ⚠️ pass in-network URLs only
Metering and billing off for self-hosted deployments ✅ never contacted
Telemetry none ✅ the engine has none

Pull on a connected machine, push to your internal registry. The all-in-one image is the smallest footprint — engine and the three decode sidecars in one container. Semantic matching is a separate image; mirror it too if you want that pass:

Terminal window
docker pull ghcr.io/capitality-io/mildport-aio:<tag>
docker tag ghcr.io/capitality-io/mildport-aio:<tag> registry.internal.example/mildport-aio:<tag>
docker push registry.internal.example/mildport-aio:<tag>
# optional — semantic matching
docker pull ghcr.io/capitality-io/mildport-embed:<tag>
docker tag ghcr.io/capitality-io/mildport-embed:<tag> registry.internal.example/mildport-embed:<tag>
docker push registry.internal.example/mildport-embed:<tag>

Prefer to scale every sidecar independently? Mirror the five-image set instead:

Terminal window
for img in mildport mildport-pdf-probe mildport-xlsx-decode mildport-ocr mildport-embed; do
docker pull ghcr.io/capitality-io/$img:<tag>
docker tag ghcr.io/capitality-io/$img:<tag> registry.internal.example/$img:<tag>
docker push registry.internal.example/$img:<tag>
done

Skip the sidecars you won’t use — pdf-probe and ocr if you never import PDFs or scans, xlsx-decode if you never import spreadsheets, embed if you don’t want semantic matching — and turn them off in your values. MongoDB and S3-compatible storage are yours; mirror or reuse what you already run. If the estate is already Postgres, FerretDB is a verified experimental option.

values.airgap.yaml
image:
repository: registry.internal.example/mildport
tag: '<tag>'
imagePullSecrets:
- name: internal-registry
sidecars:
pdfProbe: { image: { repository: registry.internal.example/mildport-pdf-probe, tag: '<tag>' } }
xlsxDecode:
{ image: { repository: registry.internal.example/mildport-xlsx-decode, tag: '<tag>' } }
ocr: { image: { repository: registry.internal.example/mildport-ocr, tag: '<tag>' } }
embed: { image: { repository: registry.internal.example/mildport-embed, tag: '<tag>' } }
existingSecret: mildport-secrets # IMPORT_LICENSE_PUBLIC_KEY, MONGO_CONNECTION_STRING, S3_*
blob:
backend: s3
s3:
endpoint: 'https://minio.storage.svc:9000'
bucket: mildport
region: us-east-1
Terminal window
helm install mildport oci://ghcr.io/capitality-io/charts/mildport \
-n mildport --create-namespace -f values.airgap.yaml
helm test mildport -n mildport # runs the preflight in-cluster

Mirror the chart itself the same way if your cluster cannot reach ghcr.io at install time.

This is the one frontend gotcha. The widget loads the PDF viewer’s worker from a version-matched public CDN, which fails in an air-gap. Point it at your own copy before you define the element:

import { configurePdfWorker, defineImportSuiteElement } from '@capitality-io/mildport-widget';
configurePdfWorker('/assets/pdf.worker.min.mjs'); // same-origin copy
await defineImportSuiteElement();

Copy pdf.worker.min.mjs from the pdfjs-dist package into your app’s static assets; its version must match the one the widget ships with. If you only import CSV, XLSX or JSON and never show the PDF preview, this does not apply to you.

Directive Allow
connect-src your Mildport API origin only
worker-src 'self' (or your asset origin) — not a CDN
script-src your app origins — the widget ships in your bundle

The importer is deterministic by default and makes no model calls. If you want AI assist, point it at a model that runs inside your network — never a public API. AI settings live in the engine’s database rather than environment variables, so you configure them once at runtime from inside the cluster. Configure nothing and the importer stays fully deterministic, with zero egress.

  • helm test mildport — the preflight passes with an offline license, your storage, and your event sink.
  • Add a NetworkPolicy that denies egress except to your database, your object storage, and (if used) your in-network model endpoint. The pods should need nothing else.
  • Watch the browser’s network tab on the first PDF preview. If you see a CDN request, the worker above is not yet pointed at your own copy.

Re-mirror the new tags, bump the image tags in your values, re-copy the PDF worker if the widget’s version changed, then helm upgrade. Your license keeps working across upgrades — it is verified locally, so nothing needs to be re-fetched or re-activated.

Next: Configuration reference · Licensing