GitOps-driven Kubernetes platform for deploying and operating OpenClaw — an open-source, self-hosted AI agent runtime. Runs OpenClaw as a standalone StatefulSet with K8s-native security (NetworkPolicy, securityContext, Pod Security Standards). This repository is the single source of truth for cluster state.
Future work: We are evaluating OpenShell sandbox isolation and the NemoClaw reference architecture for kernel-level isolation (Landlock, seccomp-BPF, network namespaces). These are not yet integrated — see the project roadmap for updates.
Kinder or KIND multi-node (1 control-plane + 2 workers)
→ [Kinder: built-in MetalLB, Envoy GW controller, cert-manager]
→ [KIND: ArgoCD-managed MetalLB, Envoy GW controller, cert-manager]
→ Envoy Gateway DaemonSet + hostPort (ArgoCD-managed, both providers)
→ ArgoCD (App of Apps pattern, self-managing)
→ OpenClaw Gateway (StatefulSet, single replica, PVC-backed)Everything deploys from a single root Application through ArgoCD sync waves:
| Wave | Component | Purpose |
|---|---|---|
| -10 | ArgoCD self-management | Must exist before managing anything else |
| -5 | MetalLB | LoadBalancer IPs needed by Gateway |
| -4 | Envoy Gateway controller | Gateway API CRDs and controller |
| -3 | Sealed Secrets | Decrypt SealedSecrets before workloads need them |
| -2 | cert-manager | TLS certificate infrastructure |
| -1 | Envoy Gateway config | Gateway + HTTPRoute resources (needs CRDs from -4) |
| +10 | OpenClaw Gateway | AI agent runtime with PVC-backed storage |
When using Kinder (default), waves -5 (MetalLB), -4 (Envoy Gateway controller), and -2 (cert-manager) are skipped -- these components are provided by Kinder as built-in addons.
- Docker Desktop
- Kinder (default) OR KIND v0.20+
- kubectl
- kubeseal (for secret management)
- ArgoCD CLI (for sync operations and status checks)
- Kubeconform (for manifest validation)
- BATS (for running tests)
make hooks # Install git pre-commit hooksYou can verify the hook is installed with:
test -x .git/hooks/pre-commit && echo "installed" || echo "not installed"make up # Bootstrap with Kinder (default)
CLUSTER_PROVIDER=kind make up # Bootstrap with KIND insteadThis creates a 3-node cluster (1 control-plane + 2 workers), installs ArgoCD, and deploys the full stack. With Kinder, MetalLB, Envoy Gateway controller, and cert-manager are provided as built-in addons; with KIND, all infrastructure is ArgoCD-managed. Idempotent -- safe to run multiple times.
After bootstrap completes (~4 minutes), OpenClaw is accessible at http://localhost.
| Kinder (default) | KIND (opt-in) | |
|---|---|---|
| MetalLB | Built-in addon | ArgoCD-managed |
| Envoy Gateway controller | Built-in addon | ArgoCD-managed |
| cert-manager | Built-in addon | ArgoCD-managed |
| Envoy DaemonSet + hostPort | ArgoCD-managed | ArgoCD-managed |
| Sealed Secrets | ArgoCD-managed | ArgoCD-managed |
| OpenClaw | ArgoCD-managed | ArgoCD-managed |
| Bootstrap steps | Fewer (skips addon infrastructure) | Full v1.0 flow |
Both providers produce identical cluster topology (1 control-plane + 2 workers) and OpenClaw is accessible at http://localhost after bootstrap.
Once the cluster is running, configure OpenClaw through its CLI:
# 1. Run the onboarding wizard (configures LLM provider keys, gateway settings)
make openclaw-onboard
# 2. Open the authenticated dashboard (extracts token and opens browser)
make openclaw-dashboard
# 3. Click "Connect" in the dashboard, then approve the device pairing request
make openclaw-cli CMD="devices list"
make openclaw-cli CMD="devices approve <requestId>"
# 4. Click "Connect" again — status should go OnlineLLM provider keys (Anthropic, OpenAI, etc.) are configured during onboarding and stored on the PVC — they are not set in deployment manifests or K8s Secrets.
make openclaw-channels # List configured channels
make openclaw-cli CMD="channels login" # WhatsApp QR login
make openclaw-cli CMD="channels add --channel telegram --token YOUR_TOKEN"
make openclaw-cli CMD="channels add --channel discord --token YOUR_TOKEN"
make openclaw-devices # List paired devices
make openclaw-cli CMD="devices approve <requestId>" # Approve a deviceRun make openclaw-cli without arguments to see all available commands.
make down # Destroy the cluster (sealing keys preserved at ~/.pincer/)
make clean # Destroy cluster + remove Docker network and backups
make reset # Full teardown + rebuild from scratchRun make or make help to see all targets:
| Target | Description |
|---|---|
| Lifecycle | |
make up |
Create cluster and deploy everything (idempotent) |
make up-verbose |
Bootstrap with verbose output |
make down |
Destroy the cluster (preserves sealing keys) |
make clean |
Destroy cluster + remove Docker network and backups |
make reset |
Full reset: teardown --clean then bootstrap |
| Development | |
make hooks |
Install git pre-commit hooks |
make validate |
Validate all Kubernetes manifests (kubeconform) |
make test |
Run all BATS tests (unit + integration) |
make test-unit |
Run unit tests only |
make test-integration |
Run integration tests only |
make check |
Run validation + all tests |
| Operations | |
make doctor |
Check cluster health for current provider |
make status |
Show ArgoCD application sync status |
make sync |
Sync all ArgoCD applications |
make password |
Print the ArgoCD admin password |
make port-forward |
Port-forward to ArgoCD UI (localhost:8080) |
make setup-mcp |
Generate ArgoCD API token for MCP integration |
make verify-netpol |
Run runtime NetworkPolicy enforcement tests |
make load-image IMAGE=name:tag |
Load a local image into KIND |
make seal FILE=secret.yaml |
Encrypt a secret with kubeseal |
make logs |
Tail OpenClaw gateway logs |
make pods |
List all pods across namespaces |
make version |
Show cluster and tool versions |
| OpenClaw CLI | |
make openclaw-onboard |
Run onboarding wizard (interactive) |
make openclaw-dashboard |
Show dashboard info |
make openclaw-channels |
List configured channels |
make openclaw-devices |
List paired devices |
make openclaw-health |
HTTP health check |
make openclaw-shell |
Interactive shell in the OpenClaw pod |
make openclaw-cli CMD="..." |
Run any OpenClaw CLI command |
pincer-ops/
├── Makefile # Developer workflow (make help)
├── bootstrap/
│ ├── kind/ # KIND-specific ArgoCD Applications
│ │ ├── root-app.yaml # Root Application (includes all infra)
│ │ ├── infra-*.yaml # Infrastructure Applications (all components)
│ │ └── workload-openclaw.yaml # OpenClaw Application
│ ├── kinder/ # Kinder-specific ArgoCD Applications
│ │ ├── root-app.yaml # Root Application (excludes Kinder-provided infra)
│ │ ├── infra-*.yaml # Kinder-compatible infrastructure Applications
│ │ └── workload-openclaw.yaml # OpenClaw Application
├── infrastructure/
│ ├── metallb/ # MetalLB L2 LoadBalancer
│ ├── envoy-gateway/ # Gateway API implementation
│ ├── sealed-secrets/ # Bitnami Sealed Secrets controller
│ └── cert-manager/ # TLS certificate management
├── workloads/
│ └── openclaw/
│ ├── base/ # StatefulSet, Service, ConfigMap, HTTPRoute, NetworkPolicy
│ └── overlays/dev/ # Kustomize dev overlay
├── cluster/
│ ├── kind-config.yaml # KIND cluster definition (3 nodes)
│ └── kinder-config.yaml # Kinder cluster definition (3 nodes + addons)
├── scripts/
│ ├── bootstrap.sh # Full cluster creation + deployment
│ ├── teardown.sh # Cluster destruction
│ ├── setup-mcp.sh # MCP server configuration for Claude Code
│ ├── validate-manifests.sh # CI manifest validation (kubeconform)
│ ├── verify-networkpolicy.sh # Runtime NetworkPolicy enforcement tests
│ ├── run-tests.sh # BATS test runner
│ ├── lib/common.sh # Shared helper library
│ ├── lib/sealed-secrets.sh # Sealing key backup/restore
│ └── hooks/ # Pre-commit hook for plaintext Secret detection
└── tests/
├── test_helper.bash # Common BATS test infrastructure
├── unit/ # Unit tests (107 tests)
└── integration/ # Integration tests (10 tests)kubectl apply -f bootstrap/kinder/root-app.yaml # Kinder (default)
kubectl apply -f bootstrap/kind/root-app.yaml # KINDThis single command must reconstruct the complete cluster state for the selected provider. Every resource in this repository is either the root Application or discoverable by ArgoCD through it.
- Gateway API over ingress-nginx — Envoy Gateway implements the Gateway API standard, avoiding a future migration from the deprecated Ingress API
- Kustomize over Helm — Declarative overlays without template complexity; better fit for GitOps state repositories
- SealedSecrets over SOPS/External Secrets — Encrypted secrets committed directly to Git; simpler workflow for single-cluster
- StatefulSet for OpenClaw — Single-replica with PVC for the file-backed monolith; K8s-native security (NetworkPolicy, seccomp, capabilities)
- DaemonSet with hostPort for Envoy — Only viable path for
localhostaccess on macOS/KIND (MetalLB VIPs unreachable from host)
Claude Code can query cluster state and manage ArgoCD applications through MCP servers:
make setup-mcpThis enables AI-assisted operations: checking pod status, viewing ArgoCD sync state, reading logs, and triggering syncs — all through conversational commands in Claude Code. MCP defaults to read-only; write operations require explicit opt-in.
- Manifest validation —
make validateruns kubeconform against all local bases (also runs in CI on PRs) - Pre-commit hook — Rejects any commit containing a plaintext
kind: Secretresource (make hooksto install) - BATS test suite — 117 tests covering all manifests and scripts (
make test) - ArgoCD notifications — Webhook triggers on sync failures and health degradation
- Automated backups — CronJobs for OpenClaw PVC data (2AM) and sealing key export (3AM)
# Cluster operations
make status # ArgoCD sync status
make sync # Sync all apps
make password # ArgoCD admin password
make port-forward # ArgoCD UI at localhost:8080
make logs # Tail OpenClaw logs
make pods # List all pods
make load-image IMAGE=app:dev # Load image into KIND
make seal FILE=secret.yaml # Encrypt a secret
# OpenClaw management
make openclaw-onboard # First-time setup wizard
make openclaw-health # Authenticated health check
make openclaw-channels # List channels
make openclaw-cli CMD="channels login" # WhatsApp QR login
make openclaw-shell # Shell into the pod
# Validation
make validate # Validate manifests
make verify-netpol # Test NetworkPolicy enforcement
make check # Validate + run all tests- Application source code or Dockerfiles — this is a pure GitOps state repo
- CI pipelines that build images — causes infinite GitOps loops
- Horizontal scaling config — OpenClaw is a single-instance monolith
- Production cloud manifests — this is local-first on Kinder/KIND
See LICENSE.