Air-gapped installs
Mirror the images and tools and install without internet access.
The platform downloads nothing at runtime: no telemetry, no update checks, the console's fonts and schemas are bundled. An install without internet access needs three things: the images in your registry, the chart from there, and mirrors for what the tools in the workspaces download.
Each release attaches images.txt, mirror.sh and the chart harthelm-<version>.tgz, and since 1.4.0 the restore
runbooks harthelm-restore-<version>.tar.gz (Backups and restore):
bring them along. The chart contains
values-airgap.yaml, a values file with every setting this page names and placeholders for your hosts.
Mirror the images
images.txt lists the five Harthelm images, the PostgreSQL 17 and 18 images of CloudNativePG, the images of the
other built-in managed services (MariaDB, Valkey, RabbitMQ, S3 object storage), the CloudNativePG operator and
cert-manager, each with its digest. On a host that reaches both registries:
./mirror.sh registry.example.internal images.txtIt runs skopeo copy --all --preserve-digests per line: every platform of an image and the same digests, so the
digests the chart pins resolve in your mirror, and the same repository paths, so the registry is the only thing the
chart needs to know. --dry-run prints the commands; SKOPEO_SRC_FLAGS and SKOPEO_DEST_FLAGS pass credentials or
--dest-tls-verify=false. Without a host that sees both sides, copy through a directory (skopeo's dir: or oci:
transport) and carry it over.
Mirror the chart
helm pull oci://<your registry>/charts/harthelm --version <version>
helm push harthelm-<version>.tgz oci://registry.example.internal/charts
tar -xzf harthelm-<version>.tgz harthelm/values-airgap.yaml
cp harthelm/values-airgap.yaml .The last two lines take the air-gapped profile out of the chart; replace its placeholders with your hosts.
Install the operators
Install cert-manager and the CloudNativePG operator from the same mirror, in the versions images.txt names. Their
charts take an image registry value.
Point the workspaces at mirrors
Set the tools' mirrors in workspaces.toolEnv; every workspace pod gets them. An empty value is dropped, so leave
the ones you do not run empty.
| Tool | Variables |
|---|---|
| Nix | NIX_CONFIG: substituters = <cache> (replaces the public cache) and trusted-public-keys = <name>:<key> |
| mise | MISE_URL_REPLACEMENTS (a JSON map of URL prefixes), MISE_NODE_MIRROR_URL, MISE_USE_VERSIONS_HOST=false |
| npm, pnpm, yarn | NPM_CONFIG_REGISTRY |
| pip | PIP_INDEX_URL; PIP_TRUSTED_HOST only for a mirror without valid TLS |
| Go | GOPROXY; GOSUMDB=off, or the checksum database through the proxy; GOPRIVATE or GONOSUMDB for internal modules |
| anything else | HTTPS_PROXY, HTTP_PROXY, NO_PROXY (core adds its in-cluster hosts and .svc to NO_PROXY itself) |
For the IDE's extensions, set workspaces.ide.extensionsGallery to an Open VSX mirror. Without one the IDE asks
nobody, and the built-in extensions work.
Workspaces may reach the internet but no private address, and mirrors usually have one. Name them in
teams.network.mirrors (NetworkPolicy peers and TCP ports); core then renders a policy harthelm-to-mirrors into
every team namespace. Without it, prepare fails at the first download.
Set the rest of the values
| Value | Air-gapped |
|---|---|
global.imageRegistry | your mirror; global.imagePullSecrets when it needs credentials |
global.proxy | only when the platform pods reach the identity provider or Git server through a proxy |
baseImages | empty for the chart's own IDE image from the mirror, or full references into the mirror |
containers.allowedRegistries | the mirror only, so container services cannot name an outside registry |
router.forward.allowPublic | false; internal targets go in router.forward.allowCIDRs |
customDomains.resolvers | your internal DNS servers |
customDomains.issuer, routing.tls.certManager.issuerRef | an internal issuer: a CA Issuer or an internal ACME server |
oidc.issuer, git.providers | your internal identity provider and Git server; oidc.caConfigMap and git.caConfigMap for a private CA |
internal.tls | unchanged: the chart's own CA through cert-manager needs nothing outside |
Install
helm install harthelm oci://registry.example.internal/charts/harthelm --version <version> \
-n harthelm-system -f values-airgap.yaml -f my-values.yamlThe preflight Job checks the cluster as for any install, the licence included: it is checked
offline, so the Secret of the install guide works unchanged. Continue there from "Prove the network policies".
hart smoke (from 1.2 on) passes air-gapped as well: its app runs on what the workspace image ships, so it needs
no mirror.
Check that nothing leaves
The release namespace reaches only what its NetworkPolicies allow: the API server, the database, the identity provider,
the Git provider, the mail relay and the registries. Workspaces are allowed to the internet by their policies, so a
firewall or CNI flow log of outbound traffic from the rg-* namespaces shows a tool that still reaches out.