Skip to main content

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.sh and tools/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​

  1. 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.sh
    bash tools/release/verify-reproducible.sh
    bash tools/release/sign.sh

    Expected result: verify-reproducible.sh prints compared <n> artefacts, 0 differences; sign.sh writes the SBOM, the Cosign signatures and the Trivy verdict scans/gate.json.

    If it fails: sign.sh stops on a HIGH or CRITICAL Trivy finding that tools/release/trivy-exceptions.yaml does not justify; fix the image or justify the finding (id, justification, owner).

    warning

    sign.sh creates 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.

  2. Prepare the package repositories (connected side, OS packages). Download the release, check it and publish the signed repositories; build the offline archives of navin-install per 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 file removes from os/<package>/<family>/ the packages of another version (an earlier build or release): the signed repositories hold the downloaded release alone.

    Expected result: os/repo/ holds apt/, rhel/ and arch/ with the client files navin.sources, navin.repo and navin.conf; os/dist/ holds navin-install-<version>-<family>.tar.gz and its .sha256.

  3. 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 -u
    skopeo copy --all docker://<image>:<tag> docker://<harbor-host>/mirror/<image>:<tag>
    helm pull <chart> --version <version>
    helm push <chart>-<version>.tgz oci://<harbor-host>/charts

    Then set global.imageRegistry (Helm), helm_repository_mirror (Terraform) and replace repo in deploy/argocd/applicationset.yaml by 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-provenance refuses any image outside those projects that is not referenced by digest.

  4. 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.preloadModels empty, ollama.registryCIDRs empty).

  5. 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.

  6. Close every outbound flow. Leave networkSecurity.providerFQDNs empty, or set networkSecurity.providerEgress.controlPlane and .litellm to false, and do not enable any eai.io/provider-* label: only the local models stay available.

  7. Install. Follow the page of your method with the internal sources: OS packages (repository files of step 2, or navin-install from the offline archive) or Kubernetes with Helm (Harbor of step 3, the chart of the bundle charts/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​

SymptomCauseFix
apt update reports NO_PUBKEYKeyring not installedCopy navin-archive-keyring.gpg to /usr/share/keyrings/
dnf reports a GPG check failureRPM-GPG-KEY-navin not reachable at gpgkeyPublish the key next to repodata/
A vLLM pod restarts while loadingWeights missing from the cacheCopy the weights on the volume; raise vllm.startupFailureThreshold for large models
Kyverno refuses a mirrored imageImage not signed with the internal keySign it again in Harbor

More details: Client installation handbook.