Skip to main content
This page is the CaseBender OpenShift installation profile. It is not a Red Hat certification, OperatorHub listing, or production-certified procedure for every OpenShift minor release. Record the exact OpenShift, CNI, CSI, and registry versions with your validation output. Use the supported on-premises Compose guide when you are not running on OpenShift.
Object storage on OpenShift Data Foundation (ODF) or Ceph RGW is documented separately: OpenShift ODF and Ceph RGW Storage. Follow that page only after this overlay is customized, or use the composed k8s/overlays/openshift-odf-rgw profile instead of local /data PVC storage.

Overview

This guide deploys CaseBender on OpenShift 4.x using the Kustomize overlay in k8s/overlays/openshift. The overlay is built from k8s/base and is designed for the platform restricted-v2 SCC:
  • arbitrary non-root UIDs (no fixed runAsUser)
  • no privilege escalation; all capabilities dropped
  • RuntimeDefault seccomp
  • read-only root filesystems
  • no custom SCC (anyuid, privileged, or host access)
Do not apply k8s/base directly on OpenShift. Ingress is replaced by Routes, placeholder Secrets are stripped from the render, and each container gets an emptyDir at /tmp.

Prerequisites

  1. An OpenShift 4.x cluster with NetworkPolicy enforcement (OpenShift SDN or OVN-Kubernetes).
  2. oc (and kubectl with Kustomize, or oc kustomize).
  3. Cluster-admin (or equivalent) to prepare the namespace, quotas, registry trust, and Routes.
  4. External PostgreSQL 14+ with TLS, and a Redis-compatible queue with TLS. This overlay does not operate the database or Redis lifecycle.
  5. DNS for the Route host and TLS terminated at the OpenShift router (edge).
  6. Signed, digest-pinned CaseBender images (and SBOMs) in a registry the cluster can pull. Production overlays must use digests, not floating tags.
  7. A secrets mechanism (External Secrets Operator, sealed secrets, or an approved injector). The rendered overlay contains no Secret objects.
Optional: a connected transfer host if the cluster is disconnected.

What the overlay deploys

Platform objects: namespace casebender, Routes, NetworkPolicies, ResourceQuota, LimitRange, PodDisruptionBudgets, and (default profile) an RWX PVC casebender-data mounted at /data on web. See Integration Execution Plane for connector-worker secrets and queue names.

Step 1: Install the OpenShift CLI

Confirm Kustomize:

Step 2: Prepare the cluster

Namespace and SCC

The overlay creates namespace casebender. Workloads must run as restricted-v2 with an arbitrary UID:
Do not grant anyuid or a custom SCC to make a fixed UID work. Images must run as an arbitrary UID, keep writable paths group 0 / g=u, listen on an unprivileged port, and write only to /tmp or /data.

Storage choice

Pick one: The default overlay sets STORAGE_PROVIDER=local and STORAGE_PATH=/data. The PVC StorageClass must support ReadWriteMany if you run more than one web replica. If it does not, use object storage and the ODF overlay. CaseBender never creates buckets. ODF/RGW steps: OpenShift ODF and Ceph RGW Storage.

ClamAV

Production user uploads stay quarantined until an external clamd scan. Compose bundles ClamAV; OpenShift does not. Provide CLAMD_HOST / TLS or CLAMD_SOCKET_PATH (sidecar). If the scanner is missing, attachments return HTTP 409 until scan/promotion succeeds.

Network

Replace bootstrap 0.0.0.0/0 CIDRs in k8s/overlays/openshift/network-policy.yaml with approved ranges for PostgreSQL, Redis, registry, identity, storage, and connectors before production. The ODF overlay additionally restricts RGW egress; do not restore wildcard egress.

Step 3: Customize the overlay

Copy k8s/overlays/openshift (or openshift-odf-rgw) into an environment-specific directory. Do not commit customer hostnames or secrets into the product repository.
  1. Images — in kustomization.yaml, replace every registry.example.com/casebender/... and replace-with-release with the mirrored digest.
  2. Route host — in route.yaml, set spec.host on all Routes to the approved DNS name (default placeholder casebender.apps.example.com). Paths: / (web), /api/v1 (API), /api/v1/ingest and /api/ingest (ingestion), /api/openapi.json and /docs (API docs).
  3. PVC (local storage profile) — in platform-controls.yaml, set storageClassName and size.
  4. ConfigMap — non-secret settings (casebender-config): public URL, storage provider, feature flags. TLS endpoints only in production.
  5. NetworkPolicy — approved CIDRs only.

Step 4: Provision secrets

The overlay deletes the base placeholder Secret from the render. Create casebender-secrets in namespace casebender before the first rollout. k8s/overlays/openshift/external-resources.example.yaml is an External Secrets example (excluded from Kustomize). Adapt it to your SecretStore. Typical keys:
  • POSTGRES_PRISMA_URL
  • REDIS_URL
  • AUDIT_INTEGRITY_SECRET
  • FIELD_ENCRYPTION_KEY
  • CREDENTIAL_ENCRYPTION_KEY
  • WEBHOOK_KEY_PEPPER
  • CONNECTOR_BUNDLE_SIGNING_KEY
  • OAUTH_BROKER_SECRET
Preserve AUDIT_INTEGRITY_SECRET across upgrades. Rotating it invalidates the audit chain. Never put secret values in ConfigMaps, Kustomize patches, or git. Confirm the Secret exists and the render has no Secret objects:

Step 5: Render, validate, and apply

From the repository root (or your copied overlay tree):
For ODF/RGW storage, render k8s/overlays/openshift-odf-rgw instead (it composes the OpenShift overlay). Provision ObjectBucketClaims before application startup. The adapter never creates buckets. Web runs database migrations on startup. You do not run Prisma by hand.

Step 6: Verify

Then confirm:
  • every pod has a non-zero arbitrary UID and restricted-v2
  • writes to the root filesystem fail; /tmp (and /data if used) succeed
  • Routes serve HTTPS only; HTTP redirects
  • default-deny NetworkPolicy blocks unapproved traffic
  • /api/health/live and /api/health/ready behave as documented in Storage Health and Troubleshooting
  • a test upload is SHA-256 verified and, with clamd, leaves quarantine
Archive the rendered manifest, image digests, validate.sh output, and SCC review with the change record. Cluster execution is required before calling a release “OpenShift validated.”

Disconnected registry

  1. On a connected host, download images, checksums, signatures, and SBOMs.
  2. Verify, then scan the mirrored digest under your policy.
  3. oc image mirror (or the approved tool) by digest.
  4. Configure ImageDigestMirrorSet / ImageTagMirrorSet if required; wait for MachineConfigPool convergence.
  5. Create a namespace pull secret and link it for pull. Do not commit it.
Re-render and confirm every image is the mirror digest. Do not fall back to a public registry.

Proxy and custom CA

Cluster-wide proxy is a cluster-admin change (oc edit proxy/cluster). If workloads need HTTPS_PROXY / HTTP_PROXY / NO_PROXY, include cluster domains, service and pod CIDRs, PostgreSQL, Redis, and storage. Add an egress rule for the proxy CIDR and port; the bootstrap policy does not open common proxy ports. For an internal CA, mount only the CA file (do not replace the image trust store):
Mount read-only at /etc/pki/ca-trust/source/anchors/casebender-ca.crt (subPath) and set NODE_EXTRA_CA_CERTS to that path. Restart and test TLS to PostgreSQL, Redis, storage, OIDC, and connectors. Never disable TLS verification as a CA workaround.

Backup, upgrade, and rollback

Back up a consistency set: PostgreSQL, object storage (or /data snapshot), secret versions (not plaintext in the archive), rendered manifest, and Route/NetworkPolicy. See Storage Backup and Restore. Before upgrade, save live objects and the target render:
Roll stateless workers before externally exposed services. Application rollback is allowed only while the database and object format stay backward compatible. If a non-reversible migration ran, restore; do not point old images at a new schema.

Troubleshooting

  1. Pods crash with permission denied / SCC
    Confirm restricted-v2, no fixed UID, group-writable image paths, and /tmp emptyDir.
  2. Route 503 / no backends
    Check probes, Service port (webapp often 80 → container), and rollout.
  3. Attachments HTTP 409 / “Image unavailable”
    Worker malware scanner not reachable, or storage mutation not running. Restore clamd; objects stay quarantined until a clean verdict.
  4. Readiness 503 / storage
    Local PVC vs ODF mismatch, missing buckets, or TLS/CA. Use Storage Health.
  5. Audit errors after upgrade
    AUDIT_INTEGRITY_SECRET changed. Restore the previous value.