Run AI coding agents in OpenShift/Kubernetes pods with persistent sessions, credential management, and network filtering.
- oc CLI - OpenShift command-line tools installed and in PATH
- Cluster Access - Logged in to an OpenShift cluster (
oc login) - gcloud credentials - Vertex AI authentication at
~/.config/gcloud
# Verify cluster connectivity
oc whoami
oc project
# Create a session and push code in one step
paude create --backend=openshift --git
# Or with explicit namespace
paude create --backend=openshift --openshift-namespace=my-namespace
# Connect to the running session
paude connect- Binary Build: Container image is built on-cluster via OpenShift BuildConfig and
oc start-build - Pod Creation: A pod is created with persistent storage and credentials injected
- Session Persistence: tmux inside the pod preserves your agent session across reconnects
- Git-Based Sync: Use
--giton create orpaude remote addandgit push/pullto sync code - Network Filtering: NetworkPolicy restricts pod egress to approved destinations
Paude uses a unified session model across all backends. Sessions are persistent by default, surviving pod restarts via StatefulSets and PersistentVolumeClaims.
# Create session and push code in one step
paude create my-project --backend=openshift --git
# Connect and work with the agent... then detach with Ctrl+b d
paude connect my-project
# Pull changes made by the agent
git pull paude-my-project main
# Stop to save cluster resources (scales to 0, preserves PVC)
paude stop my-project --backend=openshift
# Restart - instant resume, everything still there
paude start my-project --backend=openshift
# List all sessions
paude list --backend=openshift
# Delete session completely (removes StatefulSet + PVC)
paude delete my-project --confirm --backend=openshift| State | StatefulSet Replicas | Pod | PVC | Files |
|---|---|---|---|---|
| Created | 1 | Running | Bound | Push via git |
| Stopped | 0 | None | Retained | Preserved |
| Started | 1 | Running | Bound | Preserved |
| Deleted | Deleted | Deleted | Deleted | Gone |
# Custom PVC size
paude create my-project --backend=openshift --pvc-size=50Gi
# Custom storage class
paude create my-project --backend=openshift --storage-class=fast-ssd| Flag | Description | Default |
|---|---|---|
--backend=openshift |
Use OpenShift backend | podman |
--openshift-namespace=NAME |
Kubernetes namespace | current context namespace |
--openshift-context=NAME |
kubeconfig context | current |
--allowed-domains all |
Disable network filtering | default (vertexai + python + github + agent-specific) |
--yolo |
Skip agent permission prompts | False |
Notes:
- The namespace must already exist - paude will not create namespaces
- If no namespace is specified, paude uses the current namespace from your kubeconfig context
| Variable | Description | Default |
|---|---|---|
PAUDE_REGISTRY |
Container registry for pulling and building base images | quay.io/bbrowning |
Credentials are stored in RAM-only storage for enhanced security:
Security Model:
- Credentials use a tmpfs (Memory-backed) emptyDir volume at
/credentials - Credentials never persist to disk - stored only in RAM
- Automatically cleared when pod stops or restarts
- Cannot be recovered from PVC snapshots or disk images
- Refreshed on every
paude connectfor fresh tokens
Configuration Sync:
Minimal configuration is synced via oc cp to tmpfs on session start:
- Stub GCP ADC (sentinel values — real auth handled by proxy sidecar)
~/.gitconfig→ Git identity configuration~/.config/git/ignore→ Global gitignore- Agent sandbox config script (onboarding/trust prompt suppression)
- Cursor auth.json (for Cursor agent only)
Agent config directories (~/.claude/, ~/.gemini/, etc.) are not synced from the host. The agent starts with vanilla config — the sandbox config script generates the minimum viable settings. This improves security (no host credentials leak into containers) and simplifies the path to GitOps-compatible session creation.
Credential Refresh:
- First connect (after pod start): Full sync of stub credentials, gitconfig, and sandbox config
- Reconnect (subsequent connects): Stub credentials and sandbox config refreshed (fast)
By default, sessions run with restricted network access:
- Allowed: DNS resolution, Vertex AI APIs (.googleapis.com), PyPI (.pypi.org), GitHub (github.com and related subdomains), plus agent-specific domains
- Blocked: All other external traffic
NetworkPolicy restricts pod egress to DNS and the proxy only. The proxy then enforces fine-grained domain filtering via its allowlist configuration. Use --allowed-domains all to disable filtering for unrestricted access.
Pods run with:
- Non-root user
- Dropped capabilities
- Read-only credential mounts
Install the OpenShift CLI:
# macOS
brew install openshift-cli
# Linux (download from Red Hat)
# https://mirror.openshift.com/pub/openshift-v4/clients/ocp/latest/Login to your cluster:
oc login https://api.your-cluster.example.com:6443Paude requires the namespace to already exist - it will not create namespaces. Either:
- Switch to an existing namespace:
oc project my-existing-namespace- Or specify an existing namespace explicitly:
paude create --backend=openshift --openshift-namespace=my-namespace- Or ask an administrator to create the namespace for you.
Paude builds container images on-cluster using OpenShift Binary Build (BuildConfig + oc start-build). If the build fails:
# List BuildConfigs (names are dynamically generated as paude-<hash>)
oc get bc -n <namespace>
# Check build logs (use the actual BuildConfig name from the list above)
oc logs -f bc/<bc-name> -n <namespace>
# List builds and their status
oc get builds -n <namespace>
# Describe a failed build for events and errors
oc describe build <build-name> -n <namespace>Common causes:
- Insufficient cluster resources for the build pod
- BuildConfig not created (check
oc get bc -n <namespace>) - Image stream issues (check
oc get is -n <namespace>)
Check pod events:
oc describe pod paude-<session-name>-0 -n <namespace>Common causes:
- Insufficient cluster resources
- Image pull failures
- PVC provisioning issues
Paude uses git for code synchronization. Set up the remote first:
paude remote add SESSION_IDThen use standard git commands:
git push paude-SESSION_ID main # Push code to session
git pull paude-SESSION_ID main # Pull changes from sessionFor merge conflicts, use normal git workflows (rebase, merge, etc.).
┌─────────────────────────────────────────────────────────┐
│ OpenShift Cluster │
│ ┌────────────────────────────────────────────────────┐ │
│ │ paude namespace │ │
│ │ ┌──────────────────┐ ┌───────────────────────┐ │ │
│ │ │ paude-session-X │ │ NetworkPolicy │ │ │
│ │ │ ┌────────────┐ │ │ (egress filtering) │ │ │
│ │ │ │ paude │ │ └───────────────────────┘ │ │
│ │ │ │ container │ │ │ │
│ │ │ │ + tmux │ │ ┌───────────────────────┐ │ │
│ │ │ └────────────┘ │ │ tmpfs: /credentials │ │ │
│ │ │ │ │ (RAM-only, ephemeral) │ │ │
│ │ │ Mounts: │ │ - stub gcloud creds │ │ │
│ │ │ - /pvc (PVC) │ │ - gitconfig │ │ │
│ │ │ - /credentials │ │ - sandbox config │ │ │
│ │ │ (tmpfs) │ └───────────────────────┘ │ │
│ │ └──────────────────┘ │ │
│ │ ↑ │ │
│ │ │ git push/pull (code) / oc cp (creds) │ │
│ │ ↓ │ │
│ └─────────┼──────────────────────────────────────────┘ │
└────────────┼────────────────────────────────────────────┘
│
┌────────┴────────┐
│ Local Machine │
│ - workspace │
│ - credentials │
│ - paude CLI │
└─────────────────┘
| Feature | Podman | OpenShift |
|---|---|---|
| Session Persistence | Yes (named volumes) | Yes (tmux + PVC) |
| Network Disconnect | Session lost | Session preserved |
| Code Sync | git push/pull | git push/pull |
| Config Sync | oc cp at connect | oc cp at connect |
| Multi-machine | No | Yes |
| Resource Isolation | Container | Pod + namespace |
| Setup Complexity | Low | Medium |
- No SSH mounts: Git push via SSH is not available (same as Podman backend)
- Git workflow required: Must use git to sync code (no automatic file sync)
- Cluster dependency: Requires active OpenShift cluster access