In high-security environments like defense, military, or intelligence operations, systems are often airgapped - completely isolated from external networks. This creates unique challenges for Python development, particularly when it comes to package management. This guide demonstrates a secure approach to installing Python packages in airgapped environments using uv, an extremely fast package manager written in Rust. Note that this guide is specific to uv and its unique capabilities - if you're using other package managers like pip or Poetry, you'll need different approaches.

⚠️ Security Consideration

When transferring packages to airgapped systems, always follow your organization's security protocols for media transfer and file verification. Ensure all packages are scanned for malware before transfer.

Two-Phase Installation Process

The installation process consists of two distinct phases, performed on separate systems:

Phase 1: Package Download (Internet-Connected System)
  • Generate requirements file from project dependencies
  • Download all required packages and their dependencies
  • Prepare packages for secure transfer
Phase 2: Package Installation (Airgapped System)
  • Configure package manager for offline use
  • Install packages from local source
  • Verify installation integrity

Phase 1: Downloading Packages

First, we'll use a script to download all required packages on an internet-connected system. This script handles dependency resolution and package downloading:

#!/bin/bash

# Get the destination directory from command line argument
dest_dir="$1"

# Create temporary file
temp_file=$(mktemp)

# Export requirements to temporary file
uv export --no-hashes --no-dev --no-editable > "$temp_file"

# Download packages
if [ -n "$dest_dir" ]; then
    # Create destination directory if it doesn't exist
    mkdir -p "$dest_dir"
    pip download -r "$temp_file" -d "$dest_dir"
    echo "Dependencies saved into $(cd "$dest_dir" && pwd)"
else
    pip download -r "$temp_file"
fi

# Clean up temporary file
rm "$temp_file"

To use this script, save it as download_packages.sh and run:

# Make the script executable
chmod +x download_packages.sh

# Run the script, specifying the destination directory
./download_packages.sh ./python_packages
What the Download Script Does:
  • Uses uv to export a clean requirements file without hashes or development dependencies
  • Creates a temporary file to store requirements
  • Downloads all packages and their dependencies using pip
  • Organizes packages in the specified directory
  • Provides absolute path confirmation for verification

Phase 2: Installation on Airgapped System

After securely transferring the downloaded packages to the airgapped system, we'll use a second script for installation. This script ensures all packages are installed from local sources only:

#!/bin/bash

# Check if uv command exists
if ! command -v uv &> /dev/null; then
    echo "Error: 'uv' command not found. Please install uv first."
    exit 1
fi

# Run uv sync with config file
uv venv
uv pip install -r pyproject.toml --config-file airgapped-uv.toml

This script requires a configuration file (airgapped-uv.toml) to ensure offline installation:

# airgapped-uv.toml
no-index = true
package = true
offline = true
find-links = ["file:///absolute/path/to/dependencies"]
Important Configuration Notes
  • no-index = true: Prevents any attempts to reach PyPI
  • offline = true: Enforces offline mode
  • find-links: Must use absolute path to package directory

Best Practices for Airgapped Installations

Security Considerations
  • Verify package checksums after transfer to ensure integrity
  • Maintain a manifest of approved packages and versions
  • Document all package transfers in security logs
  • Regular updates should follow a controlled process
Operational Tips
  • Keep a backup of downloaded packages
  • Document any special build dependencies
  • Maintain separate virtual environments for different projects
  • Consider creating a local package index for larger deployments

Troubleshooting Common Issues

  • Missing Dependencies: Ensure all transitive dependencies are included in the download
  • Path Issues: Always use absolute paths in the configuration file
  • Permission Errors: Verify file system permissions after transfer
  • Binary Incompatibility: Ensure downloaded wheels match target system architecture

Conclusion

Airgapped Python package installation requires careful planning and execution, but using uv makes the process more manageable and secure. By following this two-phase approach and adhering to security best practices, you can maintain reliable Python environments even in highly restricted settings.