# IBM

Provision all required IBM Cloud services and install Dynamiq via Helm so that the platform is production‑ready, fully private, and upgradeable through IBM Cloud Schematics.

***

### Table of contents

1. [Prerequisites](#prerequisites)
2. [Quick‑start variables](#quick-start-variables)
3. [Install CLI & plugins](#id-1-install-cli-and-plugins)
4. [Authenticate & target a resource group](#id-1-install-cli-and-plugins)
5. [Create networking (VPC + Subnet + Gateway)](#id-3-create-networking-vpc--subnet--gateway)
6. [Provision the VPC‑Gen2 Kubernetes cluster](#id-4-provision-the-kubernetes-cluster)
7. [Provision PostgreSQL](#id-5-provision-postgresql)
8. [Provision Object Storage](#id-6-provision-object-storage)
9. [Install Dynamiq platform (Helm)](#id-7-install-dynamiq-platform)
10. [Create production secrets](#id-8-create-production-secrets)
11. [Verify installation](#id-9-verify-installation)
12. [Upgrade](#id-10-upgrade)
13. [Uninstall](#id-11-uninstall)

***

### Prerequisites

| Requirement            | Notes                                                                                                    |
| ---------------------- | -------------------------------------------------------------------------------------------------------- |
| **IBM Cloud account**  | Billing enabled & quota for VPC, Kubernetes, Databases for PostgreSQL, and Cloud Object Storage          |
| **Access**             | *Manager* and *Administrator* roles on the destination Kubernetes cluster service citeibm\_roles\_doc |
| **Local tooling**      | `bash`, `curl`, **IBM Cloud CLI v2.20+**, **kubectl v1.31+**, **Helm v3.13+**, `jq`, `openssl`           |
| **Kubernetes version** | 1.31 (latest LTS)                                                                                        |
| **Outbound network**   | Port 22 (SSH), 443 (HTTPS) open to IBM Cloud APIs                                                        |

> **Tip** If you prefer containerised tooling, grab the official 💡 *ibmcloud‑tools* image: `docker run --rm -it ibmcom/ibmcloud-tools:latest`.

***

### Quick‑start variables

Export once and reuse everywhere:

```bash
# ====== Edit me ======
export REGION="us-south"              #  <REGION>  e.g. us-south, eu-de
export RG_NAME="dynamiq"              #  <RESOURCE_GROUP_NAME>
export VPC_NAME="dynamiq"             #  <VPC_NAME>
export SUBNET_NAME="public"           #  <SUBNET_NAME>
export GW_NAME="dynamiq-gateway"      #  <PUBLIC_GATEWAY_NAME>
export ZONE="${REGION}-1"             #  Keep default or pick another zone
export CLUSTER_NAME="dynamiq-cluster" #  <CLUSTER_NAME>
export K8S_VERSION="1.31"             #  Align with supported versions
export FLAVOR="bx2.2x8"               #  2 vCPU / 8 GB each worker
export WORKERS="2"                    #  Adjust for your workload
export DB_INSTANCE_NAME="db-dynamiq"  #  <POSTGRES_INSTANCE_NAME>
export COS_INSTANCE_NAME="cos-dynamiq"#  <COS_INSTANCE_NAME>
export COS_BUCKET="dynamiqai"         #  <BUCKET_NAME>
# =======================
```

***

### 1 – Install CLI & plugins

```bash
curl -sL https://ibm.biz/idt-installer | bash
ibmcloud plugin install infrastructure-service
ibmcloud plugin install kubernetes-service
ibmcloud plugin install cos
```

Verify:

```bash
ibmcloud -v  # should be ≥ 2.20
helm version
kubectl version --client
```

***

### 2 – Authenticate & target a resource group

```bash
ibmcloud login -r $REGION --sso  # or remove --sso for API‑key login
ibmcloud resource group-create $RG_NAME || true
ibmcloud target -g $RG_NAME
```

***

### 3 – Create networking (VPC + Subnet + Gateway)

```bash
ibmcloud is vpc-create $VPC_NAME --resource-group-name $RG_NAME
ibmcloud is public-gateway-create $GW_NAME $VPC_NAME $ZONE --resource-group-name $RG_NAME
ibmcloud is subnet-create $SUBNET_NAME $VPC_NAME --zone $ZONE \
  --ipv4-address-count 256 --pgw $GW_NAME --resource-group-name $RG_NAME
```

Grab IDs for automation:

```bash
export VPC_ID=$(ibmcloud is vpcs --json | jq -r '.[] | select(.name=="'$VPC_NAME'") | .id')
export SUBNET_ID=$(ibmcloud is subnets --json | jq -r '.[] | select(.name=="'$SUBNET_NAME'") | .id')
```

***

### 4 – Provision the Kubernetes cluster

```bash
ibmcloud ks cluster create vpc-gen2 \
  --name $CLUSTER_NAME \
  --zone $ZONE \
  --version $K8S_VERSION \
  --flavor $FLAVOR \
  --workers $WORKERS \
  --vpc-id $VPC_ID \
  --subnet-id $SUBNET_ID \
  --disable-outbound-traffic-protection
```

Configure `kubectl`:

```bash
ibmcloud ks cluster ls
export CLUSTER_ID=$(ibmcloud ks cluster ls --output json --provider vpc-gen2 | jq -r '.[] | select(.name=="'$CLUSTER_NAME'") | .id')
ibmcloud ks cluster config --cluster $CLUSTER_ID
```

***

### 5 – Provision PostgreSQL

```bash
ibmcloud resource service-instance-create $DB_INSTANCE_NAME \
  databases-for-postgresql standard $REGION \
  --service-endpoints public --parameters '{"location_hardware":"virtual","version":"16"}'
# Wait until the instance becomes AVAILABLE
ibmcloud resource service-instance $DB_INSTANCE_NAME
```

Create credentials:

```bash
ibmcloud resource service-key-create ${DB_INSTANCE_NAME}-credentials \
  --instance-name $DB_INSTANCE_NAME --parameters '{"HMAC":true}'
export DATABASE_USERNAME=$(ibmcloud resource service-key ${DB_INSTANCE_NAME}-credentials --output json | jq -r '.[0].credentials.connection.postgres.authentication.username')
export DATABASE_PASSWORD=$(ibmcloud resource service-key ${DB_INSTANCE_NAME}-credentials --output json | jq -r '.[0].credentials.connection.postgres.authentication.password')
export DATABASE_HOST=$(ibmcloud resource service-key ${DB_INSTANCE_NAME}-credentials --output json | jq -r '.[0].credentials.connection.postgres.hosts[0].hostname')
export DATABASE_PORT=$(ibmcloud resource service-key ${DB_INSTANCE_NAME}-credentials --output json | jq -r '.[0].credentials.connection.postgres.hosts[0].port')
export DATABASE_NAME=$(ibmcloud resource service-key ${DB_INSTANCE_NAME}-credentials --output json | jq -r '.[0].credentials.connection.postgres.database')
```

***

### 6 – Provision Object Storage

```bash
ibmcloud resource service-instance-create $COS_INSTANCE_NAME \
  cloud-object-storage standard global -g $RG_NAME
ibmcloud resource service-key-create ${COS_INSTANCE_NAME}-credentials Writer \
  --instance-name $COS_INSTANCE_NAME --parameters '{"HMAC":true}'
export STORAGE_IBM_COS_API_KEY=$(ibmcloud resource service-key ${COS_INSTANCE_NAME}-credentials --output json | jq -r '.[0].credentials.apikey')
export STORAGE_IBM_COS_SERVICE_INSTANCE_ID=$(ibmcloud resource service-instance $COS_INSTANCE_NAME --output json | jq -r '.[0].id')
export STORAGE_IBM_COS_SERVICE_ENDPOINT="https://s3.${REGION}.cloud-object-storage.appdomain.cloud"
ibmcloud cos bucket-create --bucket $COS_BUCKET --region $REGION --ibm-service-instance-id $STORAGE_IBM_COS_SERVICE_INSTANCE_ID
```

***

### 7 – Install Dynamiq platform

Install Fission CRDs + Dynamiq dependencies:

```bash
kubectl create -k "github.com/fission/fission/crds/v1?ref=v1.20.5"
helm upgrade --install fission fission-all \
  --repo https://fission.github.io/fission-charts/ \
  --namespace fission --create-namespace \
  --set routerServiceType=ClusterIP \
  --set defaultNamespace=apps \
  --set analytics=false --wait
```

***

### 8 – Create production secrets

Generate secure keys:

```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')
# SMTP & HF tokens
export SMTP_HOST="<SMTP_HOST>"
export SMTP_PORT="<SMTP_PORT>"
export SMTP_USERNAME="<SMTP_USERNAME>"
export SMTP_PASSWORD="<SMTP_PASSWORD>"
export HUGGING_FACE_TOKEN="<HF_TOKEN>"
```

Apply secret:

```bash
kubectl create namespace dynamiq || true
cat <<EOF | envsubst | kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
  name: nexus-secret
  namespace: dynamiq
type: Opaque
stringData:
  DATABASE_HOST: "$DATABASE_HOST"
  DATABASE_PORT: "$DATABASE_PORT"
  DATABASE_SSLMODE: "require"
  DATABASE_NAME: "$DATABASE_NAME"
  DATABASE_SCHEMA: "public"
  DATABASE_USERNAME: "$DATABASE_USERNAME"
  DATABASE_PASSWORD: "$DATABASE_PASSWORD"
  STORAGE_IBM_COS_API_KEY: "$STORAGE_IBM_COS_API_KEY"
  STORAGE_IBM_COS_SERVICE_INSTANCE_ID: "$STORAGE_IBM_COS_SERVICE_INSTANCE_ID"
  STORAGE_IBM_COS_SERVICE_ENDPOINT: "$STORAGE_IBM_COS_SERVICE_ENDPOINT"
  SMTP_HOST: "$SMTP_HOST"
  SMTP_PORT: "$SMTP_PORT"
  SMTP_USERNAME: "$SMTP_USERNAME"
  SMTP_PASSWORD: "$SMTP_PASSWORD"
  SMTP_DEFAULT_FROM: "system@getdynamiq.ai"
  AUTH_ACCESS_TOKEN_KEY: "$AUTH_ACCESS_TOKEN_KEY"
  AUTH_REFRESH_TOKEN_KEY: "$AUTH_REFRESH_TOKEN_KEY"
  AUTH_VERIFICATION_TOKEN_KEY: "$AUTH_VERIFICATION_TOKEN_KEY"
  HUGGING_FACE_TOKEN: "$HUGGING_FACE_TOKEN"
EOF
```

> **Remember** to pass `--set nexus.appSecret=nexus-secret` (or prefixed name) when you deploy Dynamiq’s Helm chart.

Install Dynamiq:

```bash
helm upgrade --install dynamiq getdynamiq/dynamiq \
  --version <CHART_VERSION> \
  --namespace dynamiq \
  --create-namespace \
  --values values-production.yaml \
  --set nexus.appSecret=nexus-secret \
  --wait
```

***

### 9 – Verify installation

```bash
kubectl -n dynamiq get all
# Check that pods are RUNNING and the ingress/LoadBalancer endpoints are assigned
```

Browse to `https://<YOUR_DOMAIN>` and log in with the initial admin user.

***

### 10 – Upgrade

A new chart version appears as an **Update** inside your IBM Cloud Schematics workspace.

1. Go to **Menu ▸ Schematics** → select the workspace.
2. Click **Settings** → **Update**.
3. Pick the desired chart version and confirm.\
   The Dynamiq pods will roll seamlessly with zero‑downtime if you have ≥ 2 replicas per component.

***

### 11 – Uninstall

```bash
helm -n dynamiq uninstall dynamiq  # removes Dynamiq workloads only
# Optional: destroy workspace to delete infra managed by Schematics
ibmcloud schematics workspace destroy --id <WORKSPACE_ID>
```

***

### Appendix A – `values.yaml` reference

| Parameter                           | Description                                               | Default        | Required |
| ----------------------------------- | --------------------------------------------------------- | -------------- | -------- |
| `dynamiq.imageCredentials.username` | Container registry username                               | \`\`           | ✅        |
| `dynamiq.imageCredentials.password` | Container registry password                               | \`\`           | ✅        |
| `nexus.ingress.enabled`             | Expose Nexus API via ingress                              | `true`         | ✅        |
| `nexus.configMapData.DOMAIN`        | Public FQDN mapped in DNS (e.g. **dynamiq.example.com**)  | \`\`           | ✅        |
| `nexus.appSecret`                   | Name of Kubernetes secret with DB/ObjectStore credentials | `nexus-secret` | ✅        |
| `synapse.ingress.enabled`           | Expose WebSocket gateway                                  | `true`         | ✅        |
| `ui.ingress.enabled`                | Expose web UI                                             | `true`         | ✅        |

***

### Appendix B – Security & Compliance controls

* **Network isolation** – all components run inside your VPC with no public ingress unless explicitly enabled.
* **TLS‑only** – Dynamiq forces HTTPS and uses Cert‑Manager (optional) for automated certificate rotation.
* **IAM separation** – each IBM Cloud service instance uses least‑privileged service IDs.

***

#### Need help?

&#x20;Email: [**support@getdynamiq.ai**](mailto:support@getdynamiq.ai)
