Air-gapped & Offline Usage
This guide explains how to use bz in air-gapped (disconnected) environments where machines cannot access the internet.
Overview
bz provides first-class support for offline and air-gapped environments through:
- Local cache - Download and verify module metadata locally
- Offline mode - Operate entirely from cache without network access
- Registry sync - Mirror BCR to local/internal registries
Quick Start: Cache-based Offline
The simplest approach uses bz’s built-in cache commands:
-
On a connected machine, download dependencies:
Terminal window # Cache all dependencies from your MODULE.bazelbz cache download# Or cache specific modulesbz cache download rules_go rules_python gazelle -
Verify the cache is complete:
Terminal window bz cache verify -
Transfer the cache:
Terminal window # The cache is at ~/.cache/bz by defaultrsync -av ~/.cache/bz/ user@airgap-machine:~/.cache/bz/# Or use tar/zip for sneakernettar -czf bz-cache.tar.gz ~/.cache/bz -
On the air-gapped machine, enable offline mode:
Terminal window # Option 1: Environment variableexport BZ_OFFLINE=1# Option 2: Config file (~/.config/bz/config.toml)# [network]# mode = "offline"# Option 3: CLI flagbz mod list --offline -
Verify and use:
Terminal window bz cache verifybz mod listbz mod outdated
Cache Commands
Download Dependencies
# Download all deps from current MODULE.bazel (including transitive)bz cache download
# Download specific modules (resolves transitive deps automatically)bz cache download rules_go@0.50.1 gazelle
# Download ALL modules from registry (warning: very large!)bz cache download --all
# Use custom cache directorybz cache download --cache-dir=/opt/bz-cacheVerify Cache Completeness
# Check if cache has all deps needed for offline usebz cache verify
# Output as JSON (for scripting)bz cache verify --jsonExample output:
Verifying cache for MODULE.bazel dependencies...
✓ rules_go@0.50.1 ✓ bazel_skylib@1.5.0 ✗ gazelle@0.38.0 (missing)
Cache is INCOMPLETE. Run 'bz cache download' to fix.Check Cache Statistics
bz cache statsOutput:
Cache directory: /home/user/.cache/bzTotal modules: 15Total versions: 42Total size: 12.5 MBLast updated: 2024-01-15 10:30:00Clear Cache
# Clear everything (with confirmation)bz cache clear
# Clear without confirmationbz cache clear --force
# Clear specific modulesbz cache clear rules_go gazelleNetwork Modes
bz supports three network modes:
| Mode | Description | Use Case |
|---|---|---|
online | Always fetch from network (default) | Normal development |
prefer-offline | Use cache if available, fallback to network | Speed up builds |
offline | Never access network, fail if not cached | Air-gapped machines |
Setting Network Mode
bz mod list --offlinebz mod outdated --prefer-offlineexport BZ_OFFLINE=1# orexport BZ_PREFER_OFFLINE=1[network]mode = "offline"Advanced: Registry Mirroring
For larger deployments, you may want to create a full registry mirror that can be served over HTTP or filesystem.
Using bz mod sync
Create a bz.star configuration file:
# bz-export.star - Export configuration for air-gapped transfer
bcr = registry.http("https://bcr.bazel.build")
# Export to a portable directoryexport_dir = registry.file("/mnt/transfer/bazel-registry")
# All modules your air-gapped environment needsmodules = [ "bazel_skylib", "platforms", "rules_cc", "rules_go", "rules_python", "rules_rust", "gazelle", "protobuf", # Add all your dependencies here]
sync.workflow( name = "export", origin = bcr, destination = export_dir, modules = modules, versions = sync.all(), # Export all versions for flexibility transforms = [ sync.skip_yanked(), # Rewrite URLs to point to internal server sync.rewrite_source_urls( pattern = "https://github.com/(.*)/archive/", replacement = "https://internal-mirror.local/github/$1/archive/", ), sync.include_patches(), ],)Run the sync:
bz mod sync --config bz-export.star exportSetting Up the Air-gapped Registry
-
Transfer the registry:
Terminal window cp -r /mnt/transfer/bazel-registry /opt/bazel/registry -
Configure Bazel to use it:
.bazelrc common --registry=file:///opt/bazel/registry# Or serve via HTTP and use:common --registry=http://internal-server/bazel-registry -
Configure bz to use it:
/etc/bz/config.toml [network]mode = "offline"registry = "file:///opt/bazel/registry"
Complete Air-gapped Setup
Here’s a complete example for an air-gapped deployment:
Directory Structure
Directory/opt/bazel/
Directoryregistry/
- bazel_registry.json
Directorymodules/
Directoryrules_go/
- metadata.json
Directory0.50.1/
- MODULE.bazel
- source.json
Directoryrules_python/
- …
- …
Directorycache/
Directorymodules/ (bz cache)
- …
System Configuration
[network]mode = "offline"registry = "file:///opt/bazel/registry"
[cache]dir = "/opt/bazel/cache"
[commands]# Disable commands that require networkdisabled = ["registry ping"]Bazel Configuration
# /etc/bazel.bazelrc (system-wide) or project .bazelrc
# Use local registrycommon --registry=file:///opt/bazel/registry
# Disable network (extra safety)build --experimental_downloader_config=/etc/bazel-downloader.cfgUpdating the Mirror
When you need to add new modules or update versions:
-
On connected machine: Update your module list and run sync
Terminal window bz mod sync --config bz-export.star export -
Transfer only changes: Use rsync for incremental updates
Terminal window rsync -av --delete /mnt/transfer/bazel-registry/ /opt/bazel/registry/ -
Update the cache:
Terminal window bz cache downloadbz cache verify
Troubleshooting
”Module not found in cache"
# Check what's in the cachebz cache stats
# Verify against MODULE.bazelbz cache verify
# Download missing modulesbz cache download"Cannot connect to registry” in offline mode
This is expected! In offline mode, bz should never attempt network access. If you see this error:
- Check that offline mode is enabled:
echo $BZ_OFFLINE - Verify config file:
cat ~/.config/bz/config.toml - Ensure the cache is populated:
bz cache verify
Checking Network Mode
# This should fail in offline mode with no cachebz mod info some_uncached_module --offline
# This should work if cache is populatedbz mod list --offlineCache Location
Default cache locations by platform:
| Platform | Default Path |
|---|---|
| Linux | ~/.cache/bz |
| macOS | ~/.cache/bz |
| Windows | %LOCALAPPDATA%\bz\cache |
Override with --cache-dir flag or BZ_CACHE_DIR environment variable.
CI/CD Integration
For CI/CD pipelines with limited or no internet access:
jobs: build: runs-on: self-hosted # Air-gapped runner env: BZ_OFFLINE: "1" BZ_CACHE_DIR: "/opt/shared-cache/bz" steps: - uses: actions/checkout@v4 - name: Verify cache run: bz cache verify - name: Build run: bazel build //...For runners with internet access but slow connections:
jobs: build: env: BZ_PREFER_OFFLINE: "1" steps: - name: Restore cache uses: actions/cache@v4 with: path: ~/.cache/bz key: bz-cache-${{ hashFiles('MODULE.bazel') }} - name: Build run: | bz cache download bazel build //...