
Operating on Paperclip
Last updated 2026-07-15 ·4769745
This is the operational companion to Paperclip — AI Agent Orchestrator. That post covers architecture and deployment. This one covers health checks, database access, the shell sidecar, and common failure modes.
graph LR
subgraph ns["paperclip-system namespace"]
pc["Paperclip Pod<br/>gpu-1 pinned"]
pg["PostgreSQL Pod<br/>paperclip-db"]
shell["Shell Sidecar<br/>sshd + mosh"]
subgraph pvs["Persistent Volumes"]
pvcData["paperclip-data<br/>10Gi RWO"]
pvcDB["paperclip-db<br/>5Gi RWO"]
pvcShell["paperclip-shell-home<br/>20Gi RWO"]
end
subgraph secrets["External Secrets"]
llm["paperclip-llm-key<br/>→ LiteLLM"]
auth["paperclip-auth<br/>→ session signing"]
brave["paperclip-brave<br/>→ Brave Search"]
resend["paperclip-resend<br/>→ Resend email"]
end
end
subgraph infra["Infrastructure"]
infisical["Infisical<br/>Secret Store"]
lb["LoadBalancer<br/>192.168.55.212:3100"]
shellLB["LoadBalancer<br/>192.168.55.221:22"]
end
pc --- pvcData
pg --- pvcDB
shell --- pvcShell
llm & auth & brave & resend -.->|"ESO sync"| infisical
pc --- lb
shell --- shellLB
pc --- pg
What Healthy Looks Like
- The Paperclip pod is
1/1 Runningongpu-1. - PostgreSQL pod is
1/1 Running. - All four ExternalSecrets show
SecretSynced. - The web UI responds at
http://192.168.55.212:3100. - The shell sidecar Load BalancerWhatever spreads traffic across backends and gives them one address. On Frank that is Cilium answering for an address on the LAN, not a cloud appliance. is reachable at
192.168.55.221.
Verify
# All-in-one
kubectl get pods,pvc,externalsecret -n paperclip-system
# Web UI
curl -s -o /dev/null -w "%{http_code}" http://192.168.55.212:3100/
# Database
kubectl exec -it -n paperclip-system \
$(kubectl get pod -n paperclip-system -l app.kubernetes.io/instance=paperclip-db -o name) \
-- psql -U paperclip -d paperclip -c "SELECT count(*) FROM pg_tables;"
# Shell sidecar
ssh agent@192.168.55.221 -t tmux new -A -s mainSteps
Restart Paperclip
kubectl rollout restart deployment/paperclip -n paperclip-system
kubectl get pods -n paperclip-system -wUses Recreate strategy (ReadWriteOnceA PVC access mode that lets exactly one node mount the volume read-write at a time. It is the reason a RollingUpdate deadlocks: the replacement pod cannot mount the volume until the outgoing pod releases it. PersistentVolumeClaimA Kubernetes request for durable storage. The pod names a claim and the storage layer — Longhorn on Frank — binds real disk behind it, so the data outlives the pod. — rolling update would deadlock). Expect 10–30s downtime.
Reconcile Shell Inventory
# After editing apps/paperclip/manifests/configmap-shell-inventory.yaml
kubectl -n paperclip-system exec -c paperclip-shell deploy/paperclip -- \
paperclip-shell-reconcileUse kubectl exec, not SSH — sshd scrubs the container env (no FRANK_C2_TELEGRAM_* means alerts silently fail).
Add a Tool to the Shell Sidecar
- Add entry to the relevant section in
configmap-shell-inventory.yaml(mise:,npm-global:,pipx:,cargo:). - Commit and push (ArgoCD syncs the ConfigMap).
- Run
paperclip-shell-reconcileon the live pod.
Database Backup
# Manual backup via Longhorn UI
# http://192.168.55.201 → Volumes → paperclip-db → Create Backup
# Or via pg_dump
kubectl exec -it -n paperclip-system deploy/paperclip-db-postgresql -- \
pg_dump -U paperclip -d paperclip > paperclip-backup-$(date +%F).sqlRecover
Pod CrashLoopBackOff
kubectl logs -n paperclip-system -l app.kubernetes.io/name=paperclip --previous
kubectl describe pod -n paperclip-system -l app.kubernetes.io/name=paperclip | grep -A 10 EventsCommon causes:
- Database not ready — Paperclip starts before PostgreSQL accepts connections.
- Missing secret —
CreateContainerConfigErrorif a non-optional ExternalSecret fails to sync. Checkkubectl get externalsecret -n paperclip-system. - Out Of MemoryWhat the kernel does when memory runs out — it kills a process by score, not by fault. A container hitting its cgroup limit is killed the same way, which is why the victim is often not the culprit. — Paperclip’s working set grew beyond 12Gi. Check
kubectl top pods -n paperclip-system. If OOMKilled (exit 137), bump the memory limit in the deployment.
Multi-Attach Error on PVC
# Force-delete the stuck pod to release the volume
kubectl delete pod -n paperclip-system -l app.kubernetes.io/name=paperclip \
--grace-period=0 --force
kubectl get pods -n paperclip-system -wExternalSecret Not Syncing
kubectl describe externalsecret paperclip-llm-key -n paperclip-system
kubectl get clustersecretstore infisicalCheck the Infisical secret path hasn’t changed and the ClusterSecretStore is healthy. Retired secrets (paperclip-anthropic, paperclip-ghcr) can be left in place — they’re optional: true.
Shell Sidecar Tool Install Fails
cat /var/log/cont-init.d/40-shell-inventory.logCommon causes:
- Transient registry 5xx — re-run
paperclip-shell-reconcile. - mise activation gap —
mise installdownloads the runtime but doesn’t activate it. Runmise use -g python@3.12 node@20 rust@stablefirst. - Inventory typo — fix the ConfigMap and re-reconcile.
LoadBalancer IP Not Assigned
kubectl get svc paperclip-lb -n paperclip-system
kubectl get ciliumpoolipaddress -A | grep 192.168.55.212Missteps
| What we assumed | Why it was wrong | What it cost |
|---|---|---|
| Paperclip’s working set fits in 1Gi | Initial deployment shipped with 1Gi. Production workflows OOM-killed it repeatedly. The real working set is closer to 12Gi under load. | Two rounds of memory tuning and a node migration to gpu-1. |
| Rolling update works with RWO PVC | RWO allows one writer. A rolling update starts the new pod before the old one terminates — the new pod can’t mount the volume. | Switched to Recreate strategy. |
ssh agent@... paperclip-shell-reconcile fires Telegram alerts on failure | sshd doesn’t inherit K8s envFrom injections. The reconcile runs with no FRANK_C2_TELEGRAM_* — failures exit 0 silently. | Documentation now mandates kubectl exec for reconcile. |
| Adding a service to the host allowlist is a simple config change | A regression from #534 dropped UI domains from the allowlist, breaking external access. | Hot-fix in #535 to restore the missing domains. |
paperclip-anthropic and paperclip-ghcr ExternalSecrets can be safely deleted | They were retired but their optional: true secretRef entries were still referenced. Deleting them caused CreateContainerConfigError on the next deploy. | Left in place with optional: true. |
Quick Reference
| Command | What It Does |
|---|---|
kubectl get pods,pvc,externalsecret -n paperclip-system | Full status |
kubectl rollout restart deployment/paperclip -n paperclip-system | Restart (10–30s downtime) |
kubectl exec -c paperclip-shell deploy/paperclip -- paperclip-shell-reconcile | Reconcile shell tools |
ssh agent@192.168.55.221 | Connect to shell sidecar |
kubectl logs -n paperclip-system -l app.kubernetes.io/name=paperclip --previous | Last pod’s logs |
kubectl describe externalsecret -n paperclip-system <name> | ExternalSecret sync status |
kubectl top pods -n paperclip-system | Resource usage (OOM check) |
