Skip to content

Offline and Air-Gapped Installation

OpenEA Community can run without Internet access after the required container images have been built and staged. The supported runtime does not depend on public CDNs, Google Fonts, external JavaScript, or other browser-hosted Internet resources.

There are two supported installation patterns:

  1. Temporarily connected installation — allow Internet access for the first image build and image pulls, then disconnect the host.
  2. Fully air-gapped installation — build and collect the required images on a connected preparation host, transfer them to the isolated host, and start OpenEA with --no-build.

What requires Internet access during a normal first build

A new Docker host normally needs network access for several separate downloads:

Build/install action Why network access may be required
Obtain the OpenEA source Git clone or release download, unless the source is transferred another way
Pull python:3.10-slim Base image used to build the OpenEA application image
Pull postgres:16-alpine PostgreSQL runtime image
pip install during the OpenEA image build Python packages are resolved/downloaded from PyPI unless already cached/mirrored
Frontend asset vendoring during the OpenEA image build Pinned Tabler, HTMX, Lucide, Cytoscape.js, Swagger UI, and ReDoc files are downloaded and copied into the OpenEA image

Docker Engine and the Docker Compose plugin must already be installed on the target host. Installing Docker or operating-system packages is outside the OpenEA installation procedure and may itself require Internet access or separately staged packages.

Once the OpenEA application image and PostgreSQL image are present, normal OpenEA operation does not require Internet access.

Temporarily connected installation

If the OpenEA host can be connected during installation, use the normal procedure:

docker compose up -d --build

Wait for the build and initial image pulls to finish, then verify the application before disconnecting the host:

docker compose ps
curl http://localhost:8000/health
curl http://localhost:8000/health/ready

You can also verify that the OpenEA browser assets were copied into the built image:

docker compose exec web python scripts/vendor_frontend_assets.py --check

After those steps complete successfully, Internet access can be removed. Refreshing the browser, signing in, using Impact Analysis, switching themes, and opening /docs or /redoc should continue to work because their browser assets are served locally by OpenEA.

Rebuilds can require connectivity again

A later docker compose build can require network access again if Docker/Python caches are unavailable. If the machine must remain isolated permanently, use the air-gapped image-transfer process below for upgrades as well.

Fully air-gapped installation

Use a connected preparation host to build the exact OpenEA image that will run on the isolated machine.

Preparation-host requirements

The preparation host should use a Docker-compatible platform matching the isolated target, especially the same CPU architecture (for example, amd64 to amd64).

Start with the same OpenEA Community 1.5.2 source that will be transferred to the target.

1. Build the OpenEA image while connected

From the repository root:

cp .env.example .env

docker compose build web

The Compose configuration tags the resulting application image as:

openea-community:1.5.2

unless OPENEA_IMAGE is overridden in .env.

The build downloads Python dependencies and the pinned browser assets and stores them inside the OpenEA image.

2. Pull the PostgreSQL image

docker pull postgres:16-alpine

Verify both required images exist:

docker image inspect openea-community:1.5.2 >/dev/null
docker image inspect postgres:16-alpine >/dev/null

3. Export the images

docker save \
  openea-community:1.5.2 \
  postgres:16-alpine \
  -o openea-community-1.5.2-images.tar

Generate a checksum:

sha256sum openea-community-1.5.2-images.tar \
  > openea-community-1.5.2-images.tar.sha256

Transfer these items through your approved offline-media process:

  • the OpenEA Community 1.5.2 repository/release directory
  • openea-community-1.5.2-images.tar
  • openea-community-1.5.2-images.tar.sha256

4. Verify the transfer on the isolated host

sha256sum -c openea-community-1.5.2-images.tar.sha256

5. Load the images

docker load -i openea-community-1.5.2-images.tar

Verify:

docker image inspect openea-community:1.5.2 >/dev/null
docker image inspect postgres:16-alpine >/dev/null

6. Configure OpenEA

From the transferred repository directory:

cp .env.example .env

Set at least a strong SECRET_KEY and POSTGRES_PASSWORD. Keep:

OPENEA_IMAGE=openea-community:1.5.2

unless you intentionally used a different image tag on the preparation host.

7. Start without building

docker compose up -d --no-build

--no-build is important on an air-gapped host. It tells Compose to use the transferred OpenEA image instead of trying to rebuild it.

8. Verify the isolated deployment

docker compose ps
curl http://localhost:8000/health
curl http://localhost:8000/health/ready
docker compose exec web alembic current
docker compose exec web python scripts/vendor_frontend_assets.py --check

For Community 1.5.2, the expected migration head is:

0017_phase15 (head)

Then open:

http://localhost:8000/setup

The first-run setup page should retain the full OpenEA styling even when the host has no Internet route.

What OpenEA does not contact at runtime

The browser UI does not need to contact jsDelivr or another CDN for:

  • Tabler CSS/JavaScript
  • HTMX
  • Lucide icons
  • Cytoscape.js
  • Swagger UI
  • ReDoc

ReDoc is configured not to load Google Fonts, and Swagger UI's external specification validator is disabled. OpenEA's Content Security Policy restricts normal application pages to locally served scripts/styles and locally served/data images.

With optional login reCAPTCHA disabled, OpenEA can still communicate with external systems only if an administrator intentionally builds an integration around the REST API or places OpenEA behind external infrastructure. Those are deployment choices rather than baseline runtime requirements.

Keep login reCAPTCHA disabled offline

Google reCAPTCHA is optional and disabled by default. A fully offline or air-gapped OpenEA installation should leave Management → Settings → Enable reCAPTCHA on login turned off and should leave RECAPTCHA_SITE_KEY and RECAPTCHA_SECRET_KEY blank.

When disabled, the login page does not load Google's reCAPTCHA JavaScript and the OpenEA backend does not call Google's verification service. The local browser assets described above remain sufficient for normal OpenEA operation.

If you transfer a database from an Internet-connected environment where reCAPTCHA was enabled, disable the setting before moving that database into an isolated environment. If the setting remains enabled but the Google keys or network are unavailable, OpenEA intentionally fails interactive login closed.

Preparing future upgrades for an air-gapped host

For each future OpenEA release:

  1. Build the new OpenEA image on a connected preparation host.
  2. Pull any changed PostgreSQL image required by that release.
  3. Export the required images with docker save.
  4. Transfer and checksum-verify the images and release files.
  5. Back up the existing PostgreSQL data.
  6. Load the new images on the isolated host.
  7. Follow that release's upgrade notes.
  8. Start with docker compose up -d --no-build.

Do not rebuild on the isolated host unless all required base images, Python packages, and frontend assets have been separately staged for that build process.