From f81bbd1e38912e9787a4e174336a060812d7fafc Mon Sep 17 00:00:00 2001 From: SAGE Date: Thu, 29 Jan 2026 17:00:28 +0800 Subject: [PATCH] Railway template --- Dockerfile | 17 +++------ README.md | 73 ++++++++++++++++++++++++--------------- railway-entrypoint.sh | 80 ++++++++++++++++++++----------------------- 3 files changed, 87 insertions(+), 83 deletions(-) diff --git a/Dockerfile b/Dockerfile index 3eecd4fbe..8fa0200aa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,11 +8,11 @@ FROM codercom/code-server:latest USER root -# Install FALLBACK Node.js and essential development tools -# Volume-installed versions take priority at runtime via PATH ordering +# Install gosu for proper user switching, Node.js, and essential tools RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \ && apt-get update \ && apt-get install -y --no-install-recommends \ + gosu \ nodejs \ git \ curl \ @@ -29,7 +29,6 @@ RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \ # ============================================================================ # PERSISTENCE CONFIGURATION -# Default paths - can be overridden via CODER_HOME environment variable # ============================================================================ ENV HOME=/home/coder @@ -41,14 +40,10 @@ ENV XDG_CONFIG_HOME=/home/coder/.config ENV XDG_CACHE_HOME=/home/coder/.cache ENV XDG_STATE_HOME=/home/coder/.local/state -# ============================================================================ -# PATH PRIORITY ORDER (volume paths FIRST, image paths LAST) -# This ensures user-installed tools on the volume take precedence -# ============================================================================ - +# PATH: Volume paths FIRST (user installs), image paths LAST (fallbacks) ENV PATH="/home/coder/.local/node/bin:/home/coder/.claude/local:/home/coder/.local/bin:/home/coder/node_modules/.bin:/usr/local/bin:/usr/bin:/usr/lib/code-server/lib/vscode/bin/remote-cli:${PATH}" -# Custom startup scripts directory (on volume) +# Custom startup scripts directory ENV ENTRYPOINTD=/home/coder/entrypoint.d # ============================================================================ @@ -85,8 +80,7 @@ RUN curl -fsSL https://claude.ai/install.sh | bash \ # ============================================================================ # RUNTIME -# Note: We run as root for compatibility with existing volumes -# The entrypoint creates symlinks to ensure persistence +# Entrypoint handles permission fix and user switching via gosu # ============================================================================ WORKDIR /home/coder/workspace @@ -94,4 +88,3 @@ EXPOSE 8080 ENTRYPOINT ["/usr/bin/railway-entrypoint.sh"] CMD ["--bind-addr", "0.0.0.0:8080", "/home/coder/workspace"] - diff --git a/README.md b/README.md index a54ec261d..4856fd611 100644 --- a/README.md +++ b/README.md @@ -4,62 +4,66 @@ [![Deploy on Railway](https://railway.com/button.svg)](https://railway.com/template/TEMPLATE_ID) -Cloud IDE with persistent extensions, settings, and tools. Zero configuration. +Cloud IDE with persistent extensions, settings, and tools. Runs as non-root user. --- ## Features - **Claude Code** & **Node.js 20** pre-installed +- **Non-root execution** - runs as `coder` user (UID 1000) - Extensions persist across redeployments -- Volume-installed tools take priority (update when YOU want) -- Custom startup scripts supported +- Volume permissions auto-fixed on startup --- ## Quick Start ```bash -# Claude Code ready to use +# Claude Code with auto-accept (for automation) +claude --dangerously-skip-permissions + +# Interactive mode claude -# Node.js ready to use +# Node.js ready node --version npm --version ``` --- -## How Updates Work - -| Component | Behavior | -|-----------|----------| -| **Volume tools** | YOU control updates. Install to `~/.local/node/` or `~/.claude/local/` | -| **Image tools** | Auto-update on redeploy (fallback if no volume version) | -| **Extensions** | Never reset (persisted on volume) | - -The startup logs show `[volume]` or `[image]` next to each tool. - ---- - ## Environment Variables | Variable | Required | Default | Description | |----------|----------|---------|-------------| | `PASSWORD` | Yes | - | Login password | | `CODER_HOME` | No | `/home/coder` | Volume mount path | +| `CODER_UID` | No | `1000` | User ID for coder | +| `CODER_GID` | No | `1000` | Group ID for coder | --- -## Custom Volume Path +## How It Works -If you change the volume mount location: +1. **Starts as root** - fixes volume permissions +2. **Switches to coder** - uses `gosu` for clean handoff +3. **Runs code-server** - as non-root user -``` -CODER_HOME=/your/volume/path -``` +This means: +- ✅ No root permission warnings in code-server +- ✅ Existing volumes with root-owned files work fine +- ✅ Claude `--dangerously-skip-permissions` works -Everything adapts automatically. +--- + +## Claude Code Authentication + +After running `claude` for the first time: + +1. Follow the authentication prompts +2. Your credentials are stored in `~/.claude/` +3. They persist across redeployments (on volume) --- @@ -76,13 +80,26 @@ Make executable: `chmod +x script.sh` --- +## Update Behavior + +| Component | Behavior | +|-----------|----------| +| **Volume tools** | You control - install to `~/.local/node/` or `~/.claude/local/` | +| **Image tools** | Auto-update on redeploy (fallback) | +| **Extensions** | Persist on volume | +| **Claude auth** | Persists on volume | + +Logs show `[volume]` or `[image]` next to each tool. + +--- + ## Troubleshooting -| Issue | Check | -|-------|-------| -| Wrong Node version | Look for `[volume]` vs `[image]` in logs | -| Extensions missing | Verify volume at `CODER_HOME` | -| Claude not found | Run `which claude` to verify PATH | +| Issue | Solution | +|-------|----------| +| Permission denied | Check `CODER_UID` matches your volume owner | +| Claude not found | Run `which claude` to check PATH | +| Extensions missing | Verify volume mounted at `CODER_HOME` | --- diff --git a/railway-entrypoint.sh b/railway-entrypoint.sh index 705c0f17b..88009d43b 100644 --- a/railway-entrypoint.sh +++ b/railway-entrypoint.sh @@ -3,7 +3,7 @@ set -e # ============================================================================ # VSCode Cloud IDE - Railway Entrypoint -# Robust entrypoint with volume-first tool priority +# Handles permission fix and user switching for non-root execution # ============================================================================ echo "╔══════════════════════════════════════════════════════════════════════╗" @@ -13,10 +13,11 @@ echo "" # ============================================================================ # CONFIGURABLE PATHS -# Users can override CODER_HOME to change the volume mount point # ============================================================================ CODER_HOME="${CODER_HOME:-/home/coder}" +CODER_UID="${CODER_UID:-1000}" +CODER_GID="${CODER_GID:-1000}" export HOME="$CODER_HOME" export XDG_DATA_HOME="$CODER_HOME/.local/share" @@ -27,14 +28,14 @@ export XDG_STATE_HOME="$CODER_HOME/.local/state" # PATH: Volume paths FIRST (user installs), image paths LAST (fallbacks) export PATH="$CODER_HOME/.local/node/bin:$CODER_HOME/.claude/local:$CODER_HOME/.local/bin:$CODER_HOME/node_modules/.bin:/usr/local/bin:/usr/bin:/usr/lib/code-server/lib/vscode/bin/remote-cli:$PATH" -echo "→ User: $(whoami) (UID: $(id -u))" -echo "→ HOME: $HOME" - # ============================================================================ -# DIRECTORY CREATION +# PERMISSION FIX (runs as root, then switches to coder) # ============================================================================ -create_dirs() { +if [ "$(id -u)" = "0" ]; then + echo "→ Running initial setup as root..." + + # Create directories if they don't exist mkdir -p "$XDG_DATA_HOME" \ "$XDG_CONFIG_HOME" \ "$XDG_CACHE_HOME" \ @@ -46,33 +47,26 @@ create_dirs() { "$HOME/workspace" \ "$XDG_DATA_HOME/code-server/extensions" \ "$XDG_CONFIG_HOME/code-server" 2>/dev/null || true -} -create_dirs - -# ============================================================================ -# ROOT USER SYMLINKS -# When running as root, symlink /root directories to the volume -# ============================================================================ - -if [ "$(id -u)" = "0" ]; then - echo "→ Running as root - creating persistence symlinks..." - - mkdir -p /root/.local 2>/dev/null || true - - for dir in ".local/share" ".local/node" ".config" ".cache" ".claude"; do - target="$CODER_HOME/$dir" - link="/root/$dir" - - if [ -d "$target" ] && [ ! -L "$link" ]; then - rm -rf "$link" 2>/dev/null || true - mkdir -p "$(dirname "$link")" 2>/dev/null || true - ln -sf "$target" "$link" 2>/dev/null || true - fi - done - - echo " ✓ Root directories symlinked to $CODER_HOME" + + # Fix ownership on the entire home directory + echo "→ Fixing permissions for coder user (UID: $CODER_UID)..." + chown -R "$CODER_UID:$CODER_GID" "$CODER_HOME" 2>/dev/null || true + + echo " ✓ Permissions fixed" + echo "" + + # Re-exec this script as coder user using gosu + echo "→ Switching to coder user..." + exec gosu "$CODER_UID:$CODER_GID" "$0" "$@" fi +# ============================================================================ +# RUNNING AS CODER USER FROM HERE +# ============================================================================ + +echo "→ User: $(whoami) (UID: $(id -u))" +echo "→ HOME: $HOME" + # ============================================================================ # FIRST RUN SETUP # ============================================================================ @@ -82,10 +76,8 @@ FIRST_RUN_MARKER="$XDG_DATA_HOME/.vscode-cloud-initialized" if [ ! -f "$FIRST_RUN_MARKER" ]; then echo "→ First run detected - initializing..." - mkdir -p "$XDG_CONFIG_HOME/code-server" 2>/dev/null || true - if [ ! -f "$HOME/workspace/README.md" ]; then - cat > "$HOME/workspace/README.md" << 'WELCOME' 2>/dev/null || true + cat > "$HOME/workspace/README.md" << 'WELCOME' # Welcome to VSCode Cloud IDE Your cloud development environment is ready! @@ -99,18 +91,21 @@ Your cloud development environment is ready! ## Quick Start -1. Open the Extensions panel (Ctrl+Shift+X) -2. Install your favorite extensions (they persist!) -3. Start coding in this workspace - -## Using Claude Code - ```bash +# Start Claude Code (with auto-accept for automation) +claude --dangerously-skip-permissions + +# Or interactive mode claude ``` You'll need to authenticate with your Anthropic API key on first use. +## Persist Claude Authentication + +Your Claude config at `~/.claude/` persists across redeployments. +After authenticating once, you won't need to re-authenticate. + Happy coding! 🚀 WELCOME fi @@ -121,7 +116,6 @@ fi # ============================================================================ # ENVIRONMENT VERIFICATION -# Shows which version is being used (volume vs image) # ============================================================================ echo "" @@ -178,7 +172,7 @@ fi echo "" echo "════════════════════════════════════════════════════════════════════════" -echo "Starting code-server..." +echo "Starting code-server as $(whoami)..." echo "════════════════════════════════════════════════════════════════════════" echo ""