Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 29 additions & 29 deletions lib/k8s/sandbox-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -642,8 +642,8 @@ export class SandboxManager {
args: [this.generateInitContainerScript()],
volumeMounts: [
{
name: 'vn-homevn-agent',
mountPath: '/home/agent',
name: 'vn-homevn-fulling',
mountPath: '/home/fulling',
},
],
securityContext: {
Expand Down Expand Up @@ -686,8 +686,8 @@ export class SandboxManager {
imagePullPolicy: 'Always',
volumeMounts: [
{
name: 'vn-homevn-agent',
mountPath: '/home/agent',
name: 'vn-homevn-fulling',
mountPath: '/home/fulling',
},
],
},
Expand All @@ -699,10 +699,10 @@ export class SandboxManager {
{
metadata: {
annotations: {
path: '/home/agent',
path: '/home/fulling',
value: VERSIONS.STORAGE.SANDBOX_SIZE.replace('Gi', ''),
},
name: 'vn-homevn-agent',
name: 'vn-homevn-fulling',
},
spec: {
accessModes: ['ReadWriteOnce'],
Expand Down Expand Up @@ -739,7 +739,7 @@ export class SandboxManager {
/**
* Generate init container script
*
* Purpose: Initialize /home/agent PVC with necessary files on first run
* Purpose: Initialize /home/fulling PVC with necessary files on first run
*
* What gets initialized:
* 1. .bashrc - Shell configuration (only if doesn't exist, never overwrite user changes)
Expand All @@ -761,14 +761,14 @@ echo "=== Init Container: Home Directory Initialization ==="
# Step 1: Initialize .bashrc (if not exists)
# Rationale: User may customize .bashrc, so we never overwrite existing file
# -----------------------------------------------------------------------------
if [ -f /home/agent/.bashrc ]; then
if [ -f /home/fulling/.bashrc ]; then
echo "✓ .bashrc already exists (preserving user configuration)"
else
if [ -f /etc/skel/.bashrc ]; then
echo "→ Copying default .bashrc configuration..."
cp /etc/skel/.bashrc /home/agent/.bashrc
chown 1001:1001 /home/agent/.bashrc
chmod 644 /home/agent/.bashrc
cp /etc/skel/.bashrc /home/fulling/.bashrc
chown 1001:1001 /home/fulling/.bashrc
chmod 644 /home/fulling/.bashrc
echo "✓ .bashrc initialized"
else
echo "⚠ Warning: /etc/skel/.bashrc not found in image"
Expand All @@ -779,25 +779,25 @@ fi
# Step 2: Initialize Next.js project (if not exists or empty)
# Rationale: ANY file in next/ indicates user work - must not overwrite
# -----------------------------------------------------------------------------
if [ -d /home/agent/next ]; then
if [ -d /home/fulling/next ]; then
# Directory exists, check if it contains any files (including hidden files)
if [ -n "$(ls -A /home/agent/next 2>/dev/null)" ]; then
if [ -n "$(ls -A /home/fulling/next 2>/dev/null)" ]; then
echo "✓ Next.js project already exists (preserving user project)"
echo " Location: /home/agent/next"
echo " Location: /home/fulling/next"

# Skip to end - all initialization done
echo ""
echo "=== Initialization Summary ==="
echo "✓ .bashrc: $([ -f /home/agent/.bashrc ] && echo 'ready' || echo 'missing')"
echo "✓ .bashrc: $([ -f /home/fulling/.bashrc ] && echo 'ready' || echo 'missing')"
echo "✓ Next.js project: ready (existing)"
echo "✓ All user data preserved"
echo ""
echo "=== Init Container: Completed successfully ==="
exit 0
else
echo "→ /home/agent/next exists but is empty"
echo "→ /home/fulling/next exists but is empty"
echo "→ Removing empty directory and proceeding with initialization"
rmdir /home/agent/next
rmdir /home/fulling/next
fi
fi

Expand All @@ -815,22 +815,22 @@ fi
# Copy Next.js project template (without node_modules)
echo "→ Copying Next.js project template from /opt/next-template..."
echo " Source: /opt/next-template (agent:agent)"
echo " Target: /home/agent/next"
echo " Target: /home/fulling/next"
echo " Note: node_modules NOT included - run 'pnpm install' to install dependencies"
echo " This may take 5-10 seconds..."
mkdir -p /home/agent/next
mkdir -p /home/fulling/next

# Copy project files (node_modules already removed from image)
# Using cp instead of rsync for simplicity (rsync is available but cp is sufficient)
cp -rp /opt/next-template/. /home/agent/next 2>&1 || {
cp -rp /opt/next-template/. /home/fulling/next 2>&1 || {
echo "✗ ERROR: Failed to copy template"
exit 1
}

# Verify copy was successful
if [ ! -f /home/agent/next/package.json ]; then
if [ ! -f /home/fulling/next/package.json ]; then
echo "✗ ERROR: Project copy incomplete - package.json not found"
ls -la /home/agent/next 2>&1 || true
ls -la /home/fulling/next 2>&1 || true
exit 1
fi

Expand All @@ -840,22 +840,22 @@ echo "✓ Next.js project template copied successfully"
# Note: Even though source files are agent:agent in the image,
# cp creates new files owned by the current user (root in init container)
echo "→ Setting ownership (agent:1001) and permissions..."
chown -R 1001:1001 /home/agent/next 2>&1 || {
chown -R 1001:1001 /home/fulling/next 2>&1 || {
echo "⚠ Warning: Failed to set ownership, but continuing..."
}
chmod -R u+rwX,g+rX,o+rX /home/agent/next 2>&1 || {
chmod -R u+rwX,g+rX,o+rX /home/fulling/next 2>&1 || {
echo "⚠ Warning: Failed to set permissions, but continuing..."
}

# Count files for verification
FILE_COUNT=$(find /home/agent/next -type f | wc -l)
FILE_COUNT=$(find /home/fulling/next -type f | wc -l)
echo "✓ Copied $FILE_COUNT files"

echo ""
echo "=== Initialization Summary ==="
echo "✓ .bashrc: $([ -f /home/agent/.bashrc ] && echo 'ready' || echo 'missing')"
echo "✓ .bashrc: $([ -f /home/fulling/.bashrc ] && echo 'ready' || echo 'missing')"
echo "✓ Next.js project: ready (newly created)"
echo "✓ Location: /home/agent/next"
echo "✓ Location: /home/fulling/next"
echo "✓ Ownership: agent (1001:1001)"
echo "✓ Files copied: $FILE_COUNT"
echo "⚠ node_modules not included - run 'pnpm install' to install dependencies"
Expand Down Expand Up @@ -1187,7 +1187,7 @@ echo "=== Init Container: Completed successfully ==="
* Delete PVCs associated with a StatefulSet
*
* StatefulSets create PVCs with names: {volumeClaimTemplate.name}-{statefulset.name}-{ordinal}
* For our case: vn-homevn-agent-{sandboxName}-0
* For our case: vn-homevn-fulling-{sandboxName}-0
*
* This method handles both:
* 1. Clusters with persistentVolumeClaimRetentionPolicy support (Kubernetes 1.23+)
Expand All @@ -1200,7 +1200,7 @@ echo "=== Init Container: Completed successfully ==="
try {
// List all PVCs in namespace that belong to this StatefulSet
// StatefulSet PVC naming: {volumeClaimTemplate.name}-{statefulset.name}-{ordinal}
const pvcName = `vn-homevn-agent-${sandboxName}-0`
const pvcName = `vn-homevn-fulling-${sandboxName}-0`

try {
await this.k8sApi.deleteNamespacedPersistentVolumeClaim({
Expand Down
12 changes: 6 additions & 6 deletions sandbox/.bashrc
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ alias grep='grep --color=auto'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'

# Function to show path relative to /home/agent
# Function to show path relative to /home/fulling
_path() {
case "${PWD}" in
/home/agent) echo "/" ;;
/home/agent/*) echo "${PWD#/home/agent}" ;;
/home/fulling) echo "/" ;;
/home/fulling/*) echo "${PWD#/home/fulling}" ;;
*) echo "${PWD}" ;;
esac
}
Expand All @@ -47,9 +47,9 @@ _ps1_update() {
PROMPT_COMMAND=_ps1_update

# Change to Next.js project directory on shell start
if [ "$PWD" = "$HOME" ] && [ -d "$HOME/next" ]; then
cd "$HOME/next"
fi
# if [ "$PWD" = "$HOME" ] && [ -d "$HOME/next" ]; then
# cd "$HOME/next"
# fi

# Auto-start Claude Code CLI on first terminal connection only
# Use a file flag that persists across ttyd reconnections
Expand Down
26 changes: 13 additions & 13 deletions sandbox/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
LABEL maintainer="FullstackAgent" \
version="1.0.0" \
description="Full-stack web development runtime with Next.js, shadcn/ui, Claude Code CLI, and container tools" \
org.opencontainers.image.source="https://github.com/your-repo/FullstackAgent" \
org.opencontainers.image.source="https://github.com/FullstackAgent/fulling" \
org.opencontainers.image.licenses="MIT"

# Environment variables for build configuration
Expand All @@ -17,10 +17,10 @@
# NOTE: Sensitive variables below are declared as empty strings for documentation.
# Actual values will be securely injected at runtime via Kubernetes Secrets.
# This is safe - no actual secrets are hardcoded in the Dockerfile.
ENV DEBIAN_FRONTEND=noninteractive \

Check warning on line 20 in sandbox/Dockerfile

View workflow job for this annotation

GitHub Actions / Build Runtime Docker Images

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ENV "DOCKER_HUB_PASSWD") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/

Check warning on line 20 in sandbox/Dockerfile

View workflow job for this annotation

GitHub Actions / Build Runtime Docker Images

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ENV "ANTHROPIC_AUTH_TOKEN") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/
NODE_VERSION=22.x \
CLAUDE_CODE_VERSION=latest \
PATH="/root/.local/bin:/home/agent/.local/bin:$PATH" \
PATH="/root/.local/bin:/home/fulling/.local/bin:$PATH" \
TERM=xterm-256color \
COLORTERM=truecolor \
ANTHROPIC_BASE_URL="" \
Expand Down Expand Up @@ -89,9 +89,9 @@
# Create non-root user for security best practices
# agent user (UID 1001) with sudo privileges for development flexibility
# -----------------------------------------------------------------------------
RUN groupadd -g 1001 agent \
&& useradd -u 1001 -g 1001 -m -s /bin/bash agent \
&& echo 'agent ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
RUN groupadd -g 1001 fulling \
&& useradd -u 1001 -g 1001 -m -s /bin/bash fulling \
&& echo 'fulling ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers

# -----------------------------------------------------------------------------
# Install container tools (Buildah, Podman, Skopeo) for rootless container operations
Expand All @@ -113,13 +113,13 @@
# Configure Buildah and Podman for rootless operation
# Sets up storage, runtime, and registry configurations
# -----------------------------------------------------------------------------
RUN mkdir -p /etc/containers /home/agent/.local/share/containers /home/agent/.config/containers \
RUN mkdir -p /etc/containers /home/fulling/.local/share/containers /home/fulling/.config/containers \
# Storage configuration (VFS driver for simplicity and compatibility)
&& { \
echo '[storage]'; \
echo 'driver = "vfs"'; \
echo 'runroot = "/run/user/1001/containers"'; \
echo 'graphroot = "/home/agent/.local/share/containers/storage"'; \
echo 'graphroot = "/home/fulling/.local/share/containers/storage"'; \
echo '[storage.options]'; \
echo 'mount_program = "/usr/bin/fuse-overlayfs"'; \
} > /etc/containers/storage.conf \
Expand All @@ -136,8 +136,8 @@
echo '[registries.search]'; \
echo 'registries = ["docker.io", "quay.io"]'; \
} > /etc/containers/registries.conf \
# Set proper ownership for agent user directories
&& chown -R agent:agent /home/agent/.local /home/agent/.config
# Set proper ownership for fulling user directories
&& chown -R fulling:fulling /home/fulling/.local /home/fulling/.config

# -----------------------------------------------------------------------------
# Install development tools, GitHub CLI, and modern CLI utilities
Expand Down Expand Up @@ -189,7 +189,7 @@
ttyd --version || true

# Set working directory for application
WORKDIR /home/agent
WORKDIR /home/fulling

# -----------------------------------------------------------------------------
# Copy configuration files (placed before user switch for better caching)
Expand Down Expand Up @@ -260,8 +260,8 @@
rm -rf node_modules .next; \
echo "=== Cleaning up pnpm cache ==="; \
pnpm store prune; \
echo "=== Setting ownership to agent user (1001:1001) ==="; \
chown -R agent:agent "$TEMPLATE_DIR"; \
echo "=== Setting ownership to fulling user (1001:1001) ==="; \
chown -R fulling:fulling "$TEMPLATE_DIR"; \
echo "=== Final verification ==="; \
ls -la "$TEMPLATE_DIR"; \
if [ ! -f "$TEMPLATE_DIR/package.json" ]; then \
Expand All @@ -272,7 +272,7 @@
echo "ERROR: node_modules should have been removed"; \
exit 1; \
fi; \
echo "✓ Template ready at $TEMPLATE_DIR (owned by agent:agent)"; \
echo "✓ Template ready at $TEMPLATE_DIR (owned by fulling:fulling)"; \
echo "✓ node_modules removed - user will install dependencies as needed"

# =============================================================================
Expand Down
8 changes: 4 additions & 4 deletions yaml/sandbox/statefulset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,15 @@ spec:
name: hnkrdxqqlbuq
imagePullPolicy: Always
volumeMounts:
- name: vn-homevn-agent
mountPath: /home/agent
- name: vn-homevn-fulling
mountPath: /home/fulling
volumes: []
volumeClaimTemplates:
- metadata:
annotations:
path: /home/agent
path: /home/fulling
value: '5'
name: vn-homevn-agent
name: vn-homevn-fulling
spec:
accessModes:
- ReadWriteOnce
Expand Down
Loading