Skip to content

Playbook: Air-gapped Provisioning

What it is

The Air-gapped Provisioning playbook defines the workflow for securely transferring and verifying software artifacts (LLM models, GGUFs, Kiwix ZIMs, Docker images) onto a physically disconnected ("air-gapped") server. It relies on a "Download Once, Sneakernet, Verify" strategy to ensure system integrity without internet access.

What problem it solves

It solves the "Bootstrapping at the Edge" problem where a server requires high-bandwidth data but lacks a persistent or secure internet connection. Specifically, it addresses: - Security Isolation: Provisioning systems that cannot be connected to the internet for security reasons. - Limited Connectivity: Setting up systems in remote areas with no or expensive internet access. - Predictable Environment: Ensuring the exact same model or knowledge version is deployed across multiple air-gapped nodes. - Audit Trails: Providing a verifiable manifest of all data entering the secure environment.

Where it fits in the stack

Category: Playbook / Infrastructure. It acts as the bridge between the internet-connected "Inlet" machine and the air-gapped "Private" machine.

Typical use cases

  • Ollama Model Sneakernet: Downloading a 70B parameter model once and transferring it via external drive to an air-gapped Mac Studio.
  • Kiwix Knowledge Update: Pre-staging the latest English Wikipedia ZIM (100GB+) for offline search.
  • Docker Image Sideloading: Saving Docker images as .tar files to be loaded onto a disconnected cluster.
  • Firmware & OS Updates: Transferring critical security patches to air-gapped infrastructure.

Strengths

  • Maximum Security: The air-gapped machine remains untethered from the internet.
  • Bandwidth Efficient: Only downloads what is necessary; no repeated downloads for multi-node setups.
  • Verifiable: Uses SHA256 checksums to ensure data wasn't corrupted or tampered with during transit.
  • Resilient: Not affected by ISP outages or cloud service blocks.

Limitations

  • High Latency: The "human transport" (sneakernet) speed is the primary bottleneck.
  • Storage Requirement: Requires large external drives (2TB+) to move modern models and ZIMs.
  • Manual Effort: Requires physical presence at both the source and destination machines.
  • Version Stale-ness: Knowledge bases (Kiwix) and models are only as current as the last transfer.

When to use it

  • When setting up a Fully Offline Assistant.
  • In secure environments (financial, research, home security) where internet access is prohibited.
  • For disaster preparedness kits (Survivalist Tech Stack).

When not to use it

  • When a fast, reliable, and secure internet connection is available.
  • For small files or updates where the overhead of a physical transfer is excessive.

Getting started

1. Identify and Download (Connected Machine)

On a machine with internet access, download the required artifacts:

# Download Ollama model
ollama pull gemma3-27b-it
# Download Kiwix ZIM
wget https://download.kiwix.org/zim/wikipedia_en_all_maxi.zim

2. Export and Hash

Export the artifacts and generate checksums:

# Export Ollama model (manual copy of ~/.ollama/models)
tar -cvf gemma3.tar ~/.ollama/models/blobs
# Generate checksum
sha256sum gemma3.tar > gemma3.tar.sha256

3. Transfer (Sneakernet)

Copy the .tar and .sha256 files to a formatted external drive (exFAT or ext4).

4. Verify and Import (Air-gapped Machine)

Mount the drive and verify integrity:

sha256sum -c gemma3.tar.sha256
# If OK, extract to the local Ollama directory
tar -xvf gemma3.tar -C ~/.ollama/models/

CLI examples

1. Saving a Docker Image for Transfer

docker save ghcr.io/open-webui/open-webui:main > open-webui.tar

2. Loading a Docker Image Offline

docker load < open-webui.tar

3. Verifying a Kiwix ZIM file

sha256sum -c wikipedia_en_all_maxi.zim.sha256

API examples

Python: Automated Checksum Generation for Manifests

Automate the creation of a transfer manifest.

import hashlib
import json
import os

def generate_manifest(directory):
    manifest = {}
    for filename in os.listdir(directory):
        path = os.path.join(directory, filename)
        if os.path.isfile(path):
            sha256_hash = hashlib.sha256()
            with open(path, "rb") as f:
                for byte_block in iter(lambda: f.read(4096), b""):
                    sha256_hash.update(byte_block)
            manifest[filename] = sha256_hash.hexdigest()

    with open("transfer_manifest.json", "w") as f:
        json.dump(manifest, f, indent=2)

generate_manifest("/mnt/sneakernet_drive")

Verification Script (Air-gapped Machine)

A script to be run on the destination to verify the entire drive.

import json
import hashlib

def verify_manifest(manifest_path):
    with open(manifest_path, "r") as f:
        manifest = json.load(f)

    for filename, expected_hash in manifest.items():
        # ... (similar hashing logic as above)
        if actual_hash == expected_hash:
            print(f"✅ {filename} verified.")
        else:
            print(f"❌ {filename} FAILED verification!")

  • Kiwix — Offline knowledge libraries.
  • Ollama — Local inference engine.
  • Docker — Containerization for offline deployment.
  • Fully Offline Assistant — The target architecture.
  • MinIO — S3-compatible storage for local mirrors.
  • Syncthing — Semi-automated local sync.
  • Rclone — Moving files between storage providers.

Sources / References

Contribution Metadata

  • Last reviewed: 2026-07-21
  • Confidence: high