Install the Navin Platform on an air-gapped site
This page installs the Navin Platform on a site without Internet access. Everything comes from internal sources:
the signed release bundle, the signed package repositories (apt, dnf, pacman) or the offline archives of
navin-install, a Harbor registry mirroring the images and charts, and the model weights copied on a volume. It is
done by the release manager (connected side) and the platform engineer (isolated side).
Before you begin
- A connected machine to build and sign the bundle, with the tools of
tools/release/fetch-tools.sh,tools/oci/fetch.shandtools/components/fetch-syft.sh(versions pinned, sha256 verified). - A removable medium or a transfer zone approved by the security team.
- On the isolated site: a Harbor registry, an internal package repository server (HTTPS), and the installation method chosen (OS packages or Kubernetes with Helm).
Steps
-
Build, check and sign the bundle (connected side). The bundle holds the packaged chart, the rendered manifests, the SQL migrations, the offline documentation, the Python wheels, the SDK packages, the packs, the SBOM and the licence notices.
bash tools/release/build.shbash tools/release/verify-reproducible.shbash tools/release/sign.shExpected result:
verify-reproducible.shprintscompared <n> artefacts, 0 differences;sign.shwrites the SBOM, the Cosign signatures and the Trivy verdictscans/gate.json.If it fails:
sign.shstops on a HIGH or CRITICAL Trivy finding thattools/release/trivy-exceptions.yamldoes not justify; fix the image or justify the finding (id,justification,owner).warningsign.shcreates a test key pair under/tmp/eai-release-keys(EAI_SIGN_KEY_DIR). In production, sign with the key of the client, held in an HSM or in OpenBao. -
Prepare the package repositories (connected side, OS packages). Download the release, check it and publish the signed repositories; build the offline archives of
navin-installper family.python3 os/release.py file navin-<version>os/repo.sh --sign <key-id> --url https://<repo-host>os/build.sh install-archive<key-id>: GPG key of the release manager (RSA 4096, kept offline or in an HSM; the script never creates one).os/release.py fileremoves fromos/<package>/<family>/the packages of another version (an earlier build or release): the signed repositories hold the downloaded release alone.Expected result:
os/repo/holdsapt/,rhel/andarch/with the client filesnavin.sources,navin.repoandnavin.conf;os/dist/holdsnavin-install-<version>-<family>.tar.gzand its.sha256. -
Mirror the images and the charts (connected side, Kubernetes). List the images of the rendered manifests and of the operators, copy them to Harbor, verify the upstream signatures and sign them again with the internal key.
helm template eai deploy/helm/enterprise-ai -f deploy/helm/enterprise-ai/values-prod.yaml | grep 'image:' | sort -uskopeo copy --all docker://<image>:<tag> docker://<harbor-host>/mirror/<image>:<tag>helm pull <chart> --version <version>helm push <chart>-<version>.tgz oci://<harbor-host>/chartsThen set
global.imageRegistry(Helm),helm_repository_mirror(Terraform) and replacerepoindeploy/argocd/applicationset.yamlby the Harbor chart project (already allowed by the AppProject).Expected result: every image of the rendered manifests is under
<harbor-host>/eai/or<harbor-host>/mirror/.If it fails: the Kyverno policy
eai-image-provenancerefuses any image outside those projects that is not referenced by digest. -
Copy the model weights. vLLM pods run with
HF_HUB_OFFLINE=1: they never download. Copy the weights on the model cache volume (vllm.modelCache), or restore the Ollama store from a validated volume (ollama.preloadModelsempty,ollama.registryCIDRsempty). -
Transfer, then verify on the isolated site.
bash tools/release/verify.sh <bundle-folder>bash tools/release/verify.sh --integrity-only <bundle-folder>The first command checks the sha256, the signatures, the SBOM and the Trivy verdict; the second only the integrity. Give the public key received by another channel as the second argument for an independent check.
Expected result: the script ends without error.
If it fails: do not install; a signature or a checksum that differs means the bundle changed in transit.
-
Close every outbound flow. Leave
networkSecurity.providerFQDNsempty, or setnetworkSecurity.providerEgress.controlPlaneand.litellmtofalse, and do not enable anyeai.io/provider-*label: only the local models stay available. -
Install. Follow the page of your method with the internal sources: OS packages (repository files of step 2, or
navin-installfrom the offline archive) or Kubernetes with Helm (Harbor of step 3, the chart of the bundlecharts/enterprise-ai-<version>.tgz).
Verify
The proof of an installation without network runs in an empty network namespace:
bash tools/release/airgap-check.sh /tmp/eai-release/<version> /tmp/eai-airgap/bundle.tar release/airgap/<date>.json
It checks that a TCP connection to the Internet and a DNS resolution fail, then verifies the bundle, the mirror of
the Navin Manager, installs the wheels with pip --no-index, renders the chart and extracts the migrations. Then
follow Verify the installation.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
apt update reports NO_PUBKEY | Keyring not installed | Copy navin-archive-keyring.gpg to /usr/share/keyrings/ |
dnf reports a GPG check failure | RPM-GPG-KEY-navin not reachable at gpgkey | Publish the key next to repodata/ |
| A vLLM pod restarts while loading | Weights missing from the cache | Copy the weights on the volume; raise vllm.startupFailureThreshold for large models |
| Kyverno refuses a mirrored image | Image not signed with the internal key | Sign it again in Harbor |
More details: Client installation handbook.