2026-01-18Carlos Eduardo

Deploying OpenShift on Proxmox with Terraform Automation

OpenShiftProxmoxTerraformKubernetesDevOpsAutomation
D

Deploying OpenShift on Proxmox with Terraform Automation

Running OpenShift in a home lab is a great way to have an enterprise-grade Kubernetes and container orchestration platform. Unlike managed services like AWS EKS (Amazon Elastic Kubernetes Service) or Azure AKS, running on Proxmox gives you full control over the infrastructure, making it perfect for mastering DevOps practices. In this guide, I'll walk you through deploying a fully functional OpenShift cluster on Proxmox VE using the Agent-based installer and Terraform for infrastructure automation.

While Docker revolutionized how we package applications, OpenShift takes it a step further by providing a complete platform for deploying and managing those containers. You can even integrate this setup with Jenkins for robust CI/CD pipelines, simulating a real-world production environment that rivals what you'd find on AWS.

Architecture Overview

This setup deploys a 5-node OpenShift cluster which can be customized as needed programmatically via Terraform:

  • 3 Master nodes — Running the control plane (etcd, API server, controllers)
  • 2 Worker nodes — Running application workloads with additional storage disks for LVM

The cluster uses static IP addresses with the Agent-based installer, which provides a streamlined installation experience without requiring a separate bootstrap node. This could also be replicated for a larger and production-like environment by increasing the number of masters and workers as needed.

Network Diagram

Network Diagram

Cluster Specifications

Cluster Specifications

Network Layout

Network Layout

Additionally, you'll need:

  • API VIP: 192.168.1.31
  • Ingress VIP: 192.168.1.30

The nodes will have the IPs assigned statically via the configuration of the network DHCP server but you can also set them manually in Proxmox if needed. The access to the cluster will use the defined VIPs which require setting up DNS records accordingly.

Prerequisites

Required Tools

Before starting, ensure you have these tools installed on your workstation:

  1. Terraform (>= 1.0.0)
  2. openshift-install — Download from Red Hat Console
  3. oc (OpenShift CLI) — Download from the same location
  4. nmstatectl — Install via your package manager (required to generate the ISO image)
# Fedora/RHEL which is usually already installed
dnf install nmstate

# Other distros or Mac/WSL2 via Rust
# Install Rust using rustup
curl https://sh.rustup.rs -sSf | sh
# and the package
cargo install nmstatectl

DNS Configuration

Configure your DNS server with the following records pointing to your cluster: Here I defined that my cluster will be published at the domain ocp.internal.example.com. Adjust accordingly to your domain.

; API and API-INT records (point to API VIP)
api.ocp.internal.example.com.     A    192.168.1.31
api-int.ocp.internal.example.com. A    192.168.1.31

; Wildcard for applications (point to Ingress VIP)
*.apps.ocp.internal.example.com.  A    192.168.1.30

; Individual node records
ocp-master-1.ocp.internal.example.com. A 192.168.1.32
ocp-master-2.ocp.internal.example.com. A 192.168.1.33
ocp-master-3.ocp.internal.example.com. A 192.168.1.34
ocp-worker-1.ocp.internal.example.com. A 192.168.1.35
ocp-worker-2.ocp.internal.example.com. A 192.168.1.36

Red Hat Pull Secret

Obtain your pull secret from Red Hat Console — you'll need this for the installation configuration.

Proxmox Configuration

Creating API Users for Terraform

Connect to your Proxmox host via SSH or console and create the required users and roles:

Proxmox User Creation

# Create a role with necessary privileges for Terraform
pveum role add terraform-role -privs "VM.Allocate VM.Clone VM.Config.CDROM VM.Config.CPU VM.Config.Cloudinit VM.Config.Disk VM.Config.HWType VM.Config.Memory VM.Config.Network VM.Config.Options VM.Audit VM.PowerMgmt Datastore.AllocateSpace Datastore.Audit Sys.Audit Pool.Allocate Sys.Console Sys.Modify VM.Migrate SDN.Use VM.GuestAgent.Audit VM.GuestAgent.Unrestricted Pool.Audit"

# Create the Terraform user and assign the role
pveum user add terraform@pve
pveum aclmod / -user terraform@pve -role terraform-role

# Create an API token for Terraform (save the output!)
pveum user token add terraform@pve terraform-token --privsep=0

The token creation will output something like:

┌──────────────┬──────────────────────────────────────┐
│ key          │ value                                │
╞══════════════╪══════════════════════════════════════╡
│ full-tokenid │ terraform@pve!terraform-token        │
├──────────────┼──────────────────────────────────────┤
│ value        │ xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx │
└──────────────┴──────────────────────────────────────┘

Save the token value — you'll need it for the Terraform configuration.

Configuration Files

install-config.yaml

This file defines your OpenShift cluster configuration:

---
apiVersion: v1
baseDomain: internal.example.com
compute:
  - architecture: amd64
    hyperthreading: Enabled
    name: worker
    replicas: 2
controlPlane:
  - architecture: amd64
    hyperthreading: Enabled
    name: master
    replicas: 3
metadata:
  name: ocp
networking:
  clusterNetwork:
    - cidr: 10.128.0.0/14
      hostPrefix: 23
  machineNetwork:
    - cidr: 192.168.1.0/24
  networkType: OVNKubernetes
  serviceNetwork:
    - 172.30.0.0/16
platform:
  baremetal:
    apiVIPs:
      - "192.168.1.31"
    ingressVIPs:
      - "192.168.1.30"
pullSecret: '<your-pull-secret-here>'
sshKey: "<your-ssh-public-key>"

Replace baseDomain, pullSecret, sshKey, and adjust parameters as needed.

agent-config.yaml

This file defines the network configuration for each node:

---
apiVersion: v1alpha1
kind: AgentConfig
metadata:
  name: ocp
rendezvousIP: 192.168.1.32
hosts:
  - hostname: ocp-master-1
    role: master
    rootDeviceHints:
      deviceName: /dev/sda
    interfaces:
      - name: enp6s18
        macAddress: BC:24:11:44:22:32
    networkConfig:
      interfaces:
        - name: enp6s18
          type: ethernet
          state: up
          mac-address: BC:24:11:44:22:32
          ipv4:
            enabled: true
            address:
              - ip: 192.168.1.32
                prefix-length: 24
            dhcp: false
      dns-resolver:
        config:
          server:
            - 192.168.1.1
      routes:
        config:
          - destination: 0.0.0.0/0
            next-hop-address: 192.168.1.1
            next-hop-interface: enp6s18
            table-id: 254
  # Similar blocks for other nodes...

terraform.tf

Here's the complete Terraform configuration that automates the entire deployment:

terraform {
  required_providers {
    proxmox = {
      source  = "telmate/proxmox"
      version = "3.0.2-rc06"
    }
  }
  required_version = ">= 1.0.0"
}

variable "install_dir" {
  description = "Directory where OCP installation files will be created"
  type        = string
  default     = "ocp-proxmox"
}

# ... (Rest of the Terraform configuration provided in the original text)

(Refer to the full gist or previous text for the complete code)

Deployment

Step 1: Initialize and Apply Terraform

export INSTALL_DIR=ocp-proxmox
terraform init
terraform plan -out plan
terraform apply plan

Step 2: Monitor Installation Progress

export KUBECONFIG=$INSTALL_DIR/auth/kubeconfig
./openshift-install agent wait-for install-complete --dir=$INSTALL_DIR

Proxmox Console

Step 3: Access Your Cluster

export KUBECONFIG=$INSTALL_DIR/auth/kubeconfig
oc get nodes
oc whoami --show-console

Web Console Login Web Console Dashboard

Post-Installation Configuration

Make Masters Schedulable (Optional)

oc patch schedulers.config.openshift.io cluster --type merge \
  --patch '{"spec":{"mastersSchedulable": true}}'

Configure LVM Storage

To use the extra disks on worker nodes for persistent storage, install the LVM Storage Operator.

1. Create the Operator Subscription

Create LVMStorage-Operator.yml and apply it.

2. Identify the Extra Disks

ssh core@ocp-worker-1 'ls -l /dev/disk/by-path/'

3. Create the LVMCluster

Create LVMStorage.yml and apply it.

LVM Storage

Conclusion

With this setup, you have a fully automated OpenShift deployment on Proxmox. The Terraform configuration handles everything from ISO generation to VM provisioning, making it easy to tear down and rebuild your cluster as needed.

All configuration files mentioned in this post are available in the accompanying gist.