From dfc0a3c1e3b7b4fc9d5e3a3b82edabdfb90b9f65 Mon Sep 17 00:00:00 2001 From: Chris Farhood Date: Thu, 19 Feb 2026 19:55:05 -0500 Subject: [PATCH] catchup --- .mcp.json | 29 ++++ .../configmap.yaml.example | 4 +- flux/httproute.yaml | 20 +++ {k8s => flux}/kustomization.yaml | 6 +- .../secrets.yaml.example | 0 flux/service.yaml | 13 ++ flux/statefulset.yaml | 83 ++++++++++++ k8s/httproute.yaml | 20 --- k8s/statefulset.yaml | 127 ------------------ memory/MEMORY.md | 20 +++ 10 files changed, 169 insertions(+), 153 deletions(-) create mode 100644 .mcp.json rename k8s/configmap.yaml => flux/configmap.yaml.example (74%) create mode 100644 flux/httproute.yaml rename {k8s => flux}/kustomization.yaml (91%) rename k8s/secrets-example.yaml => flux/secrets.yaml.example (100%) create mode 100644 flux/service.yaml create mode 100644 flux/statefulset.yaml delete mode 100644 k8s/httproute.yaml delete mode 100644 k8s/statefulset.yaml create mode 100644 memory/MEMORY.md diff --git a/.mcp.json b/.mcp.json new file mode 100644 index 0000000..2e9a710 --- /dev/null +++ b/.mcp.json @@ -0,0 +1,29 @@ +{ + "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"] + } + } +} diff --git a/k8s/configmap.yaml b/flux/configmap.yaml.example similarity index 74% rename from k8s/configmap.yaml rename to flux/configmap.yaml.example index ae929cd..051b8fe 100644 --- a/k8s/configmap.yaml +++ b/flux/configmap.yaml.example @@ -2,11 +2,11 @@ apiVersion: v1 kind: ConfigMap metadata: - name: antigravity + name: devcontainer data: # GitHub repository to clone on startup # Example: "https://github.com/username/repository" - github-repo: "https://github.com/privilegedescalation/headlamp-polaris-plugin" + # github-repo: "https://github.com/username/repository" # Happy Coder configuration (optional) # happy-server-url: "https://api.cluster-fluster.com" diff --git a/flux/httproute.yaml b/flux/httproute.yaml new file mode 100644 index 0000000..6565f18 --- /dev/null +++ b/flux/httproute.yaml @@ -0,0 +1,20 @@ +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: antigravity +spec: + parentRefs: + - name: external + namespace: gateway-system + hostnames: + - ${FQDN} + rules: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: + - name: antigravity + port: 5800 + weight: 1 diff --git a/k8s/kustomization.yaml b/flux/kustomization.yaml similarity index 91% rename from k8s/kustomization.yaml rename to flux/kustomization.yaml index d74b595..88da8d0 100644 --- a/k8s/kustomization.yaml +++ b/flux/kustomization.yaml @@ -1,12 +1,10 @@ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization - -namespace: cpfarhood - resources: - - configmap.yaml + # - configmap.yaml - statefulset.yaml + - service.yaml # Uncomment to create secrets from files # secretGenerator: diff --git a/k8s/secrets-example.yaml b/flux/secrets.yaml.example similarity index 100% rename from k8s/secrets-example.yaml rename to flux/secrets.yaml.example diff --git a/flux/service.yaml b/flux/service.yaml new file mode 100644 index 0000000..51d9d70 --- /dev/null +++ b/flux/service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: devcontainer + labels: + app: devcontainer +spec: + ports: + - port: 5800 + name: vnc-web + protocol: TCP + selector: + app: devcontainer diff --git a/flux/statefulset.yaml b/flux/statefulset.yaml new file mode 100644 index 0000000..dbfe179 --- /dev/null +++ b/flux/statefulset.yaml @@ -0,0 +1,83 @@ +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: antigravity +spec: + serviceName: "antigravity" + replicas: 1 + selector: + matchLabels: + app: devcontainer + template: + metadata: + labels: + app: devcontainer + spec: + securityContext: + fsGroup: 1000 + fsGroupChangePolicy: "OnRootMismatch" + containers: + - name: antigravity + image: ghcr.io/cpfarhood/devcontainer:latest + imagePullPolicy: Always + 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: "0" + - name: HAPPY_HOME_DIR + value: "/home/user/.happy" + - name: HAPPY_EXPERIMENTAL + value: "true" + envFrom: + - configMapRef: ${ENV_CONFIGMAP} + - secretRef: ${ENV_SECRETS} + 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 diff --git a/k8s/httproute.yaml b/k8s/httproute.yaml deleted file mode 100644 index 9eb777f..0000000 --- a/k8s/httproute.yaml +++ /dev/null @@ -1,20 +0,0 @@ ---- -apiVersion: gateway.networking.k8s.io/v1 -kind: HTTPRoute -metadata: - name: antigravity -spec: - parentRefs: - - name: external - namespace: gateway-system - hostnames: - - "antigravity.farh.net" - rules: - - matches: - - path: - type: PathPrefix - value: / - backendRefs: - - name: antigravity - port: 5800 - weight: 1 diff --git a/k8s/statefulset.yaml b/k8s/statefulset.yaml deleted file mode 100644 index ac54982..0000000 --- a/k8s/statefulset.yaml +++ /dev/null @@ -1,127 +0,0 @@ ---- -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/devcontainer:latest - imagePullPolicy: Always - 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: "0" - - 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 diff --git a/memory/MEMORY.md b/memory/MEMORY.md new file mode 100644 index 0000000..0f533f0 --- /dev/null +++ b/memory/MEMORY.md @@ -0,0 +1,20 @@ +# 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