> For the complete documentation index, see [llms.txt](https://developer.harness.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.harness.io/self-managed-enterprise-edition/use-self-managed-enterprise-edition/smp-installationupgrade/operator-installation/install/install-in-an-air-gapped-environment.md).

# Air-gapped installation

This topic covers installing the Harness Platform Installer in air-gapped (offline) environments.

In air-gapped mode, all container images are pre-loaded into a private registry. The installer pulls images from your private registry.

***

### Step 1: Download Required Artifacts <a href="#step-1-download-required-artifacts" id="step-1-download-required-artifacts"></a>

Download from the Harness Artifact Registry (from a machine with internet access):

**Clustermgr CLI:**

```bash
curl -L -o harness-clustermgr.tgz \
  "https://pkg.harness.io/pkg/G_iX-gJ_SiSGIITUoe06eQ/platform-installer/files/harness-clustermgr/<VERSION>/harness-clustermgr-<VERSION>-linux-amd64.tgz"
```

**Workflow Bundle (needed during platform upgrade):**

```bash
curl -L -o workflow-<VERSION>.tgz \
  "https://pkg.harness.io/pkg/G_iX-gJ_SiSGIITUoe06eQ/platform-installer-workflow/files/harness-workflow/<VERSION>/workflow-<VERSION>.tgz"
```

{% hint style="info" %}
**WORKFLOW VERSION**

The workflow version mirrors the Harness SMP version.
{% endhint %}

***

### Step 2: Mirror Images to Your Private Registry <a href="#step-2-mirror-images-to-your-private-registry" id="step-2-mirror-images-to-your-private-registry"></a>

#### Required Images <a href="#required-images" id="required-images"></a>

| Image                                | Source Registry                        | Version Matches            | Required                                  |
| ------------------------------------ | -------------------------------------- | -------------------------- | ----------------------------------------- |
| `platform-installer-min`             | `pkg.harness.io/.../cxe-public-docker` | clustermgr (e.g., `1.0.6`) | Always                                    |
| `tiw-airgap`                         | `pkg.harness.io/.../cxe-public-docker` | workflow (e.g., `0.43.0`)  | Always                                    |
| `ingress-nginx/controller`           | `registry.k8s.io`                      | `v1.15.1`                  | When using nginx ingress (default)        |
| `ingress-nginx/kube-webhook-certgen` | `registry.k8s.io`                      | `v1.6.9`                   | When using nginx ingress (default)        |
| `release/pilot`                      | `registry.istio.io`                    | `1.30.3`                   | When using Istio (`-i istioInstall=true`) |
| `release/proxyv2`                    | `registry.istio.io`                    | `1.30.3`                   | When using Istio (`-i istioInstall=true`) |

#### Push Installer Images <a href="#push-installer-images" id="push-installer-images"></a>

```bash
REGISTRY="your-private-registry.example.com"
PREFIX="harness"
CLUSTERMGR_VERSION="1.0.6"
WORKFLOW_VERSION="0.43.0"

docker login $REGISTRY

# 1. Platform installer <a href="#1-platform-installer" id="1-platform-installer"></a>
docker pull pkg.harness.io/g_ix-gj_sisgiituoe06eq/cxe-public-docker/platform-installer-min:$CLUSTERMGR_VERSION
docker tag pkg.harness.io/g_ix-gj_sisgiituoe06eq/cxe-public-docker/platform-installer-min:$CLUSTERMGR_VERSION $REGISTRY/$PREFIX/platform-installer-min:$CLUSTERMGR_VERSION
docker push $REGISTRY/$PREFIX/platform-installer-min:$CLUSTERMGR_VERSION

# 2. Workflow bundle image <a href="#2-workflow-bundle-image" id="2-workflow-bundle-image"></a>
docker pull pkg.harness.io/g_ix-gj_sisgiituoe06eq/cxe-public-docker/tiw-airgap:$WORKFLOW_VERSION
docker tag pkg.harness.io/g_ix-gj_sisgiituoe06eq/cxe-public-docker/tiw-airgap:$WORKFLOW_VERSION $REGISTRY/$PREFIX/tiw-airgap:$WORKFLOW_VERSION
docker push $REGISTRY/$PREFIX/tiw-airgap:$WORKFLOW_VERSION
```

#### Push Nginx Ingress Images (default ingress) <a href="#push-nginx-ingress-images-default-ingress" id="push-nginx-ingress-images-default-ingress"></a>

```bash
# 3. Nginx controller <a href="#3-nginx-controller" id="3-nginx-controller"></a>
docker pull registry.k8s.io/ingress-nginx/controller:v1.15.1
docker tag registry.k8s.io/ingress-nginx/controller:v1.15.1 $REGISTRY/$PREFIX/controller:v1.15.1
docker push $REGISTRY/$PREFIX/controller:v1.15.1

# 4. Webhook cert generator <a href="#4-webhook-cert-generator" id="4-webhook-cert-generator"></a>
docker pull registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.6.9
docker tag registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.6.9 $REGISTRY/$PREFIX/kube-webhook-certgen:v1.6.9
docker push $REGISTRY/$PREFIX/kube-webhook-certgen:v1.6.9
```

#### Push Istio Images (only if using Istio) <a href="#push-istio-images-only-if-using-istio" id="push-istio-images-only-if-using-istio"></a>

```bash
ISTIO_VERSION="1.30.3"

# 5. istiod (pilot) <a href="#5-istiod-pilot" id="5-istiod-pilot"></a>
docker pull registry.istio.io/release/pilot:$ISTIO_VERSION
docker tag registry.istio.io/release/pilot:$ISTIO_VERSION $REGISTRY/$PREFIX/pilot:$ISTIO_VERSION
docker push $REGISTRY/$PREFIX/pilot:$ISTIO_VERSION

# 6. Istio proxy (ingress gateway) <a href="#6-istio-proxy-ingress-gateway" id="6-istio-proxy-ingress-gateway"></a>
docker pull registry.istio.io/release/proxyv2:$ISTIO_VERSION
docker tag registry.istio.io/release/proxyv2:$ISTIO_VERSION $REGISTRY/$PREFIX/proxyv2:$ISTIO_VERSION
docker push $REGISTRY/$PREFIX/proxyv2:$ISTIO_VERSION
```

{% hint style="info" %}
**IMAGE VERSIONS**

* `platform-installer-min` version matches the **clustermgr** version (e.g., `1.0.6`)
* `tiw-airgap` version matches the **workflow** version (e.g., `0.43.0`)
* Nginx images: `controller:v1.15.1`, `kube-webhook-certgen:v1.6.9`
* Istio images: `pilot:1.30.3`, `proxyv2:1.30.3` from `registry.istio.io/release`
  {% endhint %}

For 0.41.0+, Harness uses a signed `manifest.yaml` with per-module download URLs instead of public bundles. See the [Harness air-gap guide](/self-managed-enterprise-edition/use-self-managed-enterprise-edition/smp-installationupgrade/helm-installation/install-in-an-air-gapped-environment.md#choose-your-helm-chart-line) for details.

***

### Step 3: Run Installation <a href="#step-3-run-installation" id="step-3-run-installation"></a>

{% hint style="info" %}
**HELM-BASED AIR-GAPPED INSTALL**

See the [Install Guide](/self-managed-enterprise-edition/use-self-managed-enterprise-edition/smp-installationupgrade/operator-installation/install/install-with-smp-operator.md) for the Helm-based air-gapped install steps (under **Step 2 → helm → Air-gapped install** under **helm** tab).
{% endhint %}

{% tabs %}
{% tab title="clustermgr" %}

```bash
./clustermgr install-pi \
  --dns platform.internal.example.com \
  --namespace harness \
  --registry-host harbor.internal.example.com \
  --registry-prefix harness-platform \
  --registry-user admin \
  --registry-password 'Harbor@123' \
  --email admin@example.com \
  --password 'SecurePass123!' \
  --version 0.43.0 \
  --pi-set cluster.triggerInstall=false \
  --pi-set cluster.tfi.storageClass=local-path \
  --pi-set cluster.profile=medium \
  -i airgap=true
```

**Air-Gap with Istio:**

```bash
./clustermgr install-pi \
  --dns platform.internal.example.com \
  --registry-host harbor.internal.example.com \
  --registry-prefix harness-platform \
  --registry-user admin \
  --registry-password 'Harbor@123' \
  --version 0.43.0 \
  --pi-set cluster.triggerInstall=false \
  --pi-set cluster.profile=medium \
  -i ingressType=istio \
  -i istioInstall=true \
  -i airgap=true
```

{% endtab %}
{% endtabs %}

***

### Registry Flags Reference <a href="#registry-flags-reference" id="registry-flags-reference"></a>

| Flag                  | Description                                      | Example                                                    |
| --------------------- | ------------------------------------------------ | ---------------------------------------------------------- |
| `--registry-host`     | Registry hostname (can include namespace suffix) | `registry.example.com` or `registry.example.com/namespace` |
| `--registry-prefix`   | Path prefix within the registry                  | `harness-platform`                                         |
| `--registry-user`     | Registry username                                | `admin`                                                    |
| `--registry-password` | Registry password or token                       | `pat.xxx.xxx`                                              |
