An air-gapped AI deployment is not a normal deployment with the network switched off. Roughly half of a standard stack assumes an outbound connection somewhere — a package index, a model hub, a licence check, a telemetry endpoint, a certificate revocation lookup — and each of those has to be replaced rather than removed. This page is the inventory and the transfer protocol.
What breaks the moment you unplug
Enumerate this first, because the list is longer than expected and finding items one at a time is what turns a two-week project into a two-month one.
Dependency Description Package installs Every language package manager reaches out by default, including at container build time and inside a test suite that installs a plugin. Needs an internal mirror or a vendored bundle. Model and dataset downloads Libraries that fetch weights or tokenisers by identifier on first use will hang or fail. Set the offline environment variables your framework provides, point the cache directory at pre-populated storage, and test with the network actually removed — not merely unset. Container base images Needs an internal registry, mirrored deliberately rather than pulled through a proxy that fails closed when the gap is real. Hosted model APIs Unavailable by definition. Everything must run on local weights, which sets a hard ceiling on model size from your hardware and is the constraint that shapes the whole design. Telemetry and error reporting SDKs that post to a vendor endpoint will retry, buffer and eventually block a thread. Disable them explicitly at configuration level rather than relying on the network to fail fast. Licence and update checks Some commercial components phone home. Find out before deployment, not on day 31 when a grace period ends. Certificate and revocation checks OCSP and CRL lookups over the public internet will time out. Internal PKI, with the timeout behaviour tested. Time synchronisation Public NTP is unreachable. An internal time source is needed, and clock drift breaks token expiry and log correlation before it breaks anything obvious.The reliable way to find the rest is to build and run the whole system on a host with no route to the internet and watch what fails. A firewall rule that returns a refusal is not the same test — many clients behave quite differently against a black hole that times out than against an immediate reset, and the real gap is the first one.
The inbound transfer protocol
Everything that crosses the gap should cross the same way, through one procedure, so the controls apply uniformly.
- Assemble on a build host with network access. The bundle is produced by a reproducible pipeline, not by a person copying files.
- Verify upstream authenticity before packaging. Publisher signatures and checksums, checked on the connected side where you can reach the publisher’s key. Once inside, you can only verify against what you brought.
- Produce a manifest. Every file, its size, its SHA-256, its upstream source and its licence. This is the artefact an auditor reads and the thing the receiving side checks against.
- Sign the manifest with a key whose public half is already inside. This is what makes the transfer trustworthy rather than merely intact — a checksum proves the bytes did not change; a signature proves who assembled them.
- Scan. Malware scan on the connected side, and a software bill of materials for the dependency tree, since the receiving side cannot look up a vulnerability database later.
- Transfer by whatever the site permits: removable media, a data diode, a reviewed one-way gateway.
- Verify inside. Signature first, then per-file hashes against the manifest, then install. A single mismatch fails the whole bundle — do not install the files that matched.
- Record the import. What, when, who, which manifest hash. This log is the answer to “where did this binary come from?” six months later, and there is no other way to answer it inside a gap.
# Producing the manifest on the connected side.
find bundle/ -type f -print0 \
| sort -z \
| xargs -0 sha256sum > bundle/MANIFEST.sha256
# Add provenance the checksums cannot carry.
cat > bundle/MANIFEST.json <<'JSON'
{
"bundle_id": "2026-08-04-r3",
"created_utc": "2026-08-04T11:02:00Z",
"contents": [
{"path": "models/my-model/", "digest": "sha256-3f9a1c...",
"source": "<upstream url>", "licence": "<spdx id>"},
{"path": "wheels/", "count": 214, "source": "internal mirror snapshot"},
{"path": "images/inference-2026.08.04.tar", "digest": "sha256-91be..."}
]
}
JSON
gpg --detach-sign --armor bundle/MANIFEST.sha256
# Verifying inside the gap. Order matters: signature, then hashes.
gpg --verify MANIFEST.sha256.asc MANIFEST.sha256 || exit 1
sha256sum -c MANIFEST.sha256 --quiet || exit 1
echo "bundle verified"
Enter fullscreen mode Exit fullscreen mode
What goes in the bundle
- Container images as archives. Export with
docker saveand import withdocker load, or copy registry-to-archive-to-registry with a tool built for it. Include every base image, not only your own. - Language packages as files. For Python,
pip download -r requirements.txt -d wheels/on a host with the same platform and Python version, thenpip install --no-index --find-links=wheels/inside. The platform match matters: wheels are platform-specific and a mismatched download silently falls back to a source build that will fail inside without a compiler. - Model weights, with the manifest digest from model weights in CI/CD, plus the tokeniser, the config and anything else the loader fetches separately. Test the load offline before shipping the bundle; the file that gets forgotten is always a small one.
- The licence texts, per model and per package. Some open-weight licences carry redistribution and use conditions, and inside a gap there is no way to go and read them later. Open weights versus open source covers what the distinction means in practice.
- OS packages and drivers, including the GPU driver and container toolkit, matched to the kernel version inside. A driver mismatch is the most common single cause of a failed air-gapped GPU install.
- Documentation and runbooks, because inside the gap nobody can open a vendor’s documentation site during an incident. Ship the pages you need offline.
Getting telemetry out
Operating blind is not acceptable, and neither is a general outbound channel. The resolution is that outbound data is a reviewed export, not a stream.
- Aggregate inside. Run the full metrics and logging stack within the gap. Nothing leaves in raw form.
- Define an export schema that contains only aggregates: counts, percentiles, error class frequencies, resource utilisation. No prompts, no completions, no identifiers, no free text. Free text is the leak, always — an exception message can contain a customer record.
- Review before release. A human, or a validator that rejects anything not matching the schema, or both. Automated schema validation is the part that scales.
- Export on a schedule through the same controlled path as inbound, in reverse, with its own manifest and log.
Two consequences worth planning for. Debugging is much harder when you cannot see an example input, so invest in reproducing failures from aggregates — error taxonomies, structured error codes, counters keyed by cause rather than by message. And any vendor support arrangement needs an agreed procedure for what you can send them, decided in the contract rather than during an outage.
Update cadence and the CVE problem
The honest difficulty of air-gapped operation is not the initial install, it is month nine. A vulnerability is published in a dependency; inside the gap nothing notices, because the thing that notices is a scanner with a network connection.
- Keep the SBOM outside. The bill of materials for each bundle stays on the connected side and is scanned continuously there. That is what turns “is our air-gapped system vulnerable?” into a query rather than an investigation.
- Schedule bundles, do not wait for events. A monthly or quarterly cadence means the transfer procedure is practised. A procedure used twice a year fails when it is needed urgently.
- Have an emergency path, defined in advance. Who approves an out-of-cycle bundle, how it is expedited, what verification is not skipped. Deciding this during an incident is how controls get bypassed.
- Version-pin everything and record what is installed. Inside the gap, “which version is running?” must be answerable from the import log without inspecting the running system.
Degrees of air gap
“Air-gapped” is used for several quite different arrangements, and the design differs substantially between them. Ask which one is actually required, because teams routinely build the strictest version when a weaker one was the requirement.
Arrangement Description True air gap No network path exists. Everything above applies in full. Rare outside defence and some industrial control settings. One-way (data diode) Data can leave, or enter, but not both. Physically enforced. The transfer protocol above still applies in the permitted direction; the other direction is media. Isolated network No internet, but internal services are reachable — an internal registry, an internal package mirror, internal PKI. Much more comfortable, and what most ‘air-gapped’ requirements actually mean. Egress-controlled Internet access through an allow-list proxy with logging. Not an air gap at all, but often what a compliance requirement is satisfied by. Ask, because the difference is weeks of work.For the last two, an on-premises deployment with strict egress controls gets most of the assurance for a fraction of the effort — on-premises LLM deployment covers that shape, and AI sovereignty covers the reasons organisations end up here. If the requirement genuinely is the first row, budget for the update cadence above from the start: it is the recurring cost, and it is the one that gets forgotten in the plan.
답글 남기기