Fix startup scripts and k8s config for initial deployment
- Fix chown/sudo to use numeric UID/GID instead of hardcoded 'claude' username (baseimage-gui creates users dynamically, name not available at script runtime) - Fix image name: ghcr.io/cpfarhood/devcontainer (matches github.repository) - Fix ConfigMap name: antigravity-config -> antigravity (matches statefulset refs) - Set github-repo in ConfigMap to headlamp-polaris-plugin - Set HTTPRoute to external gateway at antigravity.dev.farh.net - Add CLAUDE.md for Claude Code guidance 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>
This commit is contained in:
@@ -0,0 +1,107 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
Antigravity is a Docker-based cloud development environment that provides:
|
||||||
|
- Web-based GUI IDE (VSCode/Antigravity) via VNC on port 5800
|
||||||
|
- Happy Coder AI assistant integration
|
||||||
|
- Automatic GitHub repository cloning on startup
|
||||||
|
- Kubernetes-native deployment with persistent home storage
|
||||||
|
|
||||||
|
The stack is primarily **Bash scripts + YAML** — there is no Node.js package, compiled language, or test framework.
|
||||||
|
|
||||||
|
## Common Commands
|
||||||
|
|
||||||
|
### Building
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make build # Build Docker image
|
||||||
|
make build REGISTRY=ghcr.io/myuser IMAGE_TAG=v1.0 # Custom registry/tag
|
||||||
|
docker build -t ghcr.io/cpfarhood/antigravity:latest . # Direct build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Running Locally
|
||||||
|
|
||||||
|
```bash
|
||||||
|
GITHUB_REPO="https://github.com/user/repo" make run # Run with Docker
|
||||||
|
make stop # Stop container
|
||||||
|
make clean # Remove volumes
|
||||||
|
```
|
||||||
|
|
||||||
|
### Kubernetes Deployment
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make k8s-deploy # Deploy via kustomize
|
||||||
|
kubectl apply -k k8s/ # Direct kustomize apply
|
||||||
|
make k8s-delete # Tear down
|
||||||
|
make k8s-port-forward # Forward port 5800 to localhost
|
||||||
|
make k8s-logs # Stream container logs
|
||||||
|
make k8s-shell # Open interactive shell in pod
|
||||||
|
```
|
||||||
|
|
||||||
|
### Other Useful Targets
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make help # List all Makefile targets with descriptions
|
||||||
|
make push # Push image to registry (build first)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### Startup Flow
|
||||||
|
|
||||||
|
```
|
||||||
|
Container start
|
||||||
|
→ scripts/startapp.sh
|
||||||
|
→ scripts/init-repo.sh (clone GITHUB_REPO, start Happy Coder)
|
||||||
|
→ launch VSCode as user `claude` in /workspace
|
||||||
|
```
|
||||||
|
|
||||||
|
### Key Files
|
||||||
|
|
||||||
|
| File | Purpose |
|
||||||
|
|------|---------|
|
||||||
|
| `Dockerfile` | Image definition — installs Chrome, Node.js, VSCode, Happy Coder; creates non-root user `claude` (UID 1000) |
|
||||||
|
| `scripts/init-repo.sh` | Clones GitHub repo, authenticates with token, starts Happy Coder background service |
|
||||||
|
| `scripts/startapp.sh` | Calls init-repo.sh then opens VSCode in the workspace |
|
||||||
|
| `k8s/statefulset.yaml` | StatefulSet + headless Service; mounts `/home` (PVC) and `/workspace` (emptyDir) |
|
||||||
|
| `k8s/configmap.yaml` | `GITHUB_REPO`, `HAPPY_SERVER_URL`, `HAPPY_WEBAPP_URL` |
|
||||||
|
| `k8s/httproute.yaml` | Gateway API HTTPRoute for external browser access |
|
||||||
|
| `k8s/secrets-example.yaml` | Template for SealedSecrets (GitHub token, VNC password) |
|
||||||
|
| `Makefile` | Build/deploy automation |
|
||||||
|
|
||||||
|
### Storage Model
|
||||||
|
|
||||||
|
- `/home` — ReadWriteMany PVC (persists across pod restarts, holds user config/dotfiles)
|
||||||
|
- `/workspace` — emptyDir by default (ephemeral; can be changed to PVC)
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
|
||||||
|
**Required:**
|
||||||
|
- `GITHUB_REPO` — URL of repository to clone into `/workspace`
|
||||||
|
|
||||||
|
**Optional:**
|
||||||
|
- `GITHUB_TOKEN` — PAT for private repo access
|
||||||
|
- `VNC_PASSWORD` — VNC web interface password
|
||||||
|
- `DISPLAY_WIDTH` / `DISPLAY_HEIGHT` — VNC resolution
|
||||||
|
- `USER_ID` / `GROUP_ID` — Override UID/GID (default 1000)
|
||||||
|
- `HAPPY_SERVER_URL` / `HAPPY_WEBAPP_URL` — Custom Happy Coder endpoints
|
||||||
|
- `HAPPY_HOME_DIR` / `HAPPY_EXPERIMENTAL`
|
||||||
|
|
||||||
|
### CI/CD
|
||||||
|
|
||||||
|
- **`build-and-push.yaml`** — Builds and pushes to GHCR on every push to `main`, version tags (`v*`), and PRs. Tags: `latest` (main), semver, branch name, commit SHA.
|
||||||
|
- **`release.yaml`** — Creates a GitHub Release with docker pull instructions when a version tag is pushed.
|
||||||
|
- **`dependabot.yml`** — Weekly updates for GitHub Actions and Docker base image.
|
||||||
|
|
||||||
|
Image registry: `ghcr.io/cpfarhood/devcontainer`
|
||||||
|
|
||||||
|
## Kubernetes Notes
|
||||||
|
|
||||||
|
- Uses Kustomize (`kubectl apply -k k8s/`)
|
||||||
|
- Storage class is `ceph-filesystem` by default — change in `statefulset.yaml` for other clusters
|
||||||
|
- Resource limits: 1–4 CPU, 2–8Gi memory
|
||||||
|
- Health checks (liveness/readiness probes) on port 5800
|
||||||
|
- Secrets managed via SealedSecrets (see `k8s/secrets-example.yaml`)
|
||||||
+2
-2
@@ -2,11 +2,11 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: ConfigMap
|
kind: ConfigMap
|
||||||
metadata:
|
metadata:
|
||||||
name: antigravity-config
|
name: antigravity
|
||||||
data:
|
data:
|
||||||
# GitHub repository to clone on startup
|
# GitHub repository to clone on startup
|
||||||
# Example: "https://github.com/username/repository"
|
# Example: "https://github.com/username/repository"
|
||||||
github-repo: ""
|
github-repo: "https://github.com/privilegedescalation/headlamp-polaris-plugin"
|
||||||
|
|
||||||
# Happy Coder configuration (optional)
|
# Happy Coder configuration (optional)
|
||||||
# happy-server-url: "https://api.cluster-fluster.com"
|
# happy-server-url: "https://api.cluster-fluster.com"
|
||||||
|
|||||||
+3
-3
@@ -5,10 +5,10 @@ metadata:
|
|||||||
name: antigravity
|
name: antigravity
|
||||||
spec:
|
spec:
|
||||||
parentRefs:
|
parentRefs:
|
||||||
- name: gateway # Replace with your Gateway name
|
- name: external
|
||||||
namespace: gateway-system # Replace with your Gateway namespace
|
namespace: gateway-system
|
||||||
hostnames:
|
hostnames:
|
||||||
- "antigravity.example.com" # Replace with your domain
|
- "antigravity.dev.farh.net"
|
||||||
rules:
|
rules:
|
||||||
- matches:
|
- matches:
|
||||||
- path:
|
- path:
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ spec:
|
|||||||
fsGroupChangePolicy: "OnRootMismatch"
|
fsGroupChangePolicy: "OnRootMismatch"
|
||||||
containers:
|
containers:
|
||||||
- name: antigravity
|
- name: antigravity
|
||||||
image: ghcr.io/cpfarhood/antigravity:latest
|
image: ghcr.io/cpfarhood/devcontainer:latest
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 5800
|
- containerPort: 5800
|
||||||
|
|||||||
+13
-11
@@ -25,8 +25,8 @@ else
|
|||||||
# Configure git to use token if provided
|
# Configure git to use token if provided
|
||||||
if [ -n "$GITHUB_TOKEN" ]; then
|
if [ -n "$GITHUB_TOKEN" ]; then
|
||||||
git config credential.helper store
|
git config credential.helper store
|
||||||
echo "https://oauth2:${GITHUB_TOKEN}@github.com" > /home/claude/.git-credentials
|
echo "https://oauth2:${GITHUB_TOKEN}@github.com" > /home/.git-credentials
|
||||||
chmod 600 /home/claude/.git-credentials
|
chmod 600 /home/.git-credentials
|
||||||
fi
|
fi
|
||||||
|
|
||||||
git pull || echo "Pull failed, continuing anyway..."
|
git pull || echo "Pull failed, continuing anyway..."
|
||||||
@@ -42,29 +42,31 @@ else
|
|||||||
|
|
||||||
# Configure credentials for future use
|
# Configure credentials for future use
|
||||||
git config --global credential.helper store
|
git config --global credential.helper store
|
||||||
echo "https://oauth2:${GITHUB_TOKEN}@github.com" > /home/claude/.git-credentials
|
echo "https://oauth2:${GITHUB_TOKEN}@github.com" > /home/.git-credentials
|
||||||
chmod 600 /home/claude/.git-credentials
|
chmod 600 /home/.git-credentials
|
||||||
else
|
else
|
||||||
git clone "$GITHUB_REPO" "$WORKSPACE_DIR"
|
git clone "$GITHUB_REPO" "$WORKSPACE_DIR"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Set ownership
|
# Set ownership using numeric IDs (username may not exist yet in baseimage-gui)
|
||||||
chown -R claude:claude "$WORKSPACE_DIR"
|
RUN_UID="${USER_ID:-1000}"
|
||||||
chown -R claude:claude /home/claude
|
RUN_GID="${GROUP_ID:-1000}"
|
||||||
|
chown -R "$RUN_UID:$RUN_GID" "$WORKSPACE_DIR"
|
||||||
|
chown -R "$RUN_UID:$RUN_GID" /home
|
||||||
|
|
||||||
# Start Happy Coder in background as claude user
|
# Start Happy Coder in background as the app user
|
||||||
echo "Starting Happy Coder..."
|
echo "Starting Happy Coder..."
|
||||||
cd "$WORKSPACE_DIR"
|
cd "$WORKSPACE_DIR"
|
||||||
|
|
||||||
# Create Happy Coder log file
|
# Create Happy Coder log file
|
||||||
HAPPY_LOG="/tmp/happy-coder.log"
|
HAPPY_LOG="/tmp/happy-coder.log"
|
||||||
touch "$HAPPY_LOG"
|
touch "$HAPPY_LOG"
|
||||||
chown claude:claude "$HAPPY_LOG"
|
chown "$RUN_UID:$RUN_GID" "$HAPPY_LOG"
|
||||||
|
|
||||||
# Start Happy Coder as claude user
|
# Start Happy Coder as the app user (use numeric UID for compatibility with baseimage-gui)
|
||||||
sudo -u claude bash -c "cd '$WORKSPACE_DIR' && happy-coder > '$HAPPY_LOG' 2>&1 &"
|
sudo -u "#$RUN_UID" bash -c "cd '$WORKSPACE_DIR' && happy-coder > '$HAPPY_LOG' 2>&1 &"
|
||||||
|
|
||||||
# Save PID for monitoring
|
# Save PID for monitoring
|
||||||
echo $! > /tmp/happy-coder.pid
|
echo $! > /tmp/happy-coder.pid
|
||||||
|
|||||||
+2
-1
@@ -18,4 +18,5 @@ echo "Opening Antigravity in: $WORKSPACE_DIR"
|
|||||||
|
|
||||||
# Start Antigravity (VSCode) in the workspace directory as claude user
|
# Start Antigravity (VSCode) in the workspace directory as claude user
|
||||||
# The baseimage-gui will handle the GUI display
|
# The baseimage-gui will handle the GUI display
|
||||||
exec sudo -u claude code --new-window --wait "$WORKSPACE_DIR"
|
RUN_UID="${USER_ID:-1000}"
|
||||||
|
exec sudo -u "#$RUN_UID" code --new-window --wait "$WORKSPACE_DIR"
|
||||||
|
|||||||
Reference in New Issue
Block a user