Skip to content

Air-Gapped Deployment

Backend.AI GO supports a fully air-gapped managed install. A single policy flag, egress.airGapped, is a fail-closed master switch that disables every outbound network path except the hosts an administrator explicitly allows. This page explains exactly what the switch disables, how it works with the egress allowlist, and how to bring up an air-gapped site end to end.

For the schema details of the air-gap and egress fields, see the Policy Schema Reference. For transferring models to an offline machine, see Offline-Only Setup, which this guide complements with the managed and policy-server path.

The air-gap master switch

egress.airGapped sits above the per-endpoint network controls. Setting it to true in an applied policy closes, in one flip, the network vectors that the firewall and per-endpoint disabled mode do not reach. It is read-only to the user: only a policy sets it. A pre-existing policy that omits the field deserializes as not air-gapped, so an install with no policy is unaffected.

Place the flag on the egress section, the same section that carries the firewall, because the firewall is installed first at startup and is the master no-egress guarantee:

{
  "egress": {
    "enforce": true,
    "allowedHosts": ["models.internal", "policy.internal"],
    "airGapped": true
  }
}

What it disables

When air-gapped, the following all hold at once.

  • The egress firewall is forced to enforce. egress.enforce is treated as true regardless of its written value, so a policy can never install an air-gapped-but-non-enforcing firewall. The install reaches only the hosts in egress.allowedHosts.
  • Every service endpoint resolves to disabled. A default-mode endpoint can never fall back to its public built-in URL. This covers the model hub, the engine and runtime registries, the web-search providers, the channel connectors, the update feed, and the inference API.
  • The bare-client network vectors that run outside the endpoint resolver are refused before any socket opens, each with a clear "disabled in air-gapped mode" error. These are the OAuth device flows (OpenAI Codex and Google Calendar), the continuum-router version probe, the agent URL-import tool, the http_request agent tool, and the agent and squad-template catalog registry.
  • Cloud-provider OAuth device-flow sign-in is blocked, and providers fall back to API-key authentication. The OAuth device-flow entry points are hidden in the UI.
  • Anonymous telemetry is forced off and locked. The toggle is disabled with a "Managed by your organization" badge, and a write that tries to enable it is rejected.
  • The in-app updater and its "check for updates" affordance are suppressed in the UI.

The switch fails closed by construction: there is no code path that installs an air-gapped policy without forcing the firewall on, and each bare-client vector checks the flag before it parses a URL or opens a socket.

The egress allowlist

Air-gapped mode forces the firewall on, but you still decide which internal hosts are reachable. The two egress fields are:

  • egress.enforce: whether the firewall blocks hosts outside the allowlist. Air-gapped mode forces this to true.
  • egress.allowedHosts: the hosts the install may reach. An entry can be a hostname, a wildcard such as *.internal.example, or a CIDR range such as 10.0.0.0/8.

An empty allowedHosts under air-gapped mode denies every host: the install makes no outbound connection at all. List only the internal hosts the install genuinely needs, typically the policy server and an internal model or inference endpoint. The firewall is installed at startup before any network call, so the guarantee holds from the first moment the app runs.

End-to-end offline bring-up

There are two shapes of air-gapped deployment. Pick the one that matches your network.

Site with an internal policy server

When the air-gapped site has an internal network with a reachable policy server, run the central-policy model with air-gap on.

  1. Stand up the policy server on the internal network. See Policy Server Deployment and Operation.
  2. Author a policy with egress.airGapped: true and egress.allowedHosts listing only the internal policy server and any internal inference or model hosts.
  3. Pair it with a fixed_endpoint deployment if all inference must go through one internal endpoint. See Fixed-Endpoint Deployment.
  4. Provision devices with a provision.json whose managementServerUrl points at the internal policy server and whose trustAnchors carry your public anchor. See Device Enrollment and Trust Anchors.
  5. Confirm in the Organization tab that the install is managed, the egress firewall is enforced, and the air-gapped indicator is on.

Fully offline machine (no internal server)

When a machine has no network at all, use a machine policy so no server is ever contacted.

  1. Author an EnterprisePolicy with egress.airGapped: true and the allowedHosts you need (often empty, or only a localhost inference port).
  2. Place it at the machine-policy path (/etc/aigo/policy.json on Linux, or the equivalent for your OS). See Deployment Models.
  3. Transfer models and engines to the machine with the .baimodel workflow in Offline-Only Setup.
  4. Optionally add a signed offline license so the install proves entitlement from a file alone. See Offline Licensing.
  5. Launch the app and confirm the Organization tab reports managed mode with the air-gapped indicator on.

Verification checklist

After bring-up, confirm the posture from the app and the status surface.

  • The Organization settings tab shows the install as managed with the air-gapped indicator on, the egress firewall enforced, and the expected allowed-host count.
  • The status surface (get_managed_status, or GET /api/v1/enterprise/status) reports egress.airGapped: true and egress.enforce: true.
  • The OAuth device-flow entry points are absent from the provider setup UI, and the "check for updates" affordance is gone.
  • A model load and a chat round-trip succeed against the internal or local endpoint, confirming the allowlist is correct.

Next steps