---
title: Deploying on OpenShift
slug: ps/help/en_us/ics/25x/vadep/deploying-on-openshift
docTags: 
createdAt: 2026-09-25T06:11:07.135Z
---

## Overview

This guide describes how to deploy **Ivanti Connect Secure (ICS)** as a virtual machine on **Red Hat OpenShift** using **KubeVirt** and Ivanti-provided deployment artifacts, including OVMF, the wrapper binary, and YAML files. Secure Boot and vTPM are enabled by default. The guide also covers optional initialization of network and administrator settings using an ISO image during first boot.

Use this guide to prepare the OpenShift environment, upload the ICS image, create the virtual machine, and optionally configure initial system settings for first-time deployment.

## Deployment Workflow

Follow these steps to deploy Ivanti Connect Secure (ICS) on Red Hat OpenShift using KubeVirt:

1. Review the OpenShift, KubeVirt, compute, storage, and networking prerequisites defined in the provided YAML files.
2. Obtain the ICS KVM deployment artifact: (The version shown in the screenshots is an example based on ICS 25.1.3.0 GA build 22109.)

::Image[]{src="https://api.archbee.com/api/optimize/wxZG1KsS4xNkVZYoiu_o9/13G4eT3ifCJoFMrNoR1nP_upload.png" size="70" width="711" height="68" isUploading="false" darkWidth="711" darkHeight="68" position="flex-start" showCaption="false" indent="1"}

3. Extract the ZIP archive to obtain the deployment files, including the KVM image, OVMF files, and YAML manifests.

::Image[]{src="https://api.archbee.com/api/optimize/wxZG1KsS4xNkVZYoiu_o9/_YpLy3Jz949HASdG8ue9w_upload.png" size="70" width="714" height="123" isUploading="false" darkWidth="714" darkHeight="123" position="flex-start" showCaption="false" indent="1"}

4. Extract ISA-V-KVM-ICS-25.1.3.0-22109.1-VT-kvm.img.gz to obtain the ICS VM image file (.img in QCOW2 format).

::Image[]{src="https://api.archbee.com/api/optimize/wxZG1KsS4xNkVZYoiu_o9/af6zYlUCA_UsnfSLxhgbh_image.png" size="50" isUploading="false" width="647" height="52" darkWidth="647" darkHeight="52" position="flex-start" showCaption="false" indent="1"}

5. Upload the extracted ICS (qcow2 format) image to the OpenShift cluster.
6. Obtain and run the Ivanti wrapper binary (provided separately from the deployment artifact). Supply the OVMF\_VARS file and YAML manifests as input. The wrapper validates Secure Boot and vTPM settings, then creates and deploys the ICS virtual machine. Login to in [download portal](https://portal.ivanti.com/customer/product-downloads)  and navigate to **Download > Network Security> Ivanti Connect Secure> Ivanti Connect Secure&#x20;**&#x74;o fetch `KVM_OpenShift_wrapper_binaries.zip`
7. (Optional) Initialize the VM configuration during deployment by attaching a configuration ISO image.

## Pre-Requisites

- OpenShiftServer
- Kubeconfigfile
- KubevirtOperatorinstalled
- StorageClassprovisioned
- Networkprovisioned

## Key Concepts

Review the terms below before starting the deployment steps. These explain the OpenShift virtualization components and security features referenced throughout this guide.

- **Kubevirt**: KubeVirt is an open-source Kubernetes extension that allows you to run and manage Virtual Machines (VMs) alongside standard containers on a single platform.
- **Secure Boot**: Secure Boot is a UEFI firmware feature that prevents malicious software, like rootkits or deep-level cheats, from loading when you turn on your PC. It acts like a bouncer by checking the cryptographic signature of every boot file against a trusted database before allowing Linux to start.
- **Virtual TPM**: A Virtual Trusted Platform Module (vTPM) is a software-based emulation of a physical TPM 2.0 chip. It provides virtual machines (VMs) with hardware-level security, allowing guest operating systems to securely store cryptographic keys, perform remote system attestation, and meet OS requirements.
- **OVMF**: OVMF (Open Virtual Machine Firmware) is an open-source project that provides UEFI (Unified Extensible Firmware Interface) support for virtual machines. It serves as the virtual equivalent of a motherboard's BIOS/UEFI, allowing hypervisors like QEMU and KVM to boot guest operating systems using modern firmware standards.
- **Ivanti wrapper binary**: This wrapper binary is used to deploy ICS VM automatically with Secure Boot and vTPM enabled on OpenShift environment. Supports x86\_64 and ARM architectures.
  - **ivanti-oc-wrapper-linux-amd64 (x86\_64):** Wrapper binary for deploying and managing ICS virtual machines on OpenShift from 64-bit x86 Linux workstations, jump hosts, or CI/CD runners.&#x20;
  - **ivanti-oc-wrapper-linux-arm64 (ARM64):** Wrapper binary for deploying and managing ICS virtual machines on OpenShift from 64-bit ARM Linux workstations, jump hosts, or management servers.&#x20;
- **ivanti-oc-wrapper-darwin-arm64 (macOS Apple Silicon):** Wrapper binary for deploying and managing ICS virtual machines on OpenShift from Apple Silicon (M-series) macOS workstations.

## Upload ICS Image

UploadICSKVMimage to Red Hat OpenShift Cluster. The uploaded image is stored as a source PVC and is used by the virtual machine definition during deployment.

Use the following command to upload the ICS image to the OpenShift cluster.

```python
virtctlimage-uploadpvcics-25.1.3.0-22109.1 \
--namespace=openshift-cnv \
--pvc-size=80Gi \
--image-path=/path/to/ISA-V-KVM-ICS-25.1.3.0-22109.1-VT-kvm.img \
--storage-class=hostpath-csi \
--insecure
```

:::hint{type="info"}
Above example command references the hostpath-csi storage class for demonstration purposes. Modify the storage class parameter to match the storage provisioner and storage class available in your Red Hat OpenShift deployment.
:::

## Create ICS VM

1. Create the VM YAML file for the ICS deployment.
2. Use the following sample YAML file as a starting point. Update the storage class, network attachment definitions, CPU and memory allocations, and image to match your target OpenShift environment and deployment requirements.&#x20;

Sample yaml

::File{src="https://api.archbee.com/api/presign/wxZG1KsS4xNkVZYoiu_o9/Yu-dDZ4Zztn6Upqyp2IdC_ics.yaml" label="ics.yaml" isUploading="false"}

### Review VM Configuration Areas

The following subsections explain the main parts of the VM YAML that typically require review or customization before deployment.

**Select the source image**

The following section specifies the uploaded ICS image PVC that is used as the VM source image.

:::BlockQuote
&#x20;             source:
&#x20;                 pvc:
&#x20;                     name: ics-25.1.3.0-22109.1
&#x20;                     namespace: openshift-cnv
:::

**Configure computere sources**

The following settings define the CPU and Memory allocation for the VM.

:::BlockQuote
&#x20;               cpu:
&#x20;                   cores: 4
&#x20;                   model: host-passthrough
&#x20;               resources:
&#x20;                   requests:
&#x20;                       memory: 8Gi
:::

CPUs and Memory need to be based on ICS model like ISA4500-V, ISA6500-V and ISA8500-V.

- ISA4500-V:4vCPUs and 8GB RAM
- ISA6500-V:8vCPUs and 16GB RAM
- ISA8500-V:12vCPUs and 32GB RAM

**Enable Secure Boot and vTPM**

The following settings enable UEFI Secure Boot and persistent vTPM support for the VM.

:::BlockQuote
&#x20;               firmware:
&#x20;                   bootloader:
&#x20;                       efi:
&#x20;                           persistent: true
&#x20;                           secureBoot: true
&#x20;               devices:
&#x20;                   tpm:
&#x20;                       persistent: true
:::

**Configure Network**

The following settings create the VM network interface and bind it to the specified Multus network attachment.

:::BlockQuote
&#x20;                   interfaces:
&#x20;                       \- name: extnet
&#x20;                         bridge: \{}
&#x20;                   rng: \{}
&#x20;                   networkInterfaceMultiqueue: true
&#x20;           networks:
&#x20;               \- name: extnet
&#x20;                 multus:
&#x20;                     networkName: openshift-cnv/br-ens8f0-net
:::

In above example, only one interface is created. Depending on requirement, ICS can be created with three interfaces with appropriate bridges.

- Internal (int0).
- External (ext0).
- Management (mgt0).

## Deploy ICS VM

Execute the command using the syntax shown below and with required arguments.

**Syntax**

:::BlockQuote
./ivanti-oc-wrapper \\
&#x20;-namespace \<namespace> \\
&#x20;-vars \<ovmf-path> \\
&#x20;-yaml \<yaml-file>
:::

- \<Ivanti-oc-wrapper> - Ivanti binary to deploy ICS VM.
- \<namespace> – The namespace where we deploy the VM.
- \<ovmf-path> – The path of OVMF\_VARS.secboot.ivanti.fd file.
- \<yaml> – The path of created ics.yaml file.

Example:

:::BlockQuote
./ivanti-oc-wrapper \\
&#x20;-namespace openshift-cnv \\
&#x20;-vars OVMF\_VARS.secboot.ivanti.fd \\
&#x20;-yaml ics.yaml
:::

## Configuration Initialization

ICS running on OpenShift supports configuration initialization through ISO image.

During bootup, the system checks for an attached configuration ISO. If a valid ISO is detected, then configurations like IP address, subnet, username, and password is initialized from that ISO image.

Example configuration initialization:

:::BlockQuote
\< Environment xmlns = "http\://schemas.dmtf.org/ovf/environment/1"
xmlns: xsi = "http\://www\.w3.org/2001/XMLSchema-instance"
xmlns: oe = "http\://schemas.dmtf.org/ovf/environment/1"
xmlns: ve = "http\://www\.kvmv.com/schema/ovfenv"
oe: id = "" >
&#x20; \<PlatformSection >
&#x20; \<Kind > ICS KVM Image \< /Kind>&#x20;
&#x20; \<Version > 1.0 .0 \< /Version>&#x20;
&#x20; \<Vendor > Ivanti \< /Vendor>&#x20;
&#x20; \<Locale > en \< /Locale>&#x20;
&#x20; \</PlatformSection>&#x20;
&#x20; \<PropertySection >
&#x20; \<Property oe: key = "vaNetworkStack" oe: value = "" / >
&#x20; \<Property oe: key = "vaIPAddress" oe: value = "10.10.10.10" / >
&#x20; \<Property oe: key = "vaNetmask" oe: value = "255.255.255.0" / >
&#x20; \<Property oe: key = "vaGateway" oe: value = "10.10.10.1" / >
&#x20; \<Property oe: key = "vaIPv6Address" oe: value = "" / >
&#x20; \<Property oe: key = "vaPrefix" oe: value = "" / >
&#x20; \<Property oe: key = "vaIPv6Gateway" oe: value = "" / >
&#x20; \<Property oe: key = "vaDefaultVlan" oe: value = "" / >
&#x20; \<Property oe: key = "vaExternalIPAddress" oe: value = "" / >
&#x20; \<Property oe: key = "vaExternalNetmask" oe: value = "" / >
&#x20; \<Property oe: key = "vaExternalGateway" oe: value = "" / >
&#x20; \<Property oe: key = "vaExternalIPv6Address" oe: value = "" / >
&#x20; \<Property oe: key = "vaExternalPrefix" oe: value = "" / >
&#x20; \<Property oe: key = "vaExternalIPv6Gateway" oe: value = "" / >
&#x20; \<Property oe: key = "vaExternalDefaultVlan" oe: value = "" / >
&#x20; \<Property oe: key = "vaManagementIPAddress" oe: value = "" / >
&#x20; \<Property oe: key = "vaManagementNetmask" oe: value = "" / >
&#x20; \<Property oe: key = "vaManagementGateway" oe: value = "" / >
&#x20; \<Property oe: key = "vaManagementIPv6Address" oe: value = "" / >
&#x20; \<Property oe: key = "vaManagementPrefix" oe: value = "" / >
&#x20; \<Property oe: key = "vaManagementIPv6Gateway" oe: value = "" / >
&#x20; \<Property oe: key = "vaManagementDefaultVlan" oe: value = "" / >
&#x20; \<Property oe: key = "vaExternalPortReconfigWithValueInVAppProperties" oe: value = "1" / >
&#x20; \<Property oe: key = "vaInternalPortReconfigWithValueInVAppProperties" oe: value = "1" / >
&#x20; \<Property oe: key = "vaManagementPortReconfigWithValueInVAppProperties" oe: value = "1" / >
&#x20; \<Property oe: key = "vaPrimaryDNS" oe: value = "1.2.3.4" / >
&#x20; \<Property oe: key = "vaSecondaryDNS" oe: value = "" / >
&#x20; \<Property oe: key = "vaWINSServer" oe: value = "" / >
&#x20; \<Property oe: key = "vaDNSDomain" oe: value = "ivanti.com" / >
&#x20; \<Property oe: key = "vaDNSTrafficInterface" oe: value = "" / >
&#x20; \<Property oe: key = "vaAdminUsername" oe: value = "admin" / >
&#x20; \<Property oe: key = "vaAdminPassword" oe: value = "adminpassword" / >
&#x20; \<Property oe: key = "vaCommonName" oe: value = "ivanti.com" / >
&#x20; \<Property oe: key = "vaOrganization" oe: value = "Ivanti Inc." / >
&#x20; \<Property oe: key = "vaRandomText" oe: value = "thisisrandom" / >
&#x20;\<Property oe: key = "vaAcceptLicenseAgreement" oe: value = "y" / >
&#x20; \<Property oe: key = "vaEnableLicenseServer" oe: value = "n" / >
&#x20; \<Property oe: key = "vaAdminEnableREST" oe: value = "y" / >
&#x20; \<Property oe: key = "vaRegistrationFQDN" oe: value = "" / >
&#x20; \<Property oe: key = "vaRegistrationCode" oe: value = "" / >
&#x20; \<Property oe: key = "vaRegisterNetworkInterface" oe: value = "internal" / >
&#x20; \<Property oe: key = "vaEnableProxy" oe: value = "" / >
&#x20; \<Property oe: key = "vaProxyHost" oe: value = "" / >
&#x20; \<Property oe: key = "vaProxyPort" oe: value = "" / >
&#x20; \<Property oe: key = "vaProxyUsername" oe: value = "" / >
&#x20; \<Property oe: key = "vaProxyPassword" oe: value = "" / >
&#x20; \<Property oe: key = "vaAuthCodeLicense" oe: value = "" / >
&#x20; \<Property oe: key = "vaConfigURL" oe: value = "" / >
&#x20; \<Property oe: key = "vaConfigServerCACertPEM" oe: value = "" / >
&#x20; \<Property oe: key = "vaConfigData" oe: value = "" / >
&#x20; \<Property oe: key = "vaDisableSourceIPRestrictionForDefaultAdminRealm=" oe: value = "" / >
&#x20; \</PropertySection>
&#x20;\</Environment>
:::

Save above XML as kvm\_template.xml (template is already part of compressed KVM file).

:::hint{type="info"}
The configuration file must be name&#x64;**&#x20;kvm\_template.xml**, else  configuration initialization fails.
:::

1. Creat&#x65;**&#x20;ISO image&#x20;**&#x66;rom template file using below command.

:::BlockQuote
mkisofs -l -o openshift.iso kvm\_template.xml
:::

2. Uploa&#x64;**&#x20;openshift.iso&#x20;**&#x66;ile to OpenShift data volume.&#x20;

Following YAML file creates datastore volume.

:::BlockQuote
apiVersion: cdi.kubevirt.io/v1
kind: DataVolume
metadata:
&#x20;  name: iso-dv
&#x20;  namespace: openshift-cnv&#x20;
spec:
&#x20;  source\:upload: \{}	# we will upload ISO storage:
&#x20;  accessModes:
&#x20;   \- ReadWriteOnce&#x20;
&#x20;  resources:
&#x20;   requests:&#x20;
&#x9;         storage: 100Mi
&#x20; storageClassName: hostpath-csi# or your SC
:::

3. Upload ISO image to iso-dv data volume.

:::BlockQuote
virtctl image-upload dv iso-dv \\
&#x20;   \--namespace=openshift-cnv \\
&#x20;   \--size=100Mi \\
&#x20;   \--image-path=/path/of/openshift\_kvm.iso \\
&#x20;   \--uploadproxy-url=https\://\<cdi-uploadproxy-ip-or-domain>:443 \\&#x20;
&#x20;   \--insecure
:::

4. &#x20;Verify that upload is successful.

:::BlockQuote
$0cget dv -nopenshift-cnv
NAME           PHASE        PROGRESS     RESTARTS     AGE
iso-dv        Succeeded      N/A                      11m
:::

5. &#x20;Attach iso-dev to VM during creation.
   Following is snippet of YAML file where ISO is attached.

:::BlockQuote
&#x20;     spec:
&#x20;       domain:
&#x20;         devices:
&#x20;           disks:
&#x20;             \# Your standard boot/root operating system disk
&#x20;             \- name: rootdisk5
&#x20;               disk:
&#x20;                 bus: virtio

&#x20;             \# --- THE ISO DRIVE SECTION ---
&#x20;             \- name: cdromiso  # Give the drive a reference name
&#x20;               cdrom:          # Instructs to expose this volume as a CD-ROM drive
&#x20;                 bus: sata     # SATA is the standard bus type used for CD-ROM drives
:::

6. If KVM initialization drive is successfully attached, then following message will be seen during boot up. “This is KVM environment and configuration drive is present”
