# Red Hat OpenShift

Production-grade installation guide for Red Hat OpenShift 4.18 & newer. All snippets are idempotent and tested on OCP 4.18 (Kubernetes 1.31).

#### Table of Contents

1. [Overview](#id-1-overview)
2. [Prerequisites](#id-2-prerequisites)
3. [Quick-Start Variables](#id-2-prerequisites)
4. [Install Local Tooling](#id-2-prerequisites)
5. [OpenShift Cluster Preparation](#id-5-openshift-cluster-preparation)
6. [Install Cluster Add-ons](#id-6-install-cluster-add-ons)
7. [Provision PostgreSQL (CloudNativePG)](#id-7-provision-postgresql-cloudnativepg)
8. [Provision Object Storage](#id-8-provision-object-storage)
9. [Create Dynamiq Secrets](#id-9-create-dynamiq-secrets)
10. [Prepare Helm Values](#id-10-prepare-helm-values)
11. [Deploy Dynamiq](#id-11-deploy-dynamiq)
12. [Validate & Smoke-Test](#id-12-validate-and-smoke-test)
13. [Upgrade Workflow](#id-13-upgrade-workflow)
14. [Cleanup](#id-14-cleanup)
15. [Appendix A – values-ocp.yaml Reference](#id-15-appendix-a-values-ocp.yaml-reference)

### 1 – Overview

Dynamiq is a **low-code GenAI operating platform**.\
This guide deploys it as **fully private, TLS-only, auto-upgradeable** workloads on an OpenShift 4.18+ cluster.

Key building blocks:

* **CloudNativePG** (Crunchy Data) for HA PostgreSQL
* **Object storage** – AWS S3, MinIO, or OpenShift Data Foundation
* **External Secrets Operator** for secret sync
* **Fission** for serverless logic
* **Helm** for application lifecycle

### 2 – Prerequisites

| Requirement         | Details                                               |
| ------------------- | ----------------------------------------------------- |
| **OpenShift 4.18+** | Kubernetes 1.31, cluster-admin rights                 |
| **CPU workers**     | ≥ 2 × vCPU / 8 GiB (m5.large-class)                   |
| **GPU workers**     | *Optional* – G5/A10G for model inference              |
| **CLI tools**       | `oc` 4.18+, `helm` 3.14+, `jq`, `openssl`, `envsubst` |
| **Domain**          | Root/sub-domain delegated in DNS                      |
| **Outbound 443**    | Pull container images & reach S3/MinIO                |

### 3 – Quick-Start Variables

> Edit the first block only, then paste the rest *as one*.

```bash
# ---------- BEGIN USER CONFIG ----------
export BASE_DOMAIN="example.com"        # root or delegated sub-domain
export CLUSTER_NAME="dynamiq"           # DNS-safe
export PROJECT="dynamiq"                # OpenShift namespace
export REGION="us-east-1"               # for AWS snippets
# ---------- END USER CONFIG ------------

export OCP_VERSION="4.18"
export K8S_VERSION="1.31"
export STORAGE_S3_BUCKET="${CLUSTER_NAME}-data-$(openssl rand -hex 4)"
export DYNAMIQ_CHART_REPO="oci://709825985650.dkr.ecr.us-east-1.amazonaws.com/dynamiq/enterprise/dynamiq"
```

### 4 – Install Local Tooling

```bash
# OpenShift CLI
curl -LO "https://mirror.openshift.com/pub/openshift-v4/x86_64/clients/ocp/${OCP_VERSION}/openshift-client-linux.tar.gz"
tar -xzvf openshift-client-linux.tar.gz -C /usr/local/bin oc kubectl

# Helm
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

# Verify
oc version --client
helm version
```

### 5 – OpenShift Cluster Preparation

1. **Log in**

   ```bash
   oc login https://api.${CLUSTER_NAME}.${BASE_DOMAIN}:6443 \
     --username kubeadmin --password <REDACTED>
   ```
2. **Create / select project**

   ```bash
   oc new-project ${PROJECT} || oc project ${PROJECT}
   ```
3. **(Optional) Create a fresh IPI cluster**

   ```bash
   openshift-install create cluster --dir ./install --log-level=info
   ```

### 6 – Install Cluster Add-ons

#### 6.1 External Secrets Operator

```bash
oc apply -f https://raw.githubusercontent.com/external-secrets/external-secrets/v0.9.4/deploy/crds/bundle.yaml

helm repo add external-secrets https://charts.external-secrets.io
helm upgrade --install external-secrets external-secrets/external-secrets \
  --namespace external-secrets --create-namespace \
  --set installCRDs=false \
  --wait
```

Create a `ClusterSecretStore` pointing at AWS Secrets Manager (swap provider if required):

```bash
cat <<EOF | envsubst | oc apply -f -
apiVersion: external-secrets.io/v1
kind: ClusterSecretStore
metadata:
  name: dynamiq
spec:
  provider:
    aws:
      service: SecretsManager
      region: $REGION
EOF
```

#### 6.2 Fission Serverless Engine

```bash
kubectl create -k "github.com/fission/fission/crds/v1?ref=v1.20.5"

helm repo add fission https://fission.github.io/fission-charts/
helm upgrade --install fission fission/fission-all \
  --namespace dynamiq-fission --create-namespace \
  --set routerServiceType=ClusterIP \
  --set defaultNamespace=${PROJECT} \
  --set analytics=false \
  --wait
```

#### 6.3 GPU MachineSets (optional)

```bash
oc adm machine-sets create-gpu \
  --accelerator-type nvidia-g5 \
  --name gpu-g5 \
  --replicas 1 \
  --cluster ${CLUSTER_NAME}
```

### 7 – Provision PostgreSQL (CloudNativePG)

```bash
oc apply -f https://get.crunchydata.com/postgres-operator/crunchy-postgres-operator.yaml
# Wait for operator to be Ready

cat <<EOF | oc apply -f -
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: dynamiq-pg
  namespace: ${PROJECT}
spec:
  instances: 2
  imageName: registry.developers.crunchydata.com/crunchydata/crunchy-postgres:16
  storage:
    size: 50Gi
EOF
```

Extract connection details:

```bash
export DATABASE_HOST="dynamiq-pg-rw.${PROJECT}.svc.cluster.local"
export DATABASE_PORT="5432"
export DATABASE_NAME="postgres"
export DATABASE_USERNAME="postgres"
export DATABASE_PASSWORD="$(oc -n ${PROJECT} get secret dynamiq-pg-superuser -o jsonpath='{.data.password}' | base64 -d)"
```

### 8 – Provision Object Storage

#### Option A – AWS S3

```bash
aws s3api create-bucket \
  --bucket "${STORAGE_S3_BUCKET}" \
  --region "${REGION}" \
  --create-bucket-configuration LocationConstraint="${REGION}"

export STORAGE_SERVICE="s3"
```

#### Option B – Internal MinIO

```bash
helm repo add minio https://charts.min.io
helm upgrade --install minio minio/minio \
  --namespace storage --create-namespace \
  --set accessKey=minio --set secretKey=minio123 \
  --set buckets[0].name=${STORAGE_S3_BUCKET} \
  --wait

export STORAGE_SERVICE="minio"
```

### 9 – Create Dynamiq Secrets

```bash
export AUTH_ACCESS_TOKEN_KEY=$(openssl rand -base64 48 | tr -d '\n')
export AUTH_REFRESH_TOKEN_KEY=$(openssl rand -base64 48 | tr -d '\n')
export AUTH_VERIFICATION_TOKEN_KEY=$(openssl rand -base64 48 | tr -d '\n')

cat <<EOF | envsubst | oc apply -f -
apiVersion: v1
kind: Secret
metadata:
  name: nexus-secret
  namespace: ${PROJECT}
type: Opaque
stringData:
  DATABASE_HOST: "$DATABASE_HOST"
  DATABASE_PORT: "$DATABASE_PORT"
  DATABASE_SSLMODE: "require"
  DATABASE_NAME: "$DATABASE_NAME"
  DATABASE_USERNAME: "$DATABASE_USERNAME"
  DATABASE_PASSWORD: "$DATABASE_PASSWORD"
  STORAGE_SERVICE: "$STORAGE_SERVICE"
  STORAGE_S3_BUCKET: "$STORAGE_S3_BUCKET"
  AUTH_ACCESS_TOKEN_KEY: "$AUTH_ACCESS_TOKEN_KEY"
  AUTH_REFRESH_TOKEN_KEY: "$AUTH_REFRESH_TOKEN_KEY"
  AUTH_VERIFICATION_TOKEN_KEY: "$AUTH_VERIFICATION_TOKEN_KEY"
  # --- OPTIONAL TOKENS ---
  HUGGING_FACE_ACCESS_TOKEN: "<HF_TOKEN>"
  OPENAI_API_KEY: "<OPENAI_KEY>"
  SMTP_HOST: "<SMTP_HOST>"
  SMTP_USERNAME: "<SMTP_USER>"
  SMTP_PASSWORD: "<SMTP_PASS>"
EOF
```

### 10 – Prepare Helm Values

```bash
cat <<EOF > values-ocp.yaml
dynamiq:
  domain: ${BASE_DOMAIN}

nexus:
  image:
    repository: 709825985650.dkr.ecr.us-east-1.amazonaws.com/dynamiq/enterprise/nexus
  ingress:
    enabled: true
  externalSecrets:
    enabled: false
  appSecret: nexus-secret
  configMapData:
    STORAGE_SERVICE: ${STORAGE_SERVICE}
    STORAGE_S3_BUCKET: ${STORAGE_S3_BUCKET}

synapse:
  image:
    repository: 709825985650.dkr.ecr.us-east-1.amazonaws.com/dynamiq/enterprise/synapse
  ingress:
    enabled: true
  configMapData:
    STORAGE_SERVICE: ${STORAGE_SERVICE}
    STORAGE_S3_BUCKET: ${STORAGE_S3_BUCKET}

catalyst:
  image:
    repository: 709825985650.dkr.ecr.us-east-1.amazonaws.com/dynamiq/enterprise/catalyst
  configMapData:
    STORAGE_SERVICE: ${STORAGE_SERVICE}
    STORAGE_S3_BUCKET: ${STORAGE_S3_BUCKET}

ui:
  image:
    repository: 709825985650.dkr.ecr.us-east-1.amazonaws.com/dynamiq/enterprise/ui
  ingress:
    enabled: true
EOF
```

### 11 – Deploy Dynamiq

```bash
# Authenticate to ECR
aws ecr get-login-password --region us-east-1 | \
  helm registry login --username AWS --password-stdin 709825985650.dkr.ecr.us-east-1.amazonaws.com

# Install / upgrade Dynamiq
helm upgrade --install dynamiq ${DYNAMIQ_CHART_REPO} \
  --namespace ${PROJECT} \
  --values values-ocp.yaml \
  --wait
```

### 12 – Validate & Smoke-Test

```bash
oc -n ${PROJECT} get route
```

Create **CNAME** records (`app`, `api`, etc.) pointing to the OpenShift router host.

* `https://app.${BASE_DOMAIN}` → Dynamiq UI
* `https://api.${BASE_DOMAIN}` → Dynamiq API

First registered user gains **Admin** rights.

### 13 – Upgrade Workflow

```bash
helm repo update
helm upgrade dynamiq ${DYNAMIQ_CHART_REPO} \
  --namespace ${PROJECT} \
  --reuse-values \
  --wait
```

Provided each component runs ≥ 2 replicas, OpenShift performs zero-downtime rolling updates.

### 14 – Cleanup

```bash
helm uninstall dynamiq -n ${PROJECT} || true
helm uninstall fission -n dynamiq-fission || true
oc delete project ${PROJECT} dynamiq-fission external-secrets || true
aws s3 rb s3://${STORAGE_S3_BUCKET} --force          # if you used AWS S3
# If you created the cluster via step 5:
openshift-install destroy cluster --dir ./install
```

### 15 – Appendix A – values-ocp.yaml Reference

| Key                  | Description             | Required |
| -------------------- | ----------------------- | -------- |
| `dynamiq.domain`     | Base public domain      | ✔        |
| `nexus.appSecret`    | Secret created in §9    | ✔        |
| `*_image.repository` | ECR path                | ✔        |
| `STORAGE_SERVICE`    | `s3`, `minio`, or `odf` | ✔        |

#### Need help? Reach out to us - <support@getdynamiq.ai>

**Happy shipping Dynamiq on OpenShift!** 🚀


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.getdynamiq.ai/on-premise-deployment/red-hat-openshift.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
