Add detailed documentation to enable autonomous deployment by other AI agents. New files: - DEPLOYMENT.md: Complete step-by-step deployment guide - Prerequisites checklist - Required vs optional variables clearly marked - All configuration variables documented with examples - Troubleshooting section - Quick deploy example with all values - Configuration summary table - VARIABLES.md: Complete variables reference - All variables listed with file, line, type, description - Required variables clearly marked - Optional variables with defaults - Variables grouped by use case - Quick copy templates - Environment variables reference Updated README.md: - Add links to new documentation files - Clear pointer to DEPLOYMENT.md for deployment These docs enable another Claude Code instance to: 1. Identify all required configuration variables 2. Know where to find/set each variable 3. Understand what values are valid 4. Deploy successfully without human intervention Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
11 KiB
Deployment Guide
This guide provides step-by-step instructions for deploying the Antigravity Dev Container to Kubernetes.
Prerequisites
- Kubernetes cluster with Gateway API support
kubectlconfigured to access your cluster- ReadWriteMany storage class available (e.g.,
ceph-filesystem,nfs-client,efs-sc) - Sealed Secrets controller installed (for secret encryption)
- GitHub Container Registry access (images are public)
Required Configuration Variables
Before deploying, you need to provide the following configuration:
1. Storage Configuration
Variable: storageClassName
Location: k8s/statefulset.yaml (line ~117)
Description: The ReadWriteMany storage class name in your cluster
Example values:
ceph-filesystem(Rook-Ceph)nfs-client(NFS)efs-sc(AWS EFS)azurefile(Azure Files)filestore(GCP Filestore)
How to find your storage class:
kubectl get storageclass
Look for a storage class that supports ReadWriteMany access mode.
2. GitHub Repository (Required)
Variable: github-repo
Location: k8s/configmap.yaml (line ~9)
Description: The GitHub repository URL to clone on container startup
Format: https://github.com/username/repository
Example: https://github.com/cpfarhood/my-project
3. GitHub Token (Optional, for private repos)
Variable: github-token
Location: k8s/secrets-example.yaml (sealed secret)
Description: GitHub Personal Access Token for cloning private repositories
Format: ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Required: Only if cloning a private repository
How to create a GitHub token:
- Go to https://github.com/settings/tokens
- Click "Generate new token (classic)"
- Select scopes:
repo(for private repos) - Generate and copy the token
4. VNC Password (Optional)
Variable: vnc-password
Location: k8s/secrets-example.yaml (sealed secret)
Description: Password for accessing the VNC web interface
Format: Any string (recommend 12+ characters)
Required: Optional, but recommended for security
5. Gateway Configuration (Required for external access)
Variables:
parentRefs.name- Your Gateway resource nameparentRefs.namespace- Namespace where Gateway is deployedhostnames- Domain name for accessing the container
Location: k8s/httproute.yaml
Example:
parentRefs:
- name: cilium-gateway # Your Gateway name
namespace: kube-system # Your Gateway namespace
hostnames:
- "devcontainer.example.com" # Your domain
6. Namespace (Optional)
Variable: namespace
Location: k8s/kustomization.yaml (line ~5)
Description: Kubernetes namespace to deploy into
Default: default
Example: devcontainer, development, team-workspaces
7. Container Image (Optional)
Variable: image
Location: k8s/statefulset.yaml (line ~32)
Description: Docker image to use
Default: ghcr.io/cpfarhood/devcontainer:latest
Format: registry/repository:tag
8. Resource Limits (Optional)
Variables:
resources.requests.memory(default:2Gi)resources.requests.cpu(default:1000m)resources.limits.memory(default:8Gi)resources.limits.cpu(default:4000m)
Location: k8s/statefulset.yaml (lines ~98-103)
9. Happy Coder Configuration (Optional)
Variables:
happy-server-url- Custom Happy server URLhappy-webapp-url- Custom Happy webapp URL
Location: k8s/configmap.yaml (lines ~12-13, commented out)
Default: Uses Happy's default servers
When to set: Only if using a self-hosted Happy instance
Deployment Steps
Step 1: Clone the Repository
git clone https://github.com/cpfarhood/devcontainer.git
cd devcontainer
Step 2: Configure Storage Class
Edit k8s/statefulset.yaml and find the volumeClaimTemplates section (around line 117):
# Find your storage class
kubectl get storageclass
# Edit the file
vi k8s/statefulset.yaml
Change storageClassName to match your cluster:
volumeClaimTemplates:
- metadata:
name: userhome
spec:
accessModes: [ "ReadWriteMany" ]
storageClassName: "ceph-filesystem" # ← Change this
resources:
requests:
storage: 10Gi
Step 3: Configure GitHub Repository
Edit k8s/configmap.yaml:
vi k8s/configmap.yaml
Set your repository URL:
data:
github-repo: "https://github.com/yourusername/yourrepo"
Step 4: Configure Gateway (HTTPRoute)
Edit k8s/httproute.yaml:
# Find your Gateway
kubectl get gateway -A
# Edit the file
vi k8s/httproute.yaml
Update with your Gateway details:
spec:
parentRefs:
- name: your-gateway-name # ← Change this
namespace: your-gateway-namespace # ← Change this
hostnames:
- "devcontainer.yourdomain.com" # ← Change this
Step 5: Create Secrets
Create the secrets for GitHub token and VNC password:
# Create the secret
kubectl create secret generic antigravity-secrets \
--from-literal=github-token='ghp_your_token_here' \
--from-literal=vnc-password='your_vnc_password' \
--dry-run=client -o yaml | \
kubeseal --format=yaml > k8s/sealedsecrets.yaml
# Verify the sealed secret was created
cat k8s/sealedsecrets.yaml
If you don't have Sealed Secrets controller:
Option 1: Install Sealed Secrets
kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.24.0/controller.yaml
Option 2: Use plain secrets (not recommended for production)
kubectl create secret generic antigravity-secrets \
--from-literal=github-token='ghp_your_token_here' \
--from-literal=vnc-password='your_vnc_password'
Step 6: Review Configuration (Optional)
Review and adjust optional settings:
Namespace:
vi k8s/kustomization.yaml
# Change line 5: namespace: default
Resource limits:
vi k8s/statefulset.yaml
# Adjust lines 98-103 for your needs
Step 7: Deploy to Kubernetes
# Deploy everything
kubectl apply -k k8s/
# Or if you changed the namespace
kubectl apply -k k8s/ -n your-namespace
Step 8: Verify Deployment
# Check StatefulSet
kubectl get statefulset antigravity
# Check Pod
kubectl get pods -l app=antigravity
# Check PVC
kubectl get pvc -l app=antigravity
# Check HTTPRoute
kubectl get httproute antigravity
# View logs
kubectl logs antigravity-0
Step 9: Access the Container
Option A: Via HTTPRoute (external access)
# Open in browser
open https://devcontainer.yourdomain.com
Option B: Via Port Forward (local access)
# Port forward to localhost
kubectl port-forward statefulset/antigravity 5800:5800
# Open in browser
open http://localhost:5800
Configuration Summary
Here's a quick checklist of all variables you need to set:
Required Variables
| Variable | File | Line | Example Value |
|---|---|---|---|
storageClassName |
k8s/statefulset.yaml |
~117 | ceph-filesystem |
github-repo |
k8s/configmap.yaml |
~9 | https://github.com/user/repo |
parentRefs.name |
k8s/httproute.yaml |
~8 | cilium-gateway |
parentRefs.namespace |
k8s/httproute.yaml |
~9 | kube-system |
hostnames |
k8s/httproute.yaml |
~10 | devcontainer.example.com |
Optional Variables
| Variable | File | Line | Default | When to Change |
|---|---|---|---|---|
namespace |
k8s/kustomization.yaml |
~5 | default |
If deploying to different namespace |
github-token |
Sealed secret | N/A | None | For private repos |
vnc-password |
Sealed secret | N/A | None | For VNC security |
image |
k8s/statefulset.yaml |
~32 | ghcr.io/cpfarhood/devcontainer:latest |
For specific version or custom build |
resources.* |
k8s/statefulset.yaml |
~98-103 | 2Gi/8Gi RAM, 1/4 CPU | Based on workload needs |
happy-server-url |
k8s/configmap.yaml |
~12 | Default Happy server | For self-hosted Happy |
happy-webapp-url |
k8s/configmap.yaml |
~13 | Default Happy webapp | For self-hosted Happy |
Troubleshooting
Pod not starting
Check events:
kubectl describe pod antigravity-0
Common issues:
- Storage class doesn't support ReadWriteMany
- PVC not binding (check storage class exists)
- Image pull errors (check image name)
Repository not cloning
Check logs:
kubectl logs antigravity-0 | grep -A 10 "Repository Initialization"
Common issues:
- Invalid GitHub URL
- Private repo without token
- Token doesn't have correct permissions
HTTPRoute not working
Check HTTPRoute:
kubectl describe httproute antigravity
Common issues:
- Gateway name/namespace incorrect
- Domain not pointing to Gateway
- TLS certificate not issued
VNC not accessible
Check service:
kubectl get svc antigravity
kubectl describe svc antigravity
Port forward test:
kubectl port-forward antigravity-0 5800:5800
# Try accessing http://localhost:5800
Quick Deploy Example
Complete deployment with all values filled in:
# 1. Set your values
STORAGE_CLASS="ceph-filesystem"
GITHUB_REPO="https://github.com/myuser/myproject"
GITHUB_TOKEN="ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
VNC_PASSWORD="my-secure-password-123"
GATEWAY_NAME="cilium-gateway"
GATEWAY_NAMESPACE="kube-system"
DOMAIN="devcontainer.example.com"
# 2. Update storage class
sed -i "s/storageClassName: .*/storageClassName: \"$STORAGE_CLASS\"/" k8s/statefulset.yaml
# 3. Update GitHub repo
sed -i "s|github-repo: .*|github-repo: \"$GITHUB_REPO\"|" k8s/configmap.yaml
# 4. Update Gateway
sed -i "s/- name: gateway/- name: $GATEWAY_NAME/" k8s/httproute.yaml
sed -i "s/namespace: gateway-system/namespace: $GATEWAY_NAMESPACE/" k8s/httproute.yaml
sed -i "s/antigravity.example.com/$DOMAIN/" k8s/httproute.yaml
# 5. Create sealed secret
kubectl create secret generic antigravity-secrets \
--from-literal=github-token="$GITHUB_TOKEN" \
--from-literal=vnc-password="$VNC_PASSWORD" \
--dry-run=client -o yaml | \
kubeseal --format=yaml > k8s/sealedsecrets.yaml
# 6. Deploy
kubectl apply -k k8s/
# 7. Watch deployment
kubectl get pods -l app=antigravity -w
Updates and Maintenance
Updating the Image
The image is automatically built and pushed to ghcr.io on every commit to main.
To use latest:
kubectl set image statefulset/antigravity \
antigravity=ghcr.io/cpfarhood/devcontainer:latest
To use specific version:
kubectl set image statefulset/antigravity \
antigravity=ghcr.io/cpfarhood/devcontainer:v1.0.0
Changing Repository
Edit the ConfigMap and restart:
kubectl edit configmap antigravity-config
# Change github-repo value
kubectl rollout restart statefulset/antigravity
Scaling
# Scale to multiple instances (each gets own home PVC)
kubectl scale statefulset antigravity --replicas=3
Support
For issues or questions:
- GitHub Issues: https://github.com/cpfarhood/devcontainer/issues
- Documentation: https://github.com/cpfarhood/devcontainer