Chris Farhood 9c964e7069 docs: rewrite README with current architecture and clusterAccess docs
- Replace all stale references (claude user, k8s/ dir, StatefulSet,
  old Happy paths) with current state (app user, Helm chart, Deployment)
- Add full Helm chart reference table including new clusterAccess option
  with usage examples for all five access levels
- Document Happy Coder daemon setup and startup flow accurately
- Update troubleshooting commands to match actual resource names
- Add Claude authentication notes (browser OAuth + API key fallback)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 11:26:45 -05:00
2026-02-19 19:55:05 -05:00
2026-02-19 19:55:05 -05:00

Antigravity Dev Container

Build and Push

A containerized cloud development environment with web-based GUI access, featuring:

  • VSCode via browser-based VNC (port 5800)
  • Happy Coder AI assistant backed by Claude
  • Automatic GitHub repo cloning on startup
  • Persistent home directory via ReadWriteMany PVC
  • Kubernetes-native Helm chart deployment

Quick Start

1. Create a secret

The secret is picked up automatically via envFrom. Keys recognised:

Key Purpose
GITHUB_TOKEN PAT for private repo access (repo scope)
VNC_PASSWORD Password for the VNC web UI
ANTHROPIC_API_KEY API key — alternative to browser-based Claude login
kubectl create secret generic devcontainer-mydev-secrets-env \
  --from-literal=GITHUB_TOKEN='ghp_...' \
  --from-literal=VNC_PASSWORD='changeme'

Or use SealedSecrets:

kubectl create secret generic devcontainer-mydev-secrets-env \
  --from-literal=GITHUB_TOKEN='ghp_...' \
  --from-literal=VNC_PASSWORD='changeme' \
  --dry-run=client -o yaml | \
  kubeseal --format=yaml | kubectl apply -f -

2. Deploy with Helm

helm install mydev ./chart \
  --set name=mydev \
  --set githubRepo=https://github.com/youruser/yourrepo

3. Access

# Local port-forward
kubectl port-forward deployment/devcontainer-mydev 5800:5800
open http://localhost:5800

Or configure an ingress / Gateway API HTTPRoute pointing at port 5800.

4. Authenticate Claude

On first launch, open a terminal in the VSCode GUI and run:

claude

A Chrome browser window will open inside VNC for the Claude Max OAuth login. Credentials are stored on the home PVC and persist across pod restarts.


Helm Chart Reference

Core values

Value Default Description
name "" Instance name — used in all resource names (devcontainer-{name})
githubRepo "" Repository to clone into /workspace on startup
image.repository ghcr.io/cpfarhood/devcontainer Container image
image.tag latest Image tag

Happy Coder

Value Default Description
happyServerUrl https://happy.farh.net Happy Coder server endpoint
happyWebappUrl https://happy-coder.farh.net Happy Coder webapp URL
happyHomeDir /workspace/.happy Happy runtime state directory (ephemeral — lives in emptyDir)
happyExperimental true Enable experimental Happy features

Kubernetes cluster access

The clusterAccess value provisions a ServiceAccount, Role/ClusterRole, and binding so the devcontainer pod can interact with the Kubernetes API. The default is none — no RBAC resources are created.

Value Scope Verbs
none (default) no access
readonlyns release namespace get, list, watch
readwritens release namespace *
readonly cluster-wide get, list, watch
readwrite cluster-wide *
# Give the pod read-only access to its own namespace
helm install mydev ./chart \
  --set name=mydev \
  --set githubRepo=https://github.com/youruser/yourrepo \
  --set clusterAccess=readonlyns

With any non-none value, a ServiceAccount named devcontainer-{name} is created and set as the pod's serviceAccountName, so kubectl and any in-cluster API calls use it automatically.

Display and resources

Value Default Description
display.width 1920 VNC width (px)
display.height 1080 VNC height (px)
secureConnection 0 Set to 1 if TLS is not terminated upstream
userId 1000 UID for the app user
groupId 1000 GID for the app user
storage.size 32Gi Home PVC size
storage.className ceph-filesystem StorageClass (must be ReadWriteMany)
resources.requests.memory 2Gi
resources.requests.cpu 1000m
resources.limits.memory 8Gi
resources.limits.cpu 4000m
envSecretName devcontainer-{name}-secrets-env Override the secret name

Architecture

Startup flow

Container start (as app user, UID 1000)
  → cont-init.d/20-fix-user-shell.sh   — fix shell/home on baseimage-gui app user
  → /startapp.sh
      → init-repo.sh
          → clone / pull GITHUB_REPO into /workspace/{repo}
          → happy daemon start          — starts Happy Coder background daemon
      → code --new-window /workspace/{repo}   — opens VSCode in VNC

Storage

Mount Source Persistence
/home ReadWriteMany PVC (userhome-{name}) Survives pod restarts — stores Claude credentials, dotfiles, git config
/workspace emptyDir Ephemeral — repo is re-cloned on each pod start

Happy Coder's runtime state (HAPPY_HOME_DIR) is kept in /workspace/.happy so stale lock files never survive a pod restart.


Troubleshooting

Happy Coder daemon not starting

# Check daemon status
happy daemon status

# Start manually (also clears any stale lock)
happy daemon start

# View daemon logs
ls ~/.happy/logs/ || ls /workspace/.happy/logs/

Claude not authenticated

Browser-based OAuth login is the primary method (works inside VNC via the Chrome wrapper). If you prefer API key auth:

kubectl patch secret devcontainer-mydev-secrets-env \
  --type='json' \
  -p='[{"op":"add","path":"/data/ANTHROPIC_API_KEY","value":"'$(echo -n "sk-ant-..." | base64)'"}]'

Then restart the pod to pick up the new env var.

VNC not loading

kubectl port-forward deployment/devcontainer-mydev 5800:5800
kubectl logs deployment/devcontainer-mydev
kubectl describe pod -l instance=mydev

Repository not cloning

kubectl logs deployment/devcontainer-mydev | grep "Repository Initialization"
kubectl exec deployment/devcontainer-mydev -- env | grep GITHUB

Local Docker run

docker run -d \
  -p 5800:5800 \
  -e GITHUB_REPO="https://github.com/youruser/yourrepo" \
  -e GITHUB_TOKEN="ghp_..." \
  -e VNC_PASSWORD="changeme" \
  -v $(pwd)/home:/home \
  ghcr.io/cpfarhood/devcontainer:latest

Building

docker build -t ghcr.io/cpfarhood/devcontainer:latest .
docker push ghcr.io/cpfarhood/devcontainer:latest

The image is also built and pushed automatically by CI on every push to main and on version tags (v*).


Credits

S
Description
GUI-based dev container with Antigravity IDE and Happy Coder AI assistant
Readme 591 KiB
2026-03-11 12:05:49 +00:00
Languages
Dockerfile 44.8%
Shell 32.8%
Makefile 12.5%
Smarty 9.9%