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:
| File | Purpose |
|---|---|
install-airgap.sh | The installer. install and upgrade run from this directory. |
docker-compose.yml | The Compose file of that release. |
images.tar | Every container image the Compose file uses (ProxCenter, orchestrator, PDF renderer, PostgreSQL). |
manifest.json | Edition, version, image names and digests. |
SHA256SUMS | Checksums of the files above, verified before anything is loaded. |
README.txt | The 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
| Requirement | Details |
|---|---|
| Operating system | Linux with systemd (Debian 12+, Ubuntu 22.04+, RHEL 9 family) |
| Docker | Docker 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. |
| Disk | 5 GB free under /var/lib/docker, plus the database growth |
| RAM | 2 GB minimum |
| Ports | 3000 (web interface) |
| Network | Reachability to your Proxmox nodes on port 8006 (PVE) and 8007 (PBS) |
| Tools | bash, 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:
- checks that Docker and Compose are present and refuses to continue otherwise;
- verifies
SHA256SUMS; - loads the images with
docker load; - writes
/opt/proxcenter/docker-compose.yml,.env(fresh secrets,VERSION,PROXCENTER_OFFLINE=true) and, for Enterprise,config/orchestrator.yaml; - creates the volumes and starts the stack;
- 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 loaderror), the installer removes the files and the volumes it created for this run: fix the cause, then simply runinstallagain. -
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.
| Feature | What it fetches | On an air-gapped site |
|---|---|---|
| Version check, GitHub badge | api.github.com | Disabled by PROXCENTER_OFFLINE=true |
| Cloud image catalog (Automation > Templates) | raw.githubusercontent.com catalog JSON, then the images from each distribution's site | Catalog 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 tiles | Set 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 indexes | CVE_FEED_URL= and CVE_DEBIAN_MIRROR= in .env, pointed at internal mirrors |
| Node updates (rolling updates) | Proxmox and Debian apt repositories, from the nodes | The nodes need an apt mirror; ProxCenter only drives apt on them |
| Migrations from VMware, Hyper-V, XCP-ng | On 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.org | Install 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, pulls | Not supported on an air-gapped site yet; stay on the single-node installation |
| AI assistant | The provider you configure | Use a local Ollama |
| Country flags | flagcdn.com | Cosmetic; the flags show as blank |
| Email notifications | Your SMTP relay | Unchanged |
| Web fonts | Google Fonts (fonts.googleapis.com), requested by the browser on every page | Cosmetic: the browser falls back to system fonts; no setting needed |
Related pages
- Installation for the online installer, the reverse proxy and the production checklist.
- Upgrade to v1.4 for the database changes of that release.