📚Book Signing at KubeCon EU 2026Meet us at Booking.com HQ (Mon 18:30-21:00) & vCluster booth #521 (Tue 24 Mar, 12:30-1:30pm) — free book giveaway!RSVP Booking.com Event
Deployments intermediate ⏱ 20 minutes K8s 1.28+

OpenClaw on OpenShift with SCCs and Routes

Deploy OpenClaw on OpenShift with Security Context Constraints, Routes for TLS termination, and OpenShift-specific considerations for non-root containers.

By Luca Berton 📖 5 min read

💡 Quick Answer: OpenClaw’s official manifests are already OpenShift-compatible — nonroot-v2 SCC, UID 1000, read-only root FS. Create a Route instead of Ingress for TLS termination, and use OpenShift’s built-in image registry for air-gapped deployments.

The Problem

OpenShift adds security layers beyond standard Kubernetes: Security Context Constraints (SCCs), restricted UID ranges, and Routes instead of Ingress. Deploying OpenClaw requires understanding which SCC to use and how to adapt the manifests for OpenShift’s opinionated security model.

The Solution

SCC Compatibility

OpenClaw’s security context already meets restricted-v2 SCC:

# OpenClaw's securityContext matches restricted-v2
securityContext:
  runAsNonRoot: true
  runAsUser: 1000
  allowPrivilegeEscalation: false
  readOnlyRootFilesystem: true
  seccompProfile:
    type: RuntimeDefault
  capabilities:
    drop: ["ALL"]

Verify compatibility:

# Check which SCC the pod uses
oc get pod -n openclaw -l app=openclaw -o jsonpath='{.items[0].metadata.annotations.openshift\.io/scc}'
# Expected: restricted-v2

Deploy on OpenShift

# Create project (namespace)
oc new-project openclaw

# Deploy using the standard script
export ANTHROPIC_API_KEY="sk-ant-..."
./scripts/k8s/deploy.sh

# Or apply manifests directly
oc apply -k scripts/k8s/manifests -n openclaw

Create Route for External Access

Instead of Kubernetes Ingress, use OpenShift Routes:

apiVersion: route.openshift.io/v1
kind: Route
metadata:
  name: openclaw
  namespace: openclaw
spec:
  host: openclaw.apps.cluster.example.com
  to:
    kind: Service
    name: openclaw
    weight: 100
  port:
    targetPort: 18789
  tls:
    termination: edge
    insecureEdgeTerminationPolicy: Redirect
  wildcardPolicy: None
oc apply -f route.yaml
oc get route openclaw -n openclaw
# NAME       HOST                                    PATH   SERVICES   PORT
# openclaw   openclaw.apps.cluster.example.com               openclaw   18789

⚠️ Remember: Change gateway bind from loopback to 0.0.0.0 in the ConfigMap when using Routes.

graph LR
    A[Browser] -->|HTTPS| B[OpenShift Router]
    B -->|TLS Edge Termination| C[Route: openclaw]
    C -->|HTTP| D[Service: openclaw]
    D --> E[Pod with restricted-v2 SCC]
    E --> F[PVC: openclaw-home]

Air-Gapped Deployment

Use OpenShift’s internal registry:

# Mirror OpenClaw image to internal registry
oc import-image openclaw:slim \
  --from=ghcr.io/openclaw/openclaw:slim \
  --confirm -n openclaw

# Update deployment to use internal image
# image: image-registry.openshift-image-registry.svc:5000/openclaw/openclaw:slim

Or use IDMS for transparent mirroring:

apiVersion: config.openshift.io/v1
kind: ImageDigestMirrorSet
metadata:
  name: openclaw-mirror
spec:
  imageDigestMirrors:
    - source: ghcr.io/openclaw
      mirrors:
        - registry.example.com/openclaw

OpenShift-Specific Considerations

FeatureKubernetesOpenShift
External accessIngressRoute
SecurityPSA labelsSCCs
UIDFixed 1000Arbitrary (restricted SCC assigns random UID)
Image registryExternal onlyBuilt-in
TLS certscert-managerBuilt-in via Router

UID Range Handling

OpenShift’s restricted-v2 SCC assigns a random UID from the namespace range. OpenClaw specifies runAsUser: 1000, which works with nonroot-v2 SCC. If your cluster enforces namespace UID ranges:

# Check namespace UID range
oc get namespace openclaw -o jsonpath='{.metadata.annotations.openshift\.io/sa\.scc\.uid-range}'
# e.g., 1000700000/10000

# Option 1: Use nonroot-v2 SCC (allows any non-root UID)
oc adm policy add-scc-to-user nonroot-v2 -z default -n openclaw

# Option 2: Remove runAsUser from deployment (let OpenShift assign)

Common Issues

Pod Fails with SCC Violation

oc describe pod -n openclaw -l app=openclaw | grep -i scc
# If using wrong SCC, adjust:
oc adm policy add-scc-to-user nonroot-v2 -z default -n openclaw

Route Returns 503

The gateway binds to loopback by default. Update ConfigMap:

{
  "gateway": {
    "bind": "0.0.0.0"
  }
}

PVC StorageClass Not Found

OpenShift uses gp3-csi (AWS), managed-premium (Azure), or thin-csi (vSphere):

oc get sc
# Use the default StorageClass or specify explicitly

Best Practices

  • Use Routes, not Ingress — native TLS with auto-renewed certificates
  • Stick with restricted-v2 SCC — OpenClaw manifests are already compliant
  • IDMS for disconnected clusters — transparent image mirroring
  • Don’t grant privileged SCC — OpenClaw doesn’t need it
  • Use OpenShift monitoring — leverage built-in Prometheus for pod metrics
  • NetworkPolicy — OpenShift’s OVN-Kubernetes supports native network policies

Key Takeaways

  • OpenClaw manifests work on OpenShift out of the box with restricted-v2 SCC
  • Use Routes for external access with built-in TLS termination
  • Air-gapped deployments use IDMS or oc import-image for image mirroring
  • Change gateway bind to 0.0.0.0 when exposing via Route
  • OpenShift’s security model is stricter — OpenClaw already meets the requirements
#openclaw #openshift #scc #routes #enterprise
Luca Berton
Written by Luca Berton

Principal Solutions Architect specializing in Kubernetes, AI/GPU infrastructure, and cloud-native platforms. Author of Kubernetes Recipes and creator of CopyPasteLearn courses.

Kubernetes Recipes book cover

Want More Kubernetes Recipes?

This recipe is from Kubernetes Recipes, our 750-page practical guide with hundreds of production-ready patterns.

Luca Berton Ansible Pilot Ansible by Example Open Empower K8s Recipes Terraform Pilot CopyPasteLearn ProteinLens