From c42b47bb5643dfb12d5c537281d9c5e2cbb9cc2e Mon Sep 17 00:00:00 2001 From: Antigravity Developer Date: Fri, 20 Feb 2026 21:31:32 +0000 Subject: [PATCH 1/2] fix: persist Chrome profile data and settings across container restarts - Add explicit --user-data-dir flag to Chrome wrapper to ensure profile data is stored in the persistent home directory - Add cont-init-home.sh script to properly initialize home directory structure on container startup with correct permissions - Ensure Chrome config directory exists before Chrome starts - Bump chart version to 0.1.13 This fixes the issue where Chrome loses authentication and settings after pod restarts by explicitly managing where Chrome stores its profile data. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude Co-Authored-By: Happy --- Dockerfile | 13 ++++++++++++- chart/Chart.yaml | 2 +- scripts/cont-init-home.sh | 26 ++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 scripts/cont-init-home.sh diff --git a/Dockerfile b/Dockerfile index 337f828..5a88405 100644 --- a/Dockerfile +++ b/Dockerfile @@ -35,7 +35,16 @@ RUN wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | gpg --dearm # Chrome wrapper: adds flags required for running inside a Docker container. # xdg-open (used by Claude Code on Linux) respects $BROWSER, so pointing it # here ensures the OAuth popup works without manual --no-sandbox invocations. -RUN printf '#!/bin/bash\nexec /usr/bin/google-chrome-stable \\\n --no-sandbox \\\n --disable-dev-shm-usage \\\n --disable-gpu \\\n "$@"\n' > /usr/local/bin/google-chrome && \ +# Also explicitly sets user-data-dir to persist Chrome settings across restarts. +RUN printf '#!/bin/bash\n\ +# Ensure Chrome data directory exists with proper permissions\n\ +mkdir -p "$HOME/.config/google-chrome"\n\ +exec /usr/bin/google-chrome-stable \\\n\ + --no-sandbox \\\n\ + --disable-dev-shm-usage \\\n\ + --disable-gpu \\\n\ + --user-data-dir="$HOME/.config/google-chrome" \\\n\ + "$@"\n' > /usr/local/bin/google-chrome && \ chmod +x /usr/local/bin/google-chrome # Install Node.js (LTS version for Happy Coder) @@ -87,6 +96,8 @@ COPY --chmod=755 scripts/startapp.sh /startapp.sh COPY --chmod=755 scripts/init-repo.sh /usr/local/bin/init-repo # Fix app user shell after baseimage-gui creates it at runtime COPY --chmod=755 scripts/cont-init-user.sh /etc/cont-init.d/20-fix-user-shell.sh +# Initialize persistent home directory structure +COPY --chmod=755 scripts/cont-init-home.sh /etc/cont-init.d/21-init-home.sh COPY --chmod=755 scripts/cont-init-sshd.sh /etc/cont-init.d/25-start-sshd.sh # Set working directory diff --git a/chart/Chart.yaml b/chart/Chart.yaml index aee1716..f362211 100644 --- a/chart/Chart.yaml +++ b/chart/Chart.yaml @@ -2,5 +2,5 @@ apiVersion: v2 name: devcontainer description: Antigravity Dev Container with Happy Coder AI assistant type: application -version: 0.1.12 +version: 0.1.13 appVersion: "latest" diff --git a/scripts/cont-init-home.sh b/scripts/cont-init-home.sh new file mode 100644 index 0000000..1ca8cc8 --- /dev/null +++ b/scripts/cont-init-home.sh @@ -0,0 +1,26 @@ +#!/bin/sh +# Initialize persistent home directory structure for the app user +# This ensures Chrome settings and SSH keys persist across pod restarts + +echo "=== Initializing persistent home directory ===" + +# Ensure the user home directory exists with proper ownership +if [ ! -d "/home/user" ]; then + echo "Creating /home/user directory..." + mkdir -p /home/user + chown app:app /home/user +fi + +# Ensure critical directories exist for persistent data +echo "Ensuring persistent directories exist..." +mkdir -p /home/user/.config +mkdir -p /home/user/.ssh +mkdir -p /home/user/.cache + +# Set proper ownership for all directories +chown -R app:app /home/user + +# Ensure SSH directory has proper permissions +chmod 700 /home/user/.ssh + +echo "Home directory initialization complete" \ No newline at end of file From b6bf4b664014679c56206c7d881508510e4131c3 Mon Sep 17 00:00:00 2001 From: Antigravity Developer Date: Fri, 20 Feb 2026 22:21:36 +0000 Subject: [PATCH 2/2] fix: mount PVC at /config to persist Chrome and app state across restarts The jlesage/baseimage-gui sets XDG_CONFIG_HOME=/config/xdg/config at runtime, so Chrome was writing its profile to /config/xdg/config/google-chrome which lived on ephemeral storage. This caused Chrome to open as a fresh install on every pod restart. Changes: - Mount the PVC at /config instead of /home (aligns with baseimage-gui convention) - Move user home directory to /config/userdata (on the PVC) - Add explicit --user-data-dir for Chrome pointing to PVC path - Clean up Chrome crash lock files and patch Preferences on startup to prevent session/cookie loss after unclean pod shutdown - Update all scripts (sshd, init-repo, cont-init) to use new paths - Remove unnecessary cont-init-home.sh Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude Co-Authored-By: Happy --- Dockerfile | 21 ++++++++++++++------- chart/templates/deployment.yaml | 2 +- chart/values.yaml | 2 +- scripts/cont-init-home.sh | 26 -------------------------- scripts/cont-init-sshd.sh | 2 +- scripts/cont-init-user.sh | 2 +- scripts/init-repo.sh | 8 ++++---- 7 files changed, 22 insertions(+), 41 deletions(-) delete mode 100644 scripts/cont-init-home.sh diff --git a/Dockerfile b/Dockerfile index 5a88405..9c68f0c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -35,15 +35,24 @@ RUN wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | gpg --dearm # Chrome wrapper: adds flags required for running inside a Docker container. # xdg-open (used by Claude Code on Linux) respects $BROWSER, so pointing it # here ensures the OAuth popup works without manual --no-sandbox invocations. -# Also explicitly sets user-data-dir to persist Chrome settings across restarts. +# Cleans up crash lock files and suppresses the crash-restore bubble so that +# sessions/cookies survive unclean pod shutdowns (SIGKILL). RUN printf '#!/bin/bash\n\ -# Ensure Chrome data directory exists with proper permissions\n\ -mkdir -p "$HOME/.config/google-chrome"\n\ +CHROME_DIR="/config/userdata/.config/google-chrome"\n\ +mkdir -p "$CHROME_DIR"\n\ +# Remove stale lock files left by unclean container shutdown\n\ +rm -f "$CHROME_DIR/SingletonLock" "$CHROME_DIR/SingletonSocket" "$CHROME_DIR/SingletonCookie"\n\ +# Mark the previous session as clean so Chrome does not clear cookies\n\ +PREFS="$CHROME_DIR/Default/Preferences"\n\ +if [ -f "$PREFS" ]; then\n\ + sed -i '\''s/"exit_type":"Crashed"/"exit_type":"Normal"/g; s/"exited_cleanly":false/"exited_cleanly":true/g'\'' "$PREFS"\n\ +fi\n\ exec /usr/bin/google-chrome-stable \\\n\ --no-sandbox \\\n\ --disable-dev-shm-usage \\\n\ --disable-gpu \\\n\ - --user-data-dir="$HOME/.config/google-chrome" \\\n\ + --disable-session-crashed-bubble \\\n\ + --user-data-dir="$CHROME_DIR" \\\n\ "$@"\n' > /usr/local/bin/google-chrome && \ chmod +x /usr/local/bin/google-chrome @@ -96,15 +105,13 @@ COPY --chmod=755 scripts/startapp.sh /startapp.sh COPY --chmod=755 scripts/init-repo.sh /usr/local/bin/init-repo # Fix app user shell after baseimage-gui creates it at runtime COPY --chmod=755 scripts/cont-init-user.sh /etc/cont-init.d/20-fix-user-shell.sh -# Initialize persistent home directory structure -COPY --chmod=755 scripts/cont-init-home.sh /etc/cont-init.d/21-init-home.sh COPY --chmod=755 scripts/cont-init-sshd.sh /etc/cont-init.d/25-start-sshd.sh # Set working directory WORKDIR /workspace # Configure container to run as user user -ENV HOME=/home/user \ +ENV HOME=/config/userdata \ USER=user \ BROWSER=/usr/local/bin/google-chrome diff --git a/chart/templates/deployment.yaml b/chart/templates/deployment.yaml index 20b8cb4..96adbb3 100644 --- a/chart/templates/deployment.yaml +++ b/chart/templates/deployment.yaml @@ -68,7 +68,7 @@ spec: {{- toYaml .Values.resources | nindent 12 }} volumeMounts: - name: userhome - mountPath: /home + mountPath: /config - name: workspace mountPath: /workspace - name: shm diff --git a/chart/values.yaml b/chart/values.yaml index d5aefa6..565f7e7 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -23,7 +23,7 @@ ssh: false # Happy Coder endpoints happyServerUrl: "https://happy.farh.net" happyWebappUrl: "https://happy-coder.farh.net" -happyHomeDir: "/home/user/.happy" +happyHomeDir: "/config/userdata/.happy" happyExperimental: "true" # VNC display diff --git a/scripts/cont-init-home.sh b/scripts/cont-init-home.sh deleted file mode 100644 index 1ca8cc8..0000000 --- a/scripts/cont-init-home.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh -# Initialize persistent home directory structure for the app user -# This ensures Chrome settings and SSH keys persist across pod restarts - -echo "=== Initializing persistent home directory ===" - -# Ensure the user home directory exists with proper ownership -if [ ! -d "/home/user" ]; then - echo "Creating /home/user directory..." - mkdir -p /home/user - chown app:app /home/user -fi - -# Ensure critical directories exist for persistent data -echo "Ensuring persistent directories exist..." -mkdir -p /home/user/.config -mkdir -p /home/user/.ssh -mkdir -p /home/user/.cache - -# Set proper ownership for all directories -chown -R app:app /home/user - -# Ensure SSH directory has proper permissions -chmod 700 /home/user/.ssh - -echo "Home directory initialization complete" \ No newline at end of file diff --git a/scripts/cont-init-sshd.sh b/scripts/cont-init-sshd.sh index 62d77d0..b61fd78 100644 --- a/scripts/cont-init-sshd.sh +++ b/scripts/cont-init-sshd.sh @@ -5,7 +5,7 @@ echo "=== SSH enabled: starting sshd ===" -HOME_DIR="/home/user" +HOME_DIR="/config/userdata" HOST_KEY_STORE="$HOME_DIR/.ssh/host_keys" # Persist host keys on the home PVC so clients don't see a "host key diff --git a/scripts/cont-init-user.sh b/scripts/cont-init-user.sh index 3f756d0..0963b1d 100644 --- a/scripts/cont-init-user.sh +++ b/scripts/cont-init-user.sh @@ -3,4 +3,4 @@ # baseimage-gui sets shell=/sbin/nologin and home=/dev/null, which # prevents VSCode from opening terminals. usermod -s /bin/bash app -usermod -d /home/user app +usermod -d /config/userdata app diff --git a/scripts/init-repo.sh b/scripts/init-repo.sh index 46b1313..7347e83 100644 --- a/scripts/init-repo.sh +++ b/scripts/init-repo.sh @@ -25,8 +25,8 @@ else # 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 + echo "https://oauth2:${GITHUB_TOKEN}@github.com" > /config/userdata/.git-credentials + chmod 600 /config/userdata/.git-credentials fi git pull || echo "Pull failed, continuing anyway..." @@ -42,8 +42,8 @@ else # 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 + echo "https://oauth2:${GITHUB_TOKEN}@github.com" > /config/userdata/.git-credentials + chmod 600 /config/userdata/.git-credentials else git clone "$GITHUB_REPO" "$WORKSPACE_DIR" fi