Compare commits

..

8 Commits

Author SHA1 Message Date
Chris Farhood dd12262c83 Fix Happy Coder npm package name
Changed from incorrect `@happy-sdk/happy-coder` to correct `happy-coder`
package name. The scoped package doesn't exist on npm, causing Docker
build failures.

This fixes the v1.0.0 release Docker build.

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>
2026-02-15 08:45:32 -05:00
Chris Farhood 8f0fee838e Fix invalid Docker tag format in GitHub Actions workflow
Changed SHA tag prefix from `{{branch}}-` to `sha-` to fix build
failures when creating releases from tags. The `{{branch}}` variable
is empty when building from tags (e.g., v1.0.0), which resulted in
invalid Docker tags like `:-7bdde95` instead of `sha-7bdde95`.

This fixes the v1.0.0 release build failure.

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>
2026-02-15 08:42:50 -05:00
Chris Farhood 7bdde95cb4 docs: Add release process and changelog
Add comprehensive release management documentation and changelog.

New files:
- .github/workflows/tag-release.md: Complete release process guide
  - Semantic versioning guidelines
  - 3 methods for creating releases (CLI, git, web UI)
  - Version bump guidelines (major/minor/patch)
  - Pre-release support (alpha/beta/rc)
  - Release checklist
  - Docker image tagging strategy
  - Example workflows

- CHANGELOG.md: Changelog following Keep a Changelog format
  - Unreleased section with all current features
  - Template for future releases
  - Adheres to Semantic Versioning

Release Process:
1. Create annotated git tag (e.g., v1.0.0)
2. Push tag to GitHub
3. GitHub Actions automatically:
   - Builds Docker image
   - Pushes with multiple tags (v1.0.0, 1.0, 1, latest)
   - Creates GitHub release with notes

Ready for v1.0.0 release!

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>
2026-02-15 08:39:17 -05:00
Chris Farhood f79be89e4e docs: Add comprehensive deployment and variables reference
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>
2026-02-15 08:36:45 -05:00
Chris Farhood 46b2077f99 feat: Add GitHub Actions for automated Docker image builds
Add comprehensive CI/CD pipeline for building and publishing Docker images
to GitHub Container Registry (ghcr.io).

Components:
- build-and-push.yaml: Main workflow for building and pushing images
  - Triggers on push to main, tags, PRs, and manual dispatch
  - Multi-tag strategy (latest, semver, sha, branch)
  - Docker buildx with layer caching
  - Automatic GHCR authentication
  - Platform: linux/amd64

- release.yaml: Automated GitHub releases on version tags
  - Auto-generates release notes from commits
  - Creates GitHub release with Docker pull command

- dependabot.yml: Automated dependency updates
  - Weekly updates for GitHub Actions
  - Weekly updates for Docker base images

- PULL_REQUEST_TEMPLATE.md: PR template with testing checklist

Updated README:
- Add build status badge
- Update image pull instructions
- Reference automated builds

Image tagging strategy:
- main branch → :latest, :main, :main-{sha}
- v1.2.3 tag → :v1.2.3, :1.2, :1, :latest
- PR → :pr-{number}

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>
2026-02-15 08:34:06 -05:00
Chris Farhood 667845b9a2 fix: Remove fake HAPPY_CODER_API_KEY, use actual Happy Coder env vars
Happy Coder does not require an API key. It uses these environment variables:
- HAPPY_SERVER_URL (optional custom server)
- HAPPY_WEBAPP_URL (optional custom webapp)
- HAPPY_HOME_DIR (data directory)
- HAPPY_EXPERIMENTAL (enable experimental features)

Changes:
- Remove HAPPY_CODER_API_KEY from all files
- Add proper Happy Coder environment variables to StatefulSet
- Add Happy Coder config options to ConfigMap
- Update README with correct Happy Coder configuration
- Update Makefile and docker-compose examples
- Update secrets-example.yaml

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>
2026-02-15 08:32:57 -05:00
Chris Farhood 2c80117602 fix: Replace Ingress with HTTPRoute (Gateway API)
Switch from Ingress to HTTPRoute for Gateway API compatibility.

Changes:
- Remove k8s/ingress.yaml
- Add k8s/httproute.yaml with Gateway API configuration
- Update kustomization.yaml to reference httproute.yaml
- Update README.md references from Ingress to HTTPRoute

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>
2026-02-15 08:23:56 -05:00
Chris Farhood c7a7e8bd12 Initial commit: Antigravity dev container with Happy Coder
Add containerized GUI development environment featuring:
- Antigravity IDE (VSCode) accessible via web browser
- Happy Coder AI assistant integration
- Automatic GitHub repository cloning on startup
- Persistent user home directory (ReadWriteMany PVC)
- Secure non-root execution as user claude (UID 1000)

Components:
- Dockerfile based on jlesage/baseimage-gui
- Startup scripts for repo initialization and app launch
- Kubernetes manifests (StatefulSet, ConfigMap, Secrets)
- Makefile for build and deployment automation
- Comprehensive documentation

Features:
- Web-based VNC interface (port 5800)
- GitHub token authentication for private repos
- Happy Coder runs as background service in workspace
- CephFS storage for persistent home directory
- Configurable display resolution and security

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>
2026-02-15 08:23:08 -05:00
38 changed files with 2159 additions and 297 deletions
+24
View File
@@ -0,0 +1,24 @@
.git
.gitignore
.dockerignore
*.md
README.md
LICENSE
Makefile
docker-compose.yml
# Kubernetes files
k8s/
# Local development
home/
workspace/
*.log
# IDE
.vscode/
.idea/
# OS
.DS_Store
Thumbs.db
+36
View File
@@ -0,0 +1,36 @@
## Description
<!-- Describe your changes in detail -->
## Type of Change
<!-- Mark with an `x` all that apply -->
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] Documentation update
- [ ] CI/CD update
## Testing
<!-- Describe the tests you ran to verify your changes -->
- [ ] Built Docker image locally
- [ ] Tested container startup
- [ ] Tested repository cloning
- [ ] Tested Happy Coder integration
- [ ] Tested VNC web interface
## Checklist
- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have tested that the Docker image builds successfully
## Screenshots (if applicable)
<!-- Add screenshots to help explain your changes -->
+19
View File
@@ -0,0 +1,19 @@
version: 2
updates:
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
labels:
- "dependencies"
- "github-actions"
# Maintain dependencies for Docker
- package-ecosystem: "docker"
directory: "/"
schedule:
interval: "weekly"
labels:
- "dependencies"
- "docker"
+64
View File
@@ -0,0 +1,64 @@
name: Build and Push Docker Image
on:
push:
branches:
- main
tags:
- 'v*'
pull_request:
branches:
- main
workflow_dispatch:
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GitHub Container Registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels)
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=sha,prefix=sha-
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
platforms: linux/amd64
+51
View File
@@ -0,0 +1,51 @@
name: Release
on:
push:
tags:
- 'v*'
permissions:
contents: write
packages: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate Release Notes
id: notes
run: |
# Get the tag message or generate from commits
TAG_MESSAGE=$(git tag -l --format='%(contents)' ${{ github.ref_name }})
if [ -z "$TAG_MESSAGE" ]; then
# Generate from commit messages since last tag
PREV_TAG=$(git describe --tags --abbrev=0 ${{ github.ref_name }}^ 2>/dev/null || echo "")
if [ -z "$PREV_TAG" ]; then
COMMITS=$(git log --pretty=format:"- %s (%h)" ${{ github.ref_name }})
else
COMMITS=$(git log --pretty=format:"- %s (%h)" ${PREV_TAG}..${{ github.ref_name }})
fi
NOTES="## Changes\n\n${COMMITS}\n\n## Docker Image\n\n\`\`\`bash\ndocker pull ghcr.io/${{ github.repository }}:${{ github.ref_name }}\n\`\`\`"
else
NOTES="${TAG_MESSAGE}\n\n## Docker Image\n\n\`\`\`bash\ndocker pull ghcr.io/${{ github.repository }}:${{ github.ref_name }}\n\`\`\`"
fi
echo "notes<<EOF" >> $GITHUB_OUTPUT
echo -e "$NOTES" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Create Release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref_name }}
release_name: Release ${{ github.ref_name }}
body: ${{ steps.notes.outputs.notes }}
draft: false
prerelease: false
+259
View File
@@ -0,0 +1,259 @@
# Release Process
This document describes how to create releases for this project.
## Semantic Versioning
We follow [Semantic Versioning 2.0.0](https://semver.org/):
- **MAJOR** version (v2.0.0): Incompatible API/breaking changes
- **MINOR** version (v1.1.0): New features, backwards compatible
- **PATCH** version (v1.0.1): Bug fixes, backwards compatible
## Creating a Release
### Method 1: Using GitHub CLI (Recommended)
```bash
# Ensure you're on main branch and up to date
git checkout main
git pull
# Create and push a tag
VERSION="v1.0.0" # Change this
git tag -a "$VERSION" -m "Release $VERSION
## What's New
- Feature 1
- Feature 2
- Bug fix 1
## Docker Image
\`\`\`bash
docker pull ghcr.io/cpfarhood/devcontainer:$VERSION
\`\`\`
"
git push origin "$VERSION"
# The GitHub Actions workflow will automatically:
# 1. Build the Docker image
# 2. Push to ghcr.io with multiple tags
# 3. Create a GitHub release with notes
```
### Method 2: Using Git Tags Only
```bash
git checkout main
git pull
# Create annotated tag
git tag -a v1.0.0 -m "Release v1.0.0"
# Push tag
git push origin v1.0.0
```
### Method 3: Using GitHub Web UI
1. Go to https://github.com/cpfarhood/devcontainer/releases
2. Click "Draft a new release"
3. Click "Choose a tag"
4. Type the new version (e.g., `v1.0.0`)
5. Click "Create new tag on publish"
6. Fill in the release title and description
7. Click "Publish release"
## What Happens Automatically
When you push a version tag (`v*`), GitHub Actions will:
1. **Build Docker image** with multiple tags:
- `ghcr.io/cpfarhood/devcontainer:v1.2.3` (exact version)
- `ghcr.io/cpfarhood/devcontainer:1.2` (minor version)
- `ghcr.io/cpfarhood/devcontainer:1` (major version)
- `ghcr.io/cpfarhood/devcontainer:latest` (if on default branch)
2. **Create GitHub Release** with:
- Auto-generated release notes from commits
- Docker pull command in the description
## Version Bump Guidelines
### Patch Release (v1.0.X)
- Bug fixes
- Documentation updates
- Minor dependency updates
- No new features
- No breaking changes
**Example:** v1.0.1
```bash
git tag -a v1.0.1 -m "Release v1.0.1 - Bug fixes"
git push origin v1.0.1
```
### Minor Release (v1.X.0)
- New features
- New optional configuration variables
- Enhancements to existing features
- Backwards compatible
- No breaking changes
**Example:** v1.1.0
```bash
git tag -a v1.1.0 -m "Release v1.1.0 - New Happy Coder features"
git push origin v1.1.0
```
### Major Release (vX.0.0)
- Breaking changes
- Required configuration changes
- Removal of deprecated features
- Incompatible API changes
**Example:** v2.0.0
```bash
git tag -a v2.0.0 -m "Release v2.0.0 - Breaking: New storage architecture"
git push origin v2.0.0
```
## Pre-releases
For alpha, beta, or release candidates:
```bash
# Alpha
git tag -a v1.1.0-alpha.1 -m "Release v1.1.0-alpha.1"
git push origin v1.1.0-alpha.1
# Beta
git tag -a v1.1.0-beta.1 -m "Release v1.1.0-beta.1"
git push origin v1.1.0-beta.1
# Release Candidate
git tag -a v1.1.0-rc.1 -m "Release v1.1.0-rc.1"
git push origin v1.1.0-rc.1
```
## Release Checklist
Before creating a release:
- [ ] All tests pass
- [ ] Documentation is up to date
- [ ] CHANGELOG.md is updated (if you maintain one)
- [ ] Version number follows semver
- [ ] On main/master branch
- [ ] All changes are committed
- [ ] Tag message includes release notes
## Docker Image Tags
Each release creates multiple Docker tags for flexibility:
| Git Tag | Docker Tags Created |
|---------|---------------------|
| v1.2.3 | `:v1.2.3`, `:1.2`, `:1`, `:latest` |
| v2.0.0 | `:v2.0.0`, `:2.0`, `:2`, `:latest` |
| v1.2.4-beta.1 | `:v1.2.4-beta.1`, `:1.2-beta` |
**Usage examples:**
```bash
# Specific version (recommended for production)
docker pull ghcr.io/cpfarhood/devcontainer:v1.2.3
# Minor version (gets patches automatically)
docker pull ghcr.io/cpfarhood/devcontainer:1.2
# Major version (gets minor updates and patches)
docker pull ghcr.io/cpfarhood/devcontainer:1
# Latest (always gets newest stable release)
docker pull ghcr.io/cpfarhood/devcontainer:latest
```
## Viewing Releases
- **GitHub Releases:** https://github.com/cpfarhood/devcontainer/releases
- **Docker Images:** https://github.com/cpfarhood/devcontainer/pkgs/container/devcontainer
- **Git Tags:** `git tag -l`
## Deleting a Release
If you need to delete a bad release:
```bash
# Delete local tag
git tag -d v1.0.0
# Delete remote tag
git push origin :refs/tags/v1.0.0
# Delete GitHub release (use web UI or gh CLI)
gh release delete v1.0.0
```
**Note:** Docker images pushed to ghcr.io cannot be easily deleted. It's better to create a new patch version.
## First Release
For the initial v1.0.0 release:
```bash
git checkout main
git pull
git tag -a v1.0.0 -m "Release v1.0.0 - Initial Release
## Features
- Antigravity IDE with web-based VNC access
- Happy Coder AI assistant integration
- Automatic GitHub repository cloning
- Persistent home directory with ReadWriteMany PVC
- Secure non-root execution (claude user, UID 1000)
- Support for private repositories with GitHub token
- HTTPRoute (Gateway API) support
- Multi-platform Docker images
- Comprehensive deployment documentation
## Docker Image
\`\`\`bash
docker pull ghcr.io/cpfarhood/devcontainer:v1.0.0
\`\`\`
## Deployment
See DEPLOYMENT.md for complete deployment instructions.
"
git push origin v1.0.0
```
## Example Release Workflow
```bash
# 1. Finish your feature/fix on a branch
git checkout feature/new-feature
git commit -m "feat: Add new feature"
git push
# 2. Create PR and merge to main
gh pr create
# ... get approval and merge ...
# 3. Pull latest main
git checkout main
git pull
# 4. Create release tag
git tag -a v1.1.0 -m "Release v1.1.0 - New feature"
git push origin v1.1.0
# 5. Wait for GitHub Actions
# - Check: https://github.com/cpfarhood/devcontainer/actions
# 6. Verify release
# - GitHub: https://github.com/cpfarhood/devcontainer/releases
# - Docker: docker pull ghcr.io/cpfarhood/devcontainer:v1.1.0
```
+24
View File
@@ -0,0 +1,24 @@
# Secrets
*.env
.env.local
secrets.yaml
k8s/sealedsecrets.yaml
# Local volumes
home/
workspace/
# IDE
.vscode/
.idea/
# OS
.DS_Store
Thumbs.db
# Logs
*.log
# Build artifacts
*.tar
*.tar.gz
+98
View File
@@ -0,0 +1,98 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- Initial project setup
- Antigravity IDE (VSCode) with web-based VNC access
- Happy Coder AI assistant integration
- Automatic GitHub repository cloning on startup
- Persistent home directory with ReadWriteMany PVC support
- Secure non-root execution (claude user, UID 1000, GID 1000)
- Support for private repositories via GitHub token
- HTTPRoute (Gateway API) support
- VNC password protection
- Multi-platform Docker image builds
- GitHub Actions CI/CD pipeline
- Automated releases on version tags
- Comprehensive deployment documentation (DEPLOYMENT.md)
- Complete variables reference (VARIABLES.md)
### Container Features
- Base: jlesage/baseimage-gui:ubuntu-22.04-v4
- Antigravity IDE (VSCode)
- Happy Coder npm package
- Chrome browser
- Node.js (LTS)
- Python 3
- Git
### Kubernetes Resources
- StatefulSet with volumeClaimTemplates
- ReadWriteMany PVC for /home directory
- ConfigMap for configuration
- Sealed Secrets support
- HTTPRoute for external access
- Service (headless)
### Configuration Options
- GitHub repository URL (required)
- GitHub token (optional, for private repos)
- VNC password (optional)
- Happy Coder server URL (optional)
- Happy Coder webapp URL (optional)
- Display resolution (configurable)
- Resource limits (configurable)
- Storage size (configurable)
### Documentation
- README.md with quick start guide
- DEPLOYMENT.md with step-by-step instructions
- VARIABLES.md with complete variable reference
- Release process documentation
- Pull request template
- Dependabot configuration
## Version History
No releases yet. See [Unreleased] section above for planned v1.0.0 features.
---
## Release Template
Use this template for future releases:
```markdown
## [1.0.0] - YYYY-MM-DD
### Added
- New features
- New configuration options
### Changed
- Changes to existing features
- Updated dependencies
### Deprecated
- Features that will be removed in future versions
### Removed
- Removed features
- Breaking changes
### Fixed
- Bug fixes
- Security patches
### Security
- Security improvements
- Vulnerability fixes
```
[Unreleased]: https://github.com/cpfarhood/devcontainer/compare/v1.0.0...HEAD
+436
View File
@@ -0,0 +1,436 @@
# Deployment Guide
This guide provides step-by-step instructions for deploying the Antigravity Dev Container to Kubernetes.
## Prerequisites
- Kubernetes cluster with Gateway API support
- `kubectl` configured 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:**
```bash
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:**
1. Go to https://github.com/settings/tokens
2. Click "Generate new token (classic)"
3. Select scopes: `repo` (for private repos)
4. 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 name
- `parentRefs.namespace` - Namespace where Gateway is deployed
- `hostnames` - Domain name for accessing the container
**Location:** `k8s/httproute.yaml`
**Example:**
```yaml
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 URL
- `happy-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
```bash
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):
```bash
# Find your storage class
kubectl get storageclass
# Edit the file
vi k8s/statefulset.yaml
```
Change `storageClassName` to match your cluster:
```yaml
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`:
```bash
vi k8s/configmap.yaml
```
Set your repository URL:
```yaml
data:
github-repo: "https://github.com/yourusername/yourrepo"
```
### Step 4: Configure Gateway (HTTPRoute)
Edit `k8s/httproute.yaml`:
```bash
# Find your Gateway
kubectl get gateway -A
# Edit the file
vi k8s/httproute.yaml
```
Update with your Gateway details:
```yaml
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:
```bash
# 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
```bash
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)
```bash
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:**
```bash
vi k8s/kustomization.yaml
# Change line 5: namespace: default
```
**Resource limits:**
```bash
vi k8s/statefulset.yaml
# Adjust lines 98-103 for your needs
```
### Step 7: Deploy to Kubernetes
```bash
# Deploy everything
kubectl apply -k k8s/
# Or if you changed the namespace
kubectl apply -k k8s/ -n your-namespace
```
### Step 8: Verify Deployment
```bash
# 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)**
```bash
# Open in browser
open https://devcontainer.yourdomain.com
```
**Option B: Via Port Forward (local access)**
```bash
# 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:**
```bash
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:**
```bash
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:**
```bash
kubectl describe httproute antigravity
```
**Common issues:**
- Gateway name/namespace incorrect
- Domain not pointing to Gateway
- TLS certificate not issued
### VNC not accessible
**Check service:**
```bash
kubectl get svc antigravity
kubectl describe svc antigravity
```
**Port forward test:**
```bash
kubectl port-forward antigravity-0 5800:5800
# Try accessing http://localhost:5800
```
## Quick Deploy Example
Complete deployment with all values filled in:
```bash
# 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:**
```bash
kubectl set image statefulset/antigravity \
antigravity=ghcr.io/cpfarhood/devcontainer:latest
```
**To use specific version:**
```bash
kubectl set image statefulset/antigravity \
antigravity=ghcr.io/cpfarhood/devcontainer:v1.0.0
```
### Changing Repository
Edit the ConfigMap and restart:
```bash
kubectl edit configmap antigravity-config
# Change github-repo value
kubectl rollout restart statefulset/antigravity
```
### Scaling
```bash
# 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
+76
View File
@@ -0,0 +1,76 @@
FROM jlesage/baseimage-gui:ubuntu-22.04-v4
# Set environment variables
ENV APP_NAME="Antigravity Dev Container" \
KEEP_APP_RUNNING=1 \
DISPLAY_WIDTH=1920 \
DISPLAY_HEIGHT=1080 \
SECURE_CONNECTION=1 \
USER_ID=1000 \
GROUP_ID=1000 \
CLAUDE_USER=claude
# Install system dependencies
RUN apt-get update && apt-get install -y \
curl \
wget \
gnupg \
ca-certificates \
git \
build-essential \
python3 \
python3-pip \
jq \
unzip \
sudo \
&& rm -rf /var/lib/apt/lists/*
# Install Chrome
RUN wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | gpg --dearmor -o /usr/share/keyrings/google-chrome-keyring.gpg && \
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/google-chrome-keyring.gpg] http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google-chrome.list && \
apt-get update && \
apt-get install -y google-chrome-stable && \
rm -rf /var/lib/apt/lists/*
# Install Node.js (LTS version for Happy Coder)
RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - && \
apt-get install -y nodejs && \
rm -rf /var/lib/apt/lists/*
# Install Happy Coder globally
RUN npm install -g happy-coder
# Install Antigravity (Google's Project IDX / Cloud Code alternative)
# Note: Antigravity might be packaged differently - adjust as needed
# For now, we'll use VSCode with Project IDX extensions as a placeholder
RUN wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor -o /usr/share/keyrings/packages.microsoft.gpg && \
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/packages.microsoft.gpg] https://packages.microsoft.com/repos/code stable main" > /etc/apt/sources.list.d/vscode.list && \
apt-get update && \
apt-get install -y code && \
rm -rf /var/lib/apt/lists/*
# Create claude user with specific UID/GID
RUN groupadd -g 1000 claude && \
useradd -u 1000 -g 1000 -m -s /bin/bash claude && \
echo "claude ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
# Create workspace directory
RUN mkdir -p /workspace && \
chown -R claude:claude /workspace
# Copy startup script
COPY --chmod=755 scripts/startapp.sh /startapp.sh
COPY --chmod=755 scripts/init-repo.sh /usr/local/bin/init-repo
# Set working directory
WORKDIR /workspace
# Configure container to run as claude user
ENV HOME=/home/claude \
USER=claude
# Expose VNC port (baseimage-gui default)
EXPOSE 5800
# Set app name for baseimage-gui
RUN set-cont-env APP_NAME "Antigravity"
+101
View File
@@ -0,0 +1,101 @@
.PHONY: build push run stop clean help
# Variables
REGISTRY ?= ghcr.io/cpfarhood
IMAGE_NAME ?= antigravity
IMAGE_TAG ?= latest
FULL_IMAGE = $(REGISTRY)/$(IMAGE_NAME):$(IMAGE_TAG)
.DEFAULT_GOAL := help
# Build the Docker image
build:
@echo "Building $(FULL_IMAGE)..."
docker build -t $(FULL_IMAGE) .
# Push the image to registry
push: build
@echo "Pushing $(FULL_IMAGE)..."
docker push $(FULL_IMAGE)
# Run locally with Docker
run:
@echo "Running $(FULL_IMAGE) locally..."
docker run -d \
-p 5800:5800 \
-e GITHUB_REPO="${GITHUB_REPO}" \
-e GITHUB_TOKEN="${GITHUB_TOKEN}" \
-e VNC_PASSWORD="${VNC_PASSWORD}" \
-e HAPPY_EXPERIMENTAL="true" \
-v $(PWD)/home:/home \
-v $(PWD)/workspace:/workspace \
--name antigravity \
$(FULL_IMAGE)
@echo "Access at http://localhost:5800"
# Stop the running container
stop:
@echo "Stopping antigravity container..."
docker stop antigravity || true
docker rm antigravity || true
# Clean up local volumes
clean: stop
@echo "Cleaning up..."
rm -rf ./home ./workspace
# Kubernetes deployment
k8s-deploy:
@echo "Deploying to Kubernetes..."
kubectl apply -k k8s/
k8s-delete:
@echo "Deleting from Kubernetes..."
kubectl delete -k k8s/
k8s-logs:
@echo "Showing logs..."
kubectl logs -f antigravity-0
k8s-shell:
@echo "Opening shell..."
kubectl exec -it antigravity-0 -- bash
k8s-port-forward:
@echo "Port forwarding to localhost:5800..."
kubectl port-forward antigravity-0 5800:5800
# Show help
help:
@echo "Antigravity Dev Container Makefile"
@echo ""
@echo "Usage: make [target]"
@echo ""
@echo "Docker Targets:"
@echo " build - Build the Docker image"
@echo " push - Push image to registry"
@echo " run - Run container locally (requires env vars)"
@echo " stop - Stop running container"
@echo " clean - Clean up containers and volumes"
@echo ""
@echo "Kubernetes Targets:"
@echo " k8s-deploy - Deploy to Kubernetes"
@echo " k8s-delete - Delete from Kubernetes"
@echo " k8s-logs - Show container logs"
@echo " k8s-shell - Open shell in container"
@echo " k8s-port-forward - Port forward to localhost"
@echo ""
@echo "Variables:"
@echo " REGISTRY - Docker registry (default: ghcr.io/cpfarhood)"
@echo " IMAGE_NAME - Image name (default: antigravity)"
@echo " IMAGE_TAG - Image tag (default: latest)"
@echo ""
@echo "Environment Variables for 'make run':"
@echo " GITHUB_REPO - GitHub repository URL"
@echo " GITHUB_TOKEN - GitHub token (optional)"
@echo " VNC_PASSWORD - VNC password (optional)"
@echo ""
@echo "Example:"
@echo " make build"
@echo " make push REGISTRY=ghcr.io/myuser IMAGE_TAG=v1.0"
@echo " GITHUB_REPO=https://github.com/user/repo make run"
+367
View File
@@ -0,0 +1,367 @@
# Antigravity Dev Container
![Build and Push](https://github.com/cpfarhood/devcontainer/actions/workflows/build-and-push.yaml/badge.svg)
A containerized development environment with GUI access, featuring:
- **Antigravity** (VSCode/Cloud IDE) via web browser
- **Happy Coder** - AI-powered development assistant
- **Automatic GitHub repo cloning**
- **Persistent user home directory**
- **Secure non-root execution**
## Features
### GUI Access
- Web-based VNC interface (port 5800)
- Full desktop environment in your browser
- Secure connections with optional password protection
### Development Tools
- Antigravity IDE (VSCode-based)
- Happy Coder AI assistant
- Git integration
- Node.js and npm
- Python 3
- Chrome browser
### Security
- Runs as non-root user `claude` (UID 1000, GID 1000)
- Secure VNC connections
- Token-based GitHub authentication
- Isolated workspace
### Persistence
- ReadWriteMany PVC for `/home` (user data persists)
- Workspace mounted at `/workspace`
- Repository cloned on first startup
## Documentation
- **[DEPLOYMENT.md](DEPLOYMENT.md)** - Complete deployment guide with step-by-step instructions
- **[VARIABLES.md](VARIABLES.md)** - Reference for all configuration variables
- **[README.md](README.md)** - This file (overview and quick start)
## Quick Start
**👉 For detailed deployment instructions, see [DEPLOYMENT.md](DEPLOYMENT.md)**
### 1. Get the Image
The image is automatically built and published to GitHub Container Registry on every push to main.
```bash
# Pull the latest image
docker pull ghcr.io/cpfarhood/devcontainer:latest
# Or pull a specific version
docker pull ghcr.io/cpfarhood/devcontainer:v1.0.0
```
**Building locally (optional):**
```bash
docker build -t ghcr.io/cpfarhood/devcontainer:latest .
docker push ghcr.io/cpfarhood/devcontainer:latest
```
### 2. Configure Secrets
Edit `k8s/secrets-example.yaml` and create a sealed secret:
```bash
kubectl create secret generic antigravity-secrets \
--from-literal=github-token='ghp_your_token' \
--from-literal=vnc-password='your_password' \
--dry-run=client -o yaml | \
kubeseal --format=yaml > k8s/sealedsecrets.yaml
```
### 3. Configure Repository
Edit `k8s/configmap.yaml`:
```yaml
data:
github-repo: "https://github.com/yourusername/yourrepo"
```
### 4. Deploy to Kubernetes
```bash
kubectl apply -k k8s/
```
### 5. Access the Interface
```bash
# Port forward for local access
kubectl port-forward statefulset/antigravity 5800:5800
# Open in browser
open http://localhost:5800
```
Or configure HTTPRoute (Gateway API) for external access via your domain.
## Environment Variables
### Required
- `GITHUB_REPO` - GitHub repository URL to clone
### Optional
- `GITHUB_TOKEN` - GitHub Personal Access Token (for private repos)
- `VNC_PASSWORD` - Password for VNC access
- `USER_ID` - UID for claude user (default: 1000)
- `GROUP_ID` - GID for claude user (default: 1000)
- `DISPLAY_WIDTH` - VNC display width (default: 1920)
- `DISPLAY_HEIGHT` - VNC display height (default: 1080)
### Happy Coder Configuration (Optional)
- `HAPPY_SERVER_URL` - Custom Happy server URL (default: https://api.cluster-fluster.com)
- `HAPPY_WEBAPP_URL` - Custom Happy webapp URL (default: https://app.happy.engineering)
- `HAPPY_HOME_DIR` - Happy data directory (default: /home/claude/.happy)
- `HAPPY_EXPERIMENTAL` - Enable experimental features (default: true in container)
## Architecture
```
┌─────────────────────────────────────┐
│ Web Browser (Port 5800) │
└──────────────┬──────────────────────┘
┌─────────────────────────────────────┐
│ VNC Web Interface │
│ (jlesage/baseimage-gui) │
└──────────────┬──────────────────────┘
┌─────────────────────────────────────┐
│ Antigravity IDE │
│ (VSCode + Extensions) │
│ Running as user: claude (1000) │
└──────────────┬──────────────────────┘
┌─────────────────────────────────────┐
│ Happy Coder (Background Process) │
│ AI Development Assistant │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ Workspace: /workspace/{repo} │
│ Home: /home/claude (RWX PVC) │
└─────────────────────────────────────┘
```
## Startup Flow
1. **Container starts** - baseimage-gui initializes
2. **init-repo.sh runs**:
- Checks for `GITHUB_REPO` environment variable
- Clones repository to `/workspace/{repo-name}` if not exists
- Configures git credentials with `GITHUB_TOKEN`
- Starts Happy Coder in background
3. **startapp.sh runs**:
- Opens Antigravity IDE in the cloned repository
- Happy Coder is already running and accessible
## Happy Coder Integration
Happy Coder runs as a background service and is accessible within the IDE:
```bash
# Check Happy Coder status
ps aux | grep happy-coder
# View logs
cat /tmp/happy-coder.log
# Restart Happy Coder
sudo -u claude bash -c "cd /workspace/your-repo && happy-coder &"
```
## Local Development
### Run with Docker Compose
```yaml
version: '3.8'
services:
antigravity:
build: .
ports:
- "5800:5800"
environment:
- GITHUB_REPO=https://github.com/yourusername/yourrepo
- GITHUB_TOKEN=ghp_your_token
- VNC_PASSWORD=yourpassword
- HAPPY_EXPERIMENTAL=true
volumes:
- ./home:/home
- ./workspace:/workspace
```
```bash
docker-compose up
```
### Run with Docker
```bash
docker run -d \
-p 5800:5800 \
-e GITHUB_REPO="https://github.com/yourusername/yourrepo" \
-e GITHUB_TOKEN="ghp_your_token" \
-e VNC_PASSWORD="yourpassword" \
-e HAPPY_EXPERIMENTAL="true" \
-v $(pwd)/home:/home \
-v $(pwd)/workspace:/workspace \
ghcr.io/cpfarhood/antigravity:latest
```
## Kubernetes Deployment
### With Flux
See the animaniacs cluster configuration for GitOps deployment patterns.
### Standalone
```bash
# Apply manifests
kubectl apply -k k8s/
# Check status
kubectl get statefulset antigravity
kubectl get pods -l app=antigravity
# Access logs
kubectl logs antigravity-0
# Access shell
kubectl exec -it antigravity-0 -- bash
```
## Troubleshooting
### Repository not cloning
```bash
# Check logs
kubectl logs antigravity-0 | grep "Repository Initialization"
# Verify GITHUB_REPO is set
kubectl exec antigravity-0 -- env | grep GITHUB
# Check git credentials
kubectl exec antigravity-0 -- cat /home/claude/.git-credentials
```
### Happy Coder not starting
```bash
# Check Happy Coder logs
kubectl exec antigravity-0 -- cat /tmp/happy-coder.log
# Verify API key
kubectl exec antigravity-0 -- env | grep HAPPY_CODER
# Restart Happy Coder
kubectl exec antigravity-0 -- sudo -u claude bash -c "cd /workspace/repo && happy-coder &"
```
### VNC not accessible
```bash
# Check port forwarding
kubectl port-forward antigravity-0 5800:5800
# Verify service
kubectl get svc antigravity
# Check pod status
kubectl describe pod antigravity-0
```
### Permission issues
```bash
# Check ownership
kubectl exec antigravity-0 -- ls -la /home/claude
kubectl exec antigravity-0 -- ls -la /workspace
# Fix ownership
kubectl exec antigravity-0 -- chown -R claude:claude /home/claude
kubectl exec antigravity-0 -- chown -R claude:claude /workspace
```
## Security Considerations
1. **Secrets Management**: Use SealedSecrets or external secret managers
2. **Network Policies**: Restrict ingress/egress as needed
3. **RBAC**: Limit who can access the namespace
4. **VNC Password**: Always set a strong VNC password
5. **GitHub Token**: Use fine-grained tokens with minimal permissions
6. **Container Security**: Runs as non-root user (claude:1000)
## Storage
### Home Directory (`/home`)
- Mounted from ReadWriteMany PVC (`userhome`)
- Persists user settings, credentials, history
- Survives pod restarts
### Workspace (`/workspace`)
- ephemeral emptyDir (can be changed to PVC)
- Contains cloned repository
- Rebuild on pod restart
To persist workspace:
1. Create a PVC for workspace
2. Update `statefulset.yaml` to use PVC instead of emptyDir
## Customization
### Add More Tools
Edit `Dockerfile`:
```dockerfile
RUN apt-get update && apt-get install -y \
your-package-here \
&& rm -rf /var/lib/apt/lists/*
```
### Change Display Resolution
Set environment variables:
```yaml
env:
- name: DISPLAY_WIDTH
value: "2560"
- name: DISPLAY_HEIGHT
value: "1440"
```
### Auto-clone Multiple Repos
Modify `init-repo.sh` to support `GITHUB_REPOS` (comma-separated):
```bash
IFS=',' read -ra REPOS <<< "$GITHUB_REPOS"
for repo in "${REPOS[@]}"; do
# Clone each repo
done
```
## License
MIT
## Credits
- Built on [jlesage/baseimage-gui](https://github.com/jlesage/docker-baseimage-gui)
- Uses [Happy Coder](https://happy.engineering)
- Inspired by Google's Project IDX
+305
View File
@@ -0,0 +1,305 @@
# Configuration Variables Reference
Quick reference for all configurable variables in this project.
## Required Variables
These MUST be configured before deployment:
### Storage Class Name
- **Variable:** `storageClassName`
- **File:** `k8s/statefulset.yaml`
- **Line:** ~117
- **Type:** String
- **Description:** ReadWriteMany storage class available in your cluster
- **Example:** `ceph-filesystem`, `nfs-client`, `efs-sc`
- **How to find:** `kubectl get storageclass`
### GitHub Repository URL
- **Variable:** `github-repo`
- **File:** `k8s/configmap.yaml`
- **Line:** ~9
- **Type:** String (URL)
- **Description:** Repository to clone on container startup
- **Format:** `https://github.com/username/repository`
- **Example:** `https://github.com/cpfarhood/my-project`
### Gateway Name
- **Variable:** `parentRefs[0].name`
- **File:** `k8s/httproute.yaml`
- **Line:** ~8
- **Type:** String
- **Description:** Name of your Gateway resource
- **How to find:** `kubectl get gateway -A`
### Gateway Namespace
- **Variable:** `parentRefs[0].namespace`
- **File:** `k8s/httproute.yaml`
- **Line:** ~9
- **Type:** String
- **Description:** Namespace where Gateway is deployed
- **How to find:** `kubectl get gateway -A`
### Domain Hostname
- **Variable:** `hostnames[0]`
- **File:** `k8s/httproute.yaml`
- **Line:** ~11
- **Type:** String (FQDN)
- **Description:** Domain name for accessing the container
- **Example:** `devcontainer.example.com`
## Optional Variables
### GitHub Token
- **Variable:** `github-token`
- **File:** Sealed Secret
- **Type:** String (GitHub PAT)
- **Description:** Personal Access Token for private repos
- **Required:** Only for private repositories
- **Format:** `ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`
- **Scopes:** `repo`
### VNC Password
- **Variable:** `vnc-password`
- **File:** Sealed Secret
- **Type:** String
- **Description:** Password for VNC web interface
- **Required:** Recommended for security
- **Format:** Any string (12+ characters recommended)
### Namespace
- **Variable:** `namespace`
- **File:** `k8s/kustomization.yaml`
- **Line:** ~5
- **Type:** String
- **Description:** Kubernetes namespace for deployment
- **Default:** `default`
### Container Image
- **Variable:** `image`
- **File:** `k8s/statefulset.yaml`
- **Line:** ~32
- **Type:** String (image reference)
- **Description:** Docker image to deploy
- **Default:** `ghcr.io/cpfarhood/devcontainer:latest`
- **Format:** `registry/repository:tag`
### Memory Request
- **Variable:** `resources.requests.memory`
- **File:** `k8s/statefulset.yaml`
- **Line:** ~99
- **Type:** String (quantity)
- **Description:** Minimum memory to reserve
- **Default:** `2Gi`
- **Format:** `<number>Gi` or `<number>Mi`
### Memory Limit
- **Variable:** `resources.limits.memory`
- **File:** `k8s/statefulset.yaml`
- **Line:** ~102
- **Type:** String (quantity)
- **Description:** Maximum memory allowed
- **Default:** `8Gi`
- **Format:** `<number>Gi` or `<number>Mi`
### CPU Request
- **Variable:** `resources.requests.cpu`
- **File:** `k8s/statefulset.yaml`
- **Line:** ~100
- **Type:** String (quantity)
- **Description:** Minimum CPU to reserve
- **Default:** `1000m` (1 core)
- **Format:** `<number>m` (millicores) or `<number>` (cores)
### CPU Limit
- **Variable:** `resources.limits.cpu`
- **File:** `k8s/statefulset.yaml`
- **Line:** ~103
- **Type:** String (quantity)
- **Description:** Maximum CPU allowed
- **Default:** `4000m` (4 cores)
- **Format:** `<number>m` (millicores) or `<number>` (cores)
### Storage Size
- **Variable:** `storage` (under volumeClaimTemplates)
- **File:** `k8s/statefulset.yaml`
- **Line:** ~120
- **Type:** String (quantity)
- **Description:** Size of home directory PVC
- **Default:** `10Gi`
- **Format:** `<number>Gi` or `<number>Ti`
### Happy Server URL
- **Variable:** `happy-server-url`
- **File:** `k8s/configmap.yaml`
- **Line:** ~12 (commented)
- **Type:** String (URL)
- **Description:** Custom Happy Coder server
- **Default:** `https://api.cluster-fluster.com`
- **When to set:** Self-hosted Happy instance only
### Happy Webapp URL
- **Variable:** `happy-webapp-url`
- **File:** `k8s/configmap.yaml`
- **Line:** ~13 (commented)
- **Type:** String (URL)
- **Description:** Custom Happy Coder webapp
- **Default:** `https://app.happy.engineering`
- **When to set:** Self-hosted Happy instance only
### Display Width
- **Variable:** `DISPLAY_WIDTH`
- **File:** `k8s/statefulset.yaml`
- **Line:** ~56
- **Type:** String (number)
- **Description:** VNC display width in pixels
- **Default:** `1920`
### Display Height
- **Variable:** `DISPLAY_HEIGHT`
- **File:** `k8s/statefulset.yaml`
- **Line:** ~58
- **Type:** String (number)
- **Description:** VNC display height in pixels
- **Default:** `1080`
### User ID
- **Variable:** `USER_ID`
- **File:** `k8s/statefulset.yaml`
- **Line:** ~51
- **Type:** String (number)
- **Description:** UID for claude user
- **Default:** `1000`
### Group ID
- **Variable:** `GROUP_ID`
- **File:** `k8s/statefulset.yaml`
- **Line:** ~53
- **Type:** String (number)
- **Description:** GID for claude user
- **Default:** `1000`
### StatefulSet Replicas
- **Variable:** `replicas`
- **File:** `k8s/statefulset.yaml`
- **Line:** ~21
- **Type:** Integer
- **Description:** Number of container instances
- **Default:** `1`
- **Note:** Each replica gets own home PVC
## Environment Variables (Runtime)
These are set at runtime, not in configuration files:
### GITHUB_REPO
- **Type:** String (URL)
- **Description:** Repository URL (from ConfigMap)
- **Required:** Yes
- **Source:** ConfigMap `antigravity.github-repo`
### GITHUB_TOKEN
- **Type:** String
- **Description:** GitHub PAT (from Secret)
- **Required:** No (only for private repos)
- **Source:** Secret `antigravity.github-token`
### VNC_PASSWORD
- **Type:** String
- **Description:** VNC password (from Secret)
- **Required:** No
- **Source:** Secret `antigravity.vnc-password`
### HAPPY_SERVER_URL
- **Type:** String (URL)
- **Description:** Happy server URL (from ConfigMap)
- **Required:** No
- **Source:** ConfigMap `antigravity.happy-server-url`
### HAPPY_WEBAPP_URL
- **Type:** String (URL)
- **Description:** Happy webapp URL (from ConfigMap)
- **Required:** No
- **Source:** ConfigMap `antigravity.happy-webapp-url`
### HAPPY_HOME_DIR
- **Type:** String (path)
- **Description:** Happy data directory
- **Required:** No
- **Default:** `/home/claude/.happy`
- **Source:** Hardcoded in StatefulSet
### HAPPY_EXPERIMENTAL
- **Type:** String (boolean)
- **Description:** Enable Happy experimental features
- **Required:** No
- **Default:** `true`
- **Source:** Hardcoded in StatefulSet
## Variable Groups by Use Case
### Minimal Deployment
Only these variables are required for basic deployment:
1. `storageClassName`
2. `github-repo`
3. `parentRefs.name`
4. `parentRefs.namespace`
5. `hostnames`
### Private Repository Deployment
Add these for private repos:
1. All minimal deployment variables
2. `github-token` (sealed secret)
### Production Deployment
Recommended for production:
1. All private repository variables
2. `vnc-password` (sealed secret)
3. `resources.requests.*` (adjusted for workload)
4. `resources.limits.*` (adjusted for workload)
5. `namespace` (dedicated namespace)
### Multi-User Deployment
For multiple users:
1. All production deployment variables
2. `replicas` (set to number of users)
3. Larger `storage` size for home PVCs
## Quick Copy Templates
### Minimal Required Variables
```yaml
# k8s/statefulset.yaml
storageClassName: "CHANGE_ME" # Line ~117
# k8s/configmap.yaml
github-repo: "CHANGE_ME" # Line ~9
# k8s/httproute.yaml
parentRefs:
- name: CHANGE_ME # Line ~8
namespace: CHANGE_ME # Line ~9
hostnames:
- "CHANGE_ME" # Line ~11
```
### With Secrets
```bash
kubectl create secret generic antigravity-secrets \
--from-literal=github-token='CHANGE_ME' \
--from-literal=vnc-password='CHANGE_ME' \
--dry-run=client -o yaml | \
kubeseal --format=yaml > k8s/sealedsecrets.yaml
```
### With Resource Adjustments
```yaml
# k8s/statefulset.yaml (lines ~98-103)
resources:
requests:
memory: "CHANGE_ME" # e.g., 4Gi
cpu: "CHANGE_ME" # e.g., 2000m
limits:
memory: "CHANGE_ME" # e.g., 16Gi
cpu: "CHANGE_ME" # e.g., 8000m
```
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
-11
View File
@@ -1,11 +0,0 @@
<!DOCTYPE html>
<html>
<head><title>Dev Container Helm Chart Repository</title></head>
<body>
<h1>Dev Container Helm Chart Repository</h1>
<p>Add this repository to Helm:</p>
<pre>helm repo add devcontainer https://farhoodliquor.github.io/devcontainer</pre>
<p>Install the chart:</p>
<pre>helm install mydev devcontainer/devcontainer --set name=mydev</pre>
</body>
</html>
-286
View File
@@ -1,286 +0,0 @@
apiVersion: v1
entries:
devcontainer:
- apiVersion: v2
appVersion: latest
created: "2026-03-11T12:15:44.634530101Z"
description: Dev Container with AI coding agents and MCP sidecars
digest: 0c46b5d7a889cc21c28b8b088eb6c0c785a3f9324a4b39d14813c4eefe3f8e7a
keywords:
- development
- devcontainer
- vscode
- ai
name: devcontainer
type: application
urls:
- https://farhoodliquor.github.io/devcontainer/devcontainer-2.6.0.tgz
version: 2.6.0
- apiVersion: v2
appVersion: latest
created: "2026-03-11T12:15:44.633861353Z"
description: Dev Container with AI coding agents and MCP sidecars
digest: 010294a1a9b4bb6a92c685d819a0cd34dd03bc111da715d0807799168d0aba66
keywords:
- development
- devcontainer
- vscode
- ai
name: devcontainer
type: application
urls:
- https://farhoodliquor.github.io/devcontainer/devcontainer-2.4.0.tgz
version: 2.4.0
- apiVersion: v2
appVersion: latest
created: "2026-03-11T12:15:44.633145718Z"
description: Dev Container with AI coding agents and MCP sidecars - supports persistent
and dynamic deployment modes
digest: a650e9c7a8feb961232aee4048d3bf0ff1d04c55100f51a7db138e1a0f8b524e
keywords:
- development
- devcontainer
- vscode
- ai
- knative
- serverless
name: devcontainer
type: application
urls:
- https://farhoodliquor.github.io/devcontainer/devcontainer-2.3.0.tgz
version: 2.3.0
- apiVersion: v2
appVersion: latest
created: "2026-03-11T12:15:44.631873087Z"
description: Dev Container with AI coding agents and MCP sidecars - supports persistent
and dynamic deployment modes
digest: f5c440846e7672239a6f7b14a393888988ef627d896bc967bfc018130d65921d
keywords:
- development
- devcontainer
- vscode
- ai
- knative
- serverless
name: devcontainer
type: application
urls:
- https://farhoodliquor.github.io/devcontainer/devcontainer-2.2.5.tgz
version: 2.2.5
- apiVersion: v2
appVersion: latest
created: "2026-03-11T12:15:44.6304485Z"
description: Dev Container with AI coding agents and MCP sidecars - supports persistent
and dynamic deployment modes
digest: 2bea7dc5c198a5b4dab0b74f0a75089210c7ba49b56176ba2af205b7dac3fe23
keywords:
- development
- devcontainer
- vscode
- ai
- knative
- serverless
name: devcontainer
type: application
urls:
- https://farhoodliquor.github.io/devcontainer/devcontainer-2.2.4.tgz
version: 2.2.4
- apiVersion: v2
appVersion: latest
created: "2026-03-11T12:15:44.62965028Z"
description: Dev Container with AI coding agents and MCP sidecars - supports persistent
and dynamic deployment modes
digest: afde89b22d7e4a5dfd4c918a06258d9f27f1b17493a70dba98d1ae544280505a
keywords:
- development
- devcontainer
- vscode
- ai
- knative
- serverless
name: devcontainer
type: application
urls:
- https://farhoodliquor.github.io/devcontainer/devcontainer-2.2.3.tgz
version: 2.2.3
- apiVersion: v2
appVersion: latest
created: "2026-03-11T12:15:44.628801186Z"
description: Dev Container with AI coding agents and MCP sidecars - supports persistent
and dynamic deployment modes
digest: 5b3b994b74da01579156021fcfb718c61989def7c16cafadb36e7ddc90cbeea7
keywords:
- development
- devcontainer
- vscode
- ai
- knative
- serverless
name: devcontainer
type: application
urls:
- https://farhoodliquor.github.io/devcontainer/devcontainer-2.2.2.tgz
version: 2.2.2
- apiVersion: v2
appVersion: latest
created: "2026-03-11T12:15:44.627970857Z"
description: Dev Container with AI coding agents and MCP sidecars - supports persistent
and dynamic deployment modes
digest: 8db383b24252edd37998c56bbba76793d1b6eeb37365a6894a713eef6af81210
keywords:
- development
- devcontainer
- vscode
- ai
- knative
- serverless
name: devcontainer
type: application
urls:
- https://farhoodliquor.github.io/devcontainer/devcontainer-2.2.1.tgz
version: 2.2.1
- apiVersion: v2
appVersion: latest
created: "2026-03-11T12:15:44.627169642Z"
description: Dev Container with AI coding agents and MCP sidecars - supports persistent
and dynamic deployment modes
digest: a1ea207bc96a35cc545d12fa8aca00452792de54e3fae74993260cd69afee0fa
keywords:
- development
- devcontainer
- vscode
- ai
- knative
- serverless
name: devcontainer
type: application
urls:
- https://farhoodliquor.github.io/devcontainer/devcontainer-2.2.0.tgz
version: 2.2.0
- apiVersion: v2
appVersion: latest
created: "2026-03-11T12:15:44.626328122Z"
description: Dev Container with AI coding agents and MCP sidecars - supports persistent
and dynamic deployment modes
digest: beac1182a39f158fb9aa1f3308b4b030bf378d612f2aa860f792fad62aa30321
keywords:
- development
- devcontainer
- vscode
- ai
- knative
- serverless
name: devcontainer
type: application
urls:
- https://farhoodliquor.github.io/devcontainer/devcontainer-2.1.1.tgz
version: 2.1.1
- apiVersion: v2
appVersion: latest
created: "2026-03-11T12:15:44.625121312Z"
description: Dev Container with AI coding agents and MCP sidecars - supports persistent
and dynamic deployment modes
digest: efb6cbd932a7ac082853d305e970db72e0086543a6963baabef16ebd2e8498f8
keywords:
- development
- devcontainer
- vscode
- ai
- knative
- serverless
name: devcontainer
type: application
urls:
- https://farhoodliquor.github.io/devcontainer/devcontainer-2.1.0.tgz
version: 2.1.0
- apiVersion: v2
appVersion: latest
created: "2026-03-11T12:15:44.623735055Z"
description: Dev Container with AI coding agents and MCP sidecars - supports persistent
and dynamic deployment modes
digest: 46f25124d9045802d0e50d34209d15a7fa15e1ef1c9d3f0e93ac4bb39b7c9b17
keywords:
- development
- devcontainer
- vscode
- ai
- knative
- serverless
name: devcontainer
type: application
urls:
- https://farhoodliquor.github.io/devcontainer/devcontainer-2.0.5.tgz
version: 2.0.5
- apiVersion: v2
appVersion: latest
created: "2026-03-11T12:15:44.622870733Z"
description: Dev Container with AI coding agents and MCP sidecars - supports persistent
and dynamic deployment modes
digest: db82381ffe831b07ce7777e8e6e05455a8eaeccfcd0afcd87825433a96cb2d65
keywords:
- development
- devcontainer
- vscode
- ai
- knative
- serverless
name: devcontainer
type: application
urls:
- https://farhoodliquor.github.io/devcontainer/devcontainer-2.0.4.tgz
version: 2.0.4
- apiVersion: v2
appVersion: latest
created: "2026-03-11T12:15:44.622004867Z"
description: Dev Container with AI coding agents and MCP sidecars - supports persistent
and dynamic deployment modes
digest: 872919ea64531b35dfa7f956d8a6e4130a1c7f0f80c50141b6f2d1cddd49682e
keywords:
- development
- devcontainer
- vscode
- ai
- knative
- serverless
name: devcontainer
type: application
urls:
- https://farhoodliquor.github.io/devcontainer/devcontainer-2.0.3.tgz
version: 2.0.3
- apiVersion: v2
appVersion: latest
created: "2026-03-11T12:15:44.621180038Z"
description: Dev Container with AI coding agents and MCP sidecars - supports persistent
and dynamic deployment modes
digest: 7cbb5379f8b41bc938a29b44c563757358c25fd843c75fb6d2f1a2b9365c0cf1
keywords:
- development
- devcontainer
- vscode
- ai
- knative
- serverless
name: devcontainer
type: application
urls:
- https://farhoodliquor.github.io/devcontainer/devcontainer-2.0.1-dev.tgz
version: 2.0.1-dev
- apiVersion: v2
appVersion: latest
created: "2026-03-11T12:15:44.620303012Z"
description: Dev Container with AI coding agents and MCP sidecars - supports persistent
and dynamic deployment modes
digest: 5736c92626e2c3edb8e81ddba5be581360dbf3901ccc607db8bad238ea831cd0
keywords:
- development
- devcontainer
- vscode
- ai
- knative
- serverless
name: devcontainer
type: application
urls:
- https://farhoodliquor.github.io/devcontainer/devcontainer-2.0.0-dev.tgz
version: 2.0.0-dev
generated: "2026-03-11T12:15:44.619306973Z"
+13
View File
@@ -0,0 +1,13 @@
---
apiVersion: v1
kind: ConfigMap
metadata:
name: antigravity-config
data:
# GitHub repository to clone on startup
# Example: "https://github.com/username/repository"
github-repo: ""
# Happy Coder configuration (optional)
# happy-server-url: "https://api.cluster-fluster.com"
# happy-webapp-url: "https://app.happy.engineering"
+20
View File
@@ -0,0 +1,20 @@
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: antigravity
spec:
parentRefs:
- name: gateway # Replace with your Gateway name
namespace: gateway-system # Replace with your Gateway namespace
hostnames:
- "antigravity.example.com" # Replace with your domain
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: antigravity
port: 5800
weight: 1
+25
View File
@@ -0,0 +1,25 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: default
resources:
- configmap.yaml
- statefulset.yaml
- httproute.yaml
# Uncomment to create secrets from files
# secretGenerator:
# - name: antigravity-secrets
# literals:
# - github-token=ghp_your_token
# - vnc-password=your_password
commonLabels:
app: antigravity
environment: production
commonAnnotations:
managed-by: kustomize
description: "Antigravity Dev Container with Happy Coder"
+15
View File
@@ -0,0 +1,15 @@
---
# Example secrets - DO NOT commit actual secrets!
# Use SealedSecrets or another secret management solution
apiVersion: v1
kind: Secret
metadata:
name: antigravity-secrets
type: Opaque
stringData:
# GitHub Personal Access Token (for private repos)
github-token: "ghp_your_token_here"
# VNC Password (optional, for secure VNC access)
vnc-password: "your_vnc_password"
+127
View File
@@ -0,0 +1,127 @@
---
apiVersion: v1
kind: Service
metadata:
name: antigravity
labels:
app: antigravity
spec:
ports:
- port: 5800
name: vnc-web
protocol: TCP
clusterIP: None
selector:
app: antigravity
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: antigravity
spec:
serviceName: "antigravity"
replicas: 1
selector:
matchLabels:
app: antigravity
template:
metadata:
labels:
app: antigravity
spec:
securityContext:
fsGroup: 1000
fsGroupChangePolicy: "OnRootMismatch"
containers:
- name: antigravity
image: ghcr.io/cpfarhood/antigravity:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 5800
name: vnc-web
protocol: TCP
volumeMounts:
- name: userhome
mountPath: /home
- name: workspace
mountPath: /workspace
env:
# User/Group IDs for the claude user
- name: USER_ID
value: "1000"
- name: GROUP_ID
value: "1000"
# VNC display settings
- name: DISPLAY_WIDTH
value: "1920"
- name: DISPLAY_HEIGHT
value: "1080"
- name: SECURE_CONNECTION
value: "1"
- name: VNC_PASSWORD
valueFrom:
secretKeyRef:
name: antigravity
key: vnc-password
optional: true
# GitHub configuration
- name: GITHUB_REPO
valueFrom:
configMapKeyRef:
name: antigravity
key: github-repo
optional: true
- name: GITHUB_TOKEN
valueFrom:
secretKeyRef:
name: antigravity
key: github-token
optional: true
# Happy Coder configuration (optional)
- name: HAPPY_SERVER_URL
valueFrom:
configMapKeyRef:
name: antigravity
key: happy-server-url
optional: true
- name: HAPPY_WEBAPP_URL
valueFrom:
configMapKeyRef:
name: antigravity
key: happy-webapp-url
optional: true
- name: HAPPY_HOME_DIR
value: "/home/claude/.happy"
- name: HAPPY_EXPERIMENTAL
value: "true"
resources:
requests:
memory: "2Gi"
cpu: "1000m"
limits:
memory: "8Gi"
cpu: "4000m"
livenessProbe:
httpGet:
path: /
port: 5800
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /
port: 5800
initialDelaySeconds: 10
periodSeconds: 5
volumes:
- name: workspace
emptyDir: {}
volumeClaimTemplates:
- metadata:
name: userhome
spec:
accessModes: [ "ReadWriteMany" ]
storageClassName: "ceph-filesystem"
resources:
requests:
storage: 10Gi
+78
View File
@@ -0,0 +1,78 @@
#!/bin/bash
# Initialize repository and start Happy Coder
set -e
echo "=== Repository Initialization ==="
# Check if GITHUB_REPO is set
if [ -z "$GITHUB_REPO" ]; then
echo "GITHUB_REPO not set, skipping repository clone"
WORKSPACE_DIR="/workspace/default"
mkdir -p "$WORKSPACE_DIR"
else
# Parse repo name from URL
REPO_NAME=$(basename "$GITHUB_REPO" .git)
WORKSPACE_DIR="/workspace/$REPO_NAME"
echo "Repository: $GITHUB_REPO"
echo "Target directory: $WORKSPACE_DIR"
# Check if repo already exists
if [ -d "$WORKSPACE_DIR/.git" ]; then
echo "Repository already exists, pulling latest changes..."
cd "$WORKSPACE_DIR"
# Configure git to use token if provided
if [ -n "$GITHUB_TOKEN" ]; then
git config credential.helper store
echo "https://oauth2:${GITHUB_TOKEN}@github.com" > /home/claude/.git-credentials
chmod 600 /home/claude/.git-credentials
fi
git pull || echo "Pull failed, continuing anyway..."
else
echo "Cloning repository..."
mkdir -p "$(dirname "$WORKSPACE_DIR")"
# Clone with token if provided
if [ -n "$GITHUB_TOKEN" ]; then
# Replace https://github.com/ with https://oauth2:token@github.com/
CLONE_URL=$(echo "$GITHUB_REPO" | sed "s|https://github.com/|https://oauth2:${GITHUB_TOKEN}@github.com/|")
git clone "$CLONE_URL" "$WORKSPACE_DIR"
# Configure credentials for future use
git config --global credential.helper store
echo "https://oauth2:${GITHUB_TOKEN}@github.com" > /home/claude/.git-credentials
chmod 600 /home/claude/.git-credentials
else
git clone "$GITHUB_REPO" "$WORKSPACE_DIR"
fi
fi
fi
# Set ownership
chown -R claude:claude "$WORKSPACE_DIR"
chown -R claude:claude /home/claude
# Start Happy Coder in background as claude user
echo "Starting Happy Coder..."
cd "$WORKSPACE_DIR"
# Create Happy Coder log file
HAPPY_LOG="/tmp/happy-coder.log"
touch "$HAPPY_LOG"
chown claude:claude "$HAPPY_LOG"
# Start Happy Coder as claude user
sudo -u claude bash -c "cd '$WORKSPACE_DIR' && happy-coder > '$HAPPY_LOG' 2>&1 &"
# Save PID for monitoring
echo $! > /tmp/happy-coder.pid
echo "Happy Coder started (PID: $(cat /tmp/happy-coder.pid))"
echo "Logs available at: $HAPPY_LOG"
# Export workspace directory for startapp.sh
echo "$WORKSPACE_DIR" > /tmp/workspace-dir
echo "=== Initialization Complete ==="
+21
View File
@@ -0,0 +1,21 @@
#!/bin/bash
# Start application script for baseimage-gui
set -e
echo "=== Starting Antigravity Dev Container ==="
# Initialize repository and Happy Coder
/usr/local/bin/init-repo
# Get workspace directory
if [ -f /tmp/workspace-dir ]; then
WORKSPACE_DIR=$(cat /tmp/workspace-dir)
else
WORKSPACE_DIR="/workspace/default"
fi
echo "Opening Antigravity in: $WORKSPACE_DIR"
# Start Antigravity (VSCode) in the workspace directory as claude user
# The baseimage-gui will handle the GUI display
exec sudo -u claude code --new-window --wait "$WORKSPACE_DIR"