Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b27487d844 | |||
| 24b31e061a | |||
| aad4ec4287 | |||
| 4915fce118 | |||
| 7940419c4e | |||
| 9ddbcc1e68 | |||
| 07a6baefd7 | |||
| 720e6d7de9 | |||
| c89d7e4ed6 | |||
| 80763b817d | |||
| 2bb60745ce | |||
| 46cef775b1 | |||
| b83265f131 | |||
| 695850469d | |||
| eca8d10772 | |||
| 0eaf1645e1 | |||
| 8b8af85558 | |||
| a9593a763f | |||
| 129f49abe8 | |||
| 58ee2d6770 | |||
| 955f26ab37 |
@@ -1,24 +0,0 @@
|
||||
.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
|
||||
@@ -1,36 +0,0 @@
|
||||
## 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 -->
|
||||
@@ -1,19 +0,0 @@
|
||||
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"
|
||||
@@ -1,64 +0,0 @@
|
||||
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
|
||||
@@ -1,37 +0,0 @@
|
||||
name: Publish Helm Chart
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'chart/**'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Helm
|
||||
uses: azure/setup-helm@v4
|
||||
|
||||
- name: Log in to GHCR
|
||||
run: |
|
||||
helm registry login ghcr.io \
|
||||
--username ${{ github.actor }} \
|
||||
--password ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Package chart
|
||||
run: helm package chart/
|
||||
|
||||
- name: Push chart to GHCR
|
||||
run: |
|
||||
CHART_VERSION=$(helm show chart chart/ | grep '^version:' | awk '{print $2}')
|
||||
helm push antigravity-${CHART_VERSION}.tgz oci://ghcr.io/cpfarhood/charts
|
||||
@@ -1,51 +0,0 @@
|
||||
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
|
||||
@@ -1,259 +0,0 @@
|
||||
# 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
@@ -1,24 +0,0 @@
|
||||
# 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
|
||||
@@ -1,29 +0,0 @@
|
||||
{
|
||||
"mcpServers": {
|
||||
"github": {
|
||||
"command": "github-mcp-server",
|
||||
"args": ["stdio"],
|
||||
"env": {
|
||||
"GITHUB_PERSONAL_ACCESS_TOKEN": "${CLAUDE_GITHUB_TOKEN}"
|
||||
}
|
||||
},
|
||||
"kubernetes (local)": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"kubernetes-mcp-server@latest"
|
||||
]
|
||||
},
|
||||
"flux (local)":{
|
||||
"command":"flux-operator-mcp",
|
||||
"args":["serve"],
|
||||
"env":{
|
||||
"KUBECONFIG":"/Users/cpfarhood/.kube/config"
|
||||
}
|
||||
},
|
||||
"playwright": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@playwright/mcp@latest"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
# 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
|
||||
@@ -1,107 +0,0 @@
|
||||
# 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`)
|
||||
-436
@@ -1,436 +0,0 @@
|
||||
# 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
@@ -1,76 +0,0 @@
|
||||
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=user
|
||||
|
||||
# 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 user user with specific UID/GID
|
||||
RUN groupadd -g 1000 user && \
|
||||
useradd -u 1000 -g 1000 -m -s /bin/bash user && \
|
||||
echo "user ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
|
||||
|
||||
# Create workspace directory
|
||||
RUN mkdir -p /workspace && \
|
||||
chown -R user:user /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 user user
|
||||
ENV HOME=/home/user \
|
||||
USER=user
|
||||
|
||||
# Expose VNC port (baseimage-gui default)
|
||||
EXPOSE 5800
|
||||
|
||||
# Set app name for baseimage-gui
|
||||
RUN set-cont-env APP_NAME "Antigravity"
|
||||
@@ -1,101 +0,0 @@
|
||||
.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"
|
||||
@@ -1,367 +0,0 @@
|
||||
# Antigravity Dev Container
|
||||
|
||||

|
||||
|
||||
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
@@ -1,305 +0,0 @@
|
||||
# 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
|
||||
```
|
||||
@@ -1,6 +0,0 @@
|
||||
apiVersion: v2
|
||||
name: antigravity
|
||||
description: Antigravity Dev Container with Happy Coder AI assistant
|
||||
type: application
|
||||
version: 0.1.0
|
||||
appVersion: "latest"
|
||||
@@ -1,28 +0,0 @@
|
||||
{{/*
|
||||
Resource name prefix: devcontainer-{name}
|
||||
*/}}
|
||||
{{- define "antigravity.fullname" -}}
|
||||
{{- printf "devcontainer-%s" .Values.name }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
PVC name: userhome-{name}
|
||||
*/}}
|
||||
{{- define "antigravity.pvcName" -}}
|
||||
{{- printf "userhome-%s" .Values.name }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Secret name for env vars, default to devcontainer-{name}-secrets-env
|
||||
*/}}
|
||||
{{- define "antigravity.envSecretName" -}}
|
||||
{{- .Values.envSecretName | default (printf "devcontainer-%s-secrets-env" .Values.name) }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Common labels
|
||||
*/}}
|
||||
{{- define "antigravity.labels" -}}
|
||||
app: devcontainer
|
||||
instance: {{ .Values.name }}
|
||||
{{- end }}
|
||||
@@ -1,77 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "antigravity.fullname" . }}
|
||||
labels:
|
||||
{{- include "antigravity.labels" . | nindent 4 }}
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "antigravity.labels" . | nindent 6 }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "antigravity.labels" . | nindent 8 }}
|
||||
spec:
|
||||
securityContext:
|
||||
fsGroup: 1000
|
||||
fsGroupChangePolicy: "OnRootMismatch"
|
||||
containers:
|
||||
- name: devcontainer
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
ports:
|
||||
- containerPort: 5800
|
||||
name: vnc-web
|
||||
protocol: TCP
|
||||
env:
|
||||
- name: USER_ID
|
||||
value: {{ .Values.userId | quote }}
|
||||
- name: GROUP_ID
|
||||
value: {{ .Values.groupId | quote }}
|
||||
- name: DISPLAY_WIDTH
|
||||
value: {{ .Values.display.width | quote }}
|
||||
- name: DISPLAY_HEIGHT
|
||||
value: {{ .Values.display.height | quote }}
|
||||
- name: SECURE_CONNECTION
|
||||
value: {{ .Values.secureConnection | quote }}
|
||||
- name: HAPPY_HOME_DIR
|
||||
value: {{ .Values.happyHomeDir | quote }}
|
||||
- name: HAPPY_EXPERIMENTAL
|
||||
value: {{ .Values.happyExperimental | quote }}
|
||||
- name: HAPPY_SERVER_URL
|
||||
value: {{ .Values.happyServerUrl | quote }}
|
||||
- name: HAPPY_WEBAPP_URL
|
||||
value: {{ .Values.happyWebappUrl | quote }}
|
||||
- name: GITHUB_REPO
|
||||
value: {{ .Values.githubRepo | quote }}
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: {{ include "antigravity.envSecretName" . }}
|
||||
optional: true
|
||||
resources:
|
||||
{{- toYaml .Values.resources | nindent 12 }}
|
||||
volumeMounts:
|
||||
- name: userhome
|
||||
mountPath: /home
|
||||
- name: workspace
|
||||
mountPath: /workspace
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 5800
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 5800
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
volumes:
|
||||
- name: workspace
|
||||
emptyDir: {}
|
||||
- name: userhome
|
||||
persistentVolumeClaim:
|
||||
claimName: {{ include "antigravity.pvcName" . }}
|
||||
@@ -1,13 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: {{ include "antigravity.pvcName" . }}
|
||||
labels:
|
||||
{{- include "antigravity.labels" . | nindent 4 }}
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
storageClassName: {{ .Values.storage.className }}
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.storage.size }}
|
||||
@@ -1,14 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "antigravity.fullname" . }}
|
||||
labels:
|
||||
{{- include "antigravity.labels" . | nindent 4 }}
|
||||
spec:
|
||||
ports:
|
||||
- port: 5800
|
||||
name: vnc-web
|
||||
protocol: TCP
|
||||
targetPort: vnc-web
|
||||
selector:
|
||||
{{- include "antigravity.labels" . | nindent 4 }}
|
||||
@@ -1,43 +0,0 @@
|
||||
# Instance name — used to generate resource names (devcontainer-{name}, userhome-{name})
|
||||
name: ""
|
||||
|
||||
image:
|
||||
repository: ghcr.io/cpfarhood/devcontainer
|
||||
tag: latest
|
||||
pullPolicy: Always
|
||||
|
||||
# GitHub repository to clone into /workspace
|
||||
githubRepo: ""
|
||||
|
||||
# Happy Coder endpoints
|
||||
happyServerUrl: "https://happy.farh.net"
|
||||
happyWebappUrl: "https://happy-coder.farh.net"
|
||||
happyHomeDir: "/home/user/.happy"
|
||||
happyExperimental: "true"
|
||||
|
||||
# VNC display
|
||||
display:
|
||||
width: "1920"
|
||||
height: "1080"
|
||||
|
||||
# Set to "0" when TLS is terminated at the gateway layer
|
||||
secureConnection: "0"
|
||||
|
||||
userId: "1000"
|
||||
groupId: "1000"
|
||||
|
||||
storage:
|
||||
size: 32Gi
|
||||
className: ceph-filesystem
|
||||
|
||||
resources:
|
||||
requests:
|
||||
memory: "2Gi"
|
||||
cpu: "1000m"
|
||||
limits:
|
||||
memory: "8Gi"
|
||||
cpu: "4000m"
|
||||
|
||||
# Name of existing Secret containing env vars (GITHUB_TOKEN, VNC_PASSWORD, etc.)
|
||||
# Defaults to: devcontainer-{name}-secrets-env
|
||||
envSecretName: ""
|
||||
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
@@ -0,0 +1,11 @@
|
||||
<!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
@@ -0,0 +1,286 @@
|
||||
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"
|
||||
@@ -1,20 +0,0 @@
|
||||
# Antigravity Dev Container - Session Notes
|
||||
|
||||
## Key Architecture Facts
|
||||
- Image: `ghcr.io/cpfarhood/devcontainer:latest` (repo name is `devcontainer`, not `antigravity`)
|
||||
- `imagePullPolicy: Always` in statefulset (set during initial deployment debugging)
|
||||
- Service must NOT be headless (`clusterIP: None`) — Cilium gateway can't route to headless services
|
||||
- `SECURE_CONNECTION=0` — TLS is terminated at the gateway, not the app
|
||||
- Container user is `user` (UID 1000) — baseimage-gui runs startapp.sh as `app` user, sudo is not available
|
||||
- HTTPRoute is managed by Authentik outpost, not in kustomization
|
||||
|
||||
## Cluster Patterns
|
||||
- External gateway: `external` in `gateway-system`, handles `*.farh.net` on port 443 HTTPS only
|
||||
- Hostnames must be exactly `*.farh.net` (not `*.subdomain.farh.net`) to match gateway listener
|
||||
- Authentik outpost Terraform lives in `../kubernetes/terraform/authentik-*-proxy/`
|
||||
- Outpost config uses `external` gateway for public apps, `internal` for internal apps
|
||||
|
||||
## Common Gotchas
|
||||
- `baseimage-gui` creates user dynamically — don't hardcode usernames in scripts, use numeric UID/GID
|
||||
- `chown /home` fails (PVC root not owned by container) — only chown subdirectories
|
||||
- `sudo` not available in startapp.sh — script already runs as correct user
|
||||
@@ -1,79 +0,0 @@
|
||||
#!/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/.git-credentials
|
||||
chmod 600 /home/.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/.git-credentials
|
||||
chmod 600 /home/.git-credentials
|
||||
else
|
||||
git clone "$GITHUB_REPO" "$WORKSPACE_DIR"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Set ownership using numeric IDs (username may not exist yet in baseimage-gui)
|
||||
RUN_UID="${USER_ID:-1000}"
|
||||
RUN_GID="${GROUP_ID:-1000}"
|
||||
chown -R "$RUN_UID:$RUN_GID" "$WORKSPACE_DIR"
|
||||
|
||||
# Start Happy Coder in background as the app user
|
||||
echo "Starting Happy Coder..."
|
||||
cd "$WORKSPACE_DIR"
|
||||
|
||||
# Create Happy Coder log file
|
||||
HAPPY_LOG="/tmp/happy-coder.log"
|
||||
touch "$HAPPY_LOG"
|
||||
chown "$RUN_UID:$RUN_GID" "$HAPPY_LOG"
|
||||
|
||||
# Start Happy Coder (already running as the correct user via baseimage-gui)
|
||||
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 ==="
|
||||
@@ -1,21 +0,0 @@
|
||||
#!/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 code --new-window --wait "$WORKSPACE_DIR"
|
||||
Reference in New Issue
Block a user