Offline & Air-gapped Operations
Relevant source files
The following files were used as context for generating this wiki page:
Harbor Satellite is designed to address the challenges of container image distribution in edge computing environments where network connectivity is intermittent, unreliable, or entirely absent (air-gapped). By decentralizing the registry, Satellite ensures that edge devices can fetch required images from a local OCI-compliant store that functions independently of the central Harbor registry when the upstream connection is down.
The system achieves this through a stateful local registry (Zot by default) and an orchestration component that synchronizes artifacts whenever connectivity is available. This architecture allows edge workloads to maintain high availability and predictable behavior regardless of external network conditions.
Sources: README.md:8-13, README.md:37-43
Architecture for Disconnected Environments
The architecture relies on the Satellite component acting as a local gateway for OCI artifacts. It consists of three primary interaction points that facilitate offline resilience: the Ground Control management layer, the Satellite orchestrator, and the local OCI registry.
Local Artifact Persistence
In air-gapped scenarios, the Satellite utilizes a stateful local registry to store OCI artifacts on disk. This registry acts as the primary source of truth for local edge devices. When the Satellite is offline, it continues to serve images from its local storage, ensuring that local workloads (such as Kubernetes pods or IoT containers) do not fail due to remote registry timeouts.
The diagram illustrates how local workloads interface directly with the stateful local registry, while the Satellite orchestrator handles synchronization only when network conditions permit.
Sources: README.md:65-79, CLAUDE.md:14-18
State Management and Synchronization Logic
The Satellite maintains a desired state by communicating with Ground Control. This process is designed to be resilient to intermittent failures.
Reconciliation Process
The synchronization logic uses a periodic reconciliation loop. If the Satellite cannot reach Ground Control, it maintains its current state and continues to serve existing artifacts. Once connectivity is re-established, it fetches the "Satellite Root State" to determine if new images or configurations are required.
| Step | Component | Action in Offline State |
|---|---|---|
| Fetch Root State | FetchAndReplicateStateProcess | Retries based on state_replication_interval until online. |
| Artifact Request | StateFetcher | Uses cached configuration if remote is unreachable. |
| Replication | BasicReplicator | Suspended; existing local images remain available for pull. |
Sources: internal/state/state_process.go:73-85, CLAUDE.md:104-108
State Tracking Code
The system compares digests to determine what needs to be updated once connectivity returns.
// internal/state/state_process.go:132-154
func (f *FetchAndReplicateStateProcess) GetChanges(newState StateReader, log *zerolog.Logger, oldEntites []Entity) ([]Entity, []Entity, StateReader) {
// ... logic to compare old local state with new remote state
for _, newEntity := range newEntites {
key := newEntity.Name + "|" + newEntity.Tag
oldEntity, exists := oldEntityMap[key]
switch {
case !exists:
entityToReplicate = append(entityToReplicate, newEntity)
case newEntity.Digest != oldEntity.Digest:
entityToReplicate = append(entityToReplicate, newEntity)
entityToDelete = append(entityToDelete, oldEntity)
}
}
// ...
}
Sources: internal/state/state_process.go:132-154
Container Runtime and Mirroring
To ensure transparency in air-gapped operations, the Satellite configures local container runtimes to treat the local registry as a mirror. This allows the runtime to attempt pulling from the local Satellite first before trying the (potentially unreachable) upstream registry.
Supported Mirroring Configurations
The Satellite can manage configurations for various Container Runtime Interfaces (CRIs) to support offline fallback:
- Docker: Uses
--mirrors=docker:trueto enable local mirroring fordocker.io. - Containerd/Podman/CRIO: Supports mapping specific upstream registries (e.g.,
quay.io,docker.io) to the local Satellite endpoint.
Configuration Validation
During initialization, the Satellite validates that the local registry endpoint is correctly formatted and that mirroring flags are applied to prevent runtime errors during disconnected states.
Sources: cmd/main.go:117-121, pkg/config/validate.go:121-137, deploy/no-spiffe/quickstart.md:118-132
Summary of Offline Capabilities
| Feature | Air-gapped/Offline Behavior |
|---|---|
| Image Availability | Images stored in the local OCI registry (Zot) are immediately available to local workloads. |
| CRI Mirroring | Runtimes are configured to prioritize the local registry, preventing timeouts during remote registry failures. |
| Config Persistence | Satellite writes configurations and state to disk (config.json), allowing it to reboot in a disconnected state with previous settings. |
| Health Checks | Ground Control status is monitored; Satellite continues execution of its local process even if Ground Control is unreachable. |
Sources: README.md:112-118, CLAUDE.md:120-124, internal/state/state_process.go:185-207
Harbor Satellite's offline and air-gapped operations ensure that artifact distribution is not a single point of failure for edge deployments. By combining local OCI storage with resilient state reconciliation and runtime mirroring, it provides a stable environment for containerized applications in locations with restricted or no internet access.