Skip to main content

Air-gapped installation

ProxCenter can be installed and upgraded on a host that has no internet access, from a bundle that ships every container image it needs. The bundle is produced for each release: Enterprise customers download it from their account on proxcenter.io, partners from the partner portal, Community users from the GitHub release.

Nothing in the bundle reaches the internet: the license is validated locally against a key embedded in the product, the database migrations run from the image, and the installer sets PROXCENTER_OFFLINE=true so the product stops looking for updates.

The bundle installs a single-node ProxCenter. The conversion to a 3-node high-availability control plane (Settings > High Availability) is not available on an air-gapped site yet: its preflight checks and pulls every image from ghcr.io on each node.

What the bundle contains​

proxcenter-<edition>-<version>.tar.gz extracts to one directory:

FilePurpose
install-airgap.shThe installer. install and upgrade run from this directory.
docker-compose.ymlThe Compose file of that release.
images.tarEvery container image the Compose file uses (ProxCenter, orchestrator, PDF renderer, PostgreSQL).
manifest.jsonEdition, version, image names and digests.
SHA256SUMSChecksums of the files above, verified before anything is loaded.
README.txtThe commands below.

Enterprise bundles weigh about 490 MB, Community bundles about 390 MB. Loading the images needs roughly 2 GB more under Docker's data directory.

Prerequisites on the isolated host​

RequirementDetails
Operating systemLinux with systemd (Debian 12+, Ubuntu 22.04+, RHEL 9 family)
DockerDocker Engine 24+ and the Compose plugin (docker compose version works) and the Docker daemon running, installed from your own package mirror. The air-gapped installer never installs Docker.
Disk5 GB free under /var/lib/docker, plus the database growth
RAM2 GB minimum
Ports3000 (web interface)
NetworkReachability to your Proxmox nodes on port 8006 (PVE) and 8007 (PBS)
Toolsbash, tar, gzip, sha256sum, openssl (all part of a base install)

Step 1: Get the bundle​

Enterprise: log in to proxcenter.io/account, open Air-gapped, and download the version you need. An active subscription is required. From a jump host without a browser, your install token works as a bearer token:

curl -fL -H "Authorization: Bearer YOUR_INSTALL_TOKEN" \
-o proxcenter-enterprise-1.4.11.tar.gz \
"https://proxcenter.io/api/v1/install/bundle?version=1.4.11"

Use version=latest for the newest bundle. The download resumes with curl -C -.

Partners: log in to proxcenter.io/partner, open Air-gapped, and download the bundle for your customer. A signed reseller agreement is required. From a jump host, the customer's install token or one of your NFR install tokens works as the bearer token in the command above.

Community: download proxcenter-community-<version>.tar.gz from the GitHub release.

Download the .sha256 file next to it as well, and your license .key file from Account > License if you have not already.

Step 2: Verify the download​

On the connected side, before the transfer:

sha256sum -c proxcenter-enterprise-1.4.11.tar.gz.sha256

The SHA-256 is also shown on the Air-gapped page of your account.

Step 3: Transfer​

Move the bundle and the license file to the isolated host by your usual channel (removable media, data diode, file transfer gateway). The installer verifies every file again before loading anything.

Step 4: Install​

tar xzf proxcenter-enterprise-1.4.11.tar.gz
cd proxcenter-enterprise-1.4.11
sha256sum -c SHA256SUMS
sudo ./install-airgap.sh install --license /path/to/proxcenter-license.key

When the bundle sits on media without an executable bit (a FAT-formatted USB stick, for example), run sudo bash install-airgap.sh install --license /path/to/proxcenter-license.key instead.

The installer:

  1. checks that Docker and Compose are present and refuses to continue otherwise;
  2. verifies SHA256SUMS;
  3. loads the images with docker load;
  4. writes /opt/proxcenter/docker-compose.yml, .env (fresh secrets, VERSION, PROXCENTER_OFFLINE=true) and, for Enterprise, config/orchestrator.yaml;
  5. creates the volumes and starts the stack;
  6. waits for the web interface, and for the orchestrator on Enterprise.

Then open http://your-server-ip:3000 and create the administrator account, as in the standard installation. --license takes the path to your .key file; the installer copies it into the orchestrator's data volume before the first start, and the orchestrator imports it when it starts (check Settings > License). A key that fails signature verification is ignored and the instance starts unlicensed. Without --license, upload the file later in Settings > License. Community: omit --license, there is no license file (the installer warns and ignores it if you pass one).

If the first install fails​

Every message is also written to /opt/proxcenter/install-airgap.log.

  • If the failure happens before the containers start (a bad license file, a docker load error), the installer removes the files and the volumes it created for this run: fix the cause, then simply run install again.

  • If the containers had already started (a health-check timeout on a slow first boot, for example), the configuration is kept: fix the cause, then restart with:

    cd /opt/proxcenter && sudo docker compose up -d

A second install run is refused while /opt/proxcenter/.env exists, and also when a postgres_data volume from a previous ProxCenter installation exists. To start over:

cd /opt/proxcenter && sudo docker compose down && sudo docker volume rm postgres_data proxcenter_data orchestrator_data

then delete /opt/proxcenter. The Docker daemon must be running (sudo systemctl start docker).

Options: --install-dir <dir> (default /opt/proxcenter), --registry <host/namespace> (see below), --health-timeout <seconds>.

Upgrade​

Download the bundle of the newer version, transfer it, then from its extracted directory:

sudo ./install-airgap.sh upgrade

The upgrade takes a compressed pg_dump of the database into /opt/proxcenter/backups/, backs up the current docker-compose.yml, loads the new images, replaces the Compose file, updates VERSION in .env (secrets are kept), and restarts the stack. --skip-db-backup skips the dump when you have your own backup. Pass --install-dir <dir> again if you installed somewhere other than /opt/proxcenter, and --health-timeout <seconds> to wait longer on a slow host. An upgrade is refused when the installed VERSION already equals the bundle's; to restart the stack after a failed upgrade, run docker compose up -d from /opt/proxcenter.

The previous images stay loaded on the host, which is what makes the rollback below instant. Reclaim the disk space later, once the rollback is no longer needed, with docker image prune -a.

Roll back​

The upgrade prints the exact rollback sequence twice, with the real values filled in: once before it restarts the stack (so the commands are in the transcript even if that restart fails) and again at the end. For an Enterprise install:

cd /opt/proxcenter && sudo docker compose stop frontend orchestrator
sudo docker compose exec -T postgres psql -U proxcenter -d proxcenter -c 'DROP SCHEMA public CASCADE; CREATE SCHEMA public;'
sudo sh -c 'gunzip -c /opt/proxcenter/backups/pre-upgrade-1.4.10-<timestamp>.sql.gz | docker compose exec -T postgres psql -U proxcenter -d proxcenter'
sudo sed -i 's/^VERSION=.*/VERSION=1.4.10/' /opt/proxcenter/.env
sudo cp /opt/proxcenter/docker-compose.yml.bak.<timestamp> /opt/proxcenter/docker-compose.yml
sudo docker compose up -d

Community: stop frontend only, there is no orchestrator container to stop.

The dump was taken with pg_dump --clean --if-exists, which expects the previous version's schema: restoring it straight into the already-migrated database fails on constraints the newer version added. The two database lines above, schema recreate then dump restore, put the database back exactly as it was before the upgrade. Skip both database lines (the schema recreate and the gunzip restore) when you passed --skip-db-backup at upgrade time and the newer version made no database change: the installer itself prints those two lines only when it took a dump.

Use an internal registry​

Large sites keep every image in a private registry (Harbor, Nexus, Artifactory). Log the host in to it, then:

sudo ./install-airgap.sh install --registry harbor.internal/proxcenter --license /path/to/proxcenter-license.key

The installer retags every image of the bundle into harbor.internal/proxcenter/…, pushes them, and writes REGISTRY= and POSTGRES_IMAGE= to .env so Compose pulls from there. Later upgrades push the new images to the same registry automatically.

Features that need an internal mirror​

The installation and the core product work without any outbound access. A few features fetch something at runtime; each can be pointed at an internal resource.

FeatureWhat it fetchesOn an air-gapped site
Version check, GitHub badgeapi.github.comDisabled by PROXCENTER_OFFLINE=true
Cloud image catalog (Automation > Templates)raw.githubusercontent.com catalog JSON, then the images from each distribution's siteCatalog refresh disabled; set TEMPLATE_CATALOG_URL to a mirror of the JSON, and download images from an internal HTTP server through Custom images
Maps (Topology, vDC datacenters)OpenStreetMap tilesSet a custom tile server in Settings > Appearance (the "Map basemap" section); the map explains the situation until then
CVE scanner (Enterprise)Debian Security Tracker JSON, Debian Sources.gz indexesCVE_FEED_URL= and CVE_DEBIAN_MIRROR= in .env, pointed at internal mirrors
Node updates (rolling updates)Proxmox and Debian apt repositories, from the nodesThe nodes need an apt mirror; ProxCenter only drives apt on them
Migrations from VMware, Hyper-V, XCP-ngOn the Proxmox node: virt-v2v, nbdkit, guestfs-tools, ovmf from apt; the VDDK package from ghcr.io; virtio-win.iso from fedorapeople.org; the NTFS compression plugin from GitHub; mingw32-srvany from kojipkgs.fedoraproject.orgInstall the apt packages from your mirror, drop virtio-win.iso at /usr/share/virtio-win/virtio-win.iso on the node, and allow the node an HTTPS proxy for ghcr.io for warm migrations
High-availability control plane (Settings > High Availability)ghcr.io from the three nodes: login, image manifests, pullsNot supported on an air-gapped site yet; stay on the single-node installation
AI assistantThe provider you configureUse a local Ollama
Country flagsflagcdn.comCosmetic; the flags show as blank
Email notificationsYour SMTP relayUnchanged
Web fontsGoogle Fonts (fonts.googleapis.com), requested by the browser on every pageCosmetic: the browser falls back to system fonts; no setting needed
  • Installation for the online installer, the reverse proxy and the production checklist.
  • Upgrade to v1.4 for the database changes of that release.