Easy install Claude Code

This commit is contained in:
SAGE 2026-01-29 10:02:56 +08:00
parent d868d96535
commit da6737c5ba
4 changed files with 331 additions and 56 deletions

View File

@ -1,46 +1,97 @@
# Custom code-server image for Railway with persistent Node.js and extensions
# ============================================================================
# VSCode Cloud IDE - Claude Code & Node.js Ready
# Browser-based VSCode with persistent extensions and Node.js
# https://github.com/sphinxcode/code-server
# ============================================================================
FROM codercom/code-server:latest
USER root
# Install Node.js 20 LTS
# Install FALLBACK Node.js and essential development tools
# Volume-installed versions take priority at runtime via PATH ordering
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
&& apt-get install -y nodejs \
&& apt-get update \
&& apt-get install -y --no-install-recommends \
nodejs \
git \
curl \
wget \
unzip \
jq \
htop \
vim \
nano \
ripgrep \
&& npm install -g npm@latest \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Set HOME to /home/coder (the volume mount point on Railway)
# This ensures all user data goes to the persistent volume
# ============================================================================
# PERSISTENCE CONFIGURATION
# Default paths - can be overridden via CODER_HOME environment variable
# ============================================================================
ENV HOME=/home/coder
ENV USER=coder
# Set XDG directories to use the persistent volume
# XDG Base Directory Specification
ENV XDG_DATA_HOME=/home/coder/.local/share
ENV XDG_CONFIG_HOME=/home/coder/.config
ENV XDG_CACHE_HOME=/home/coder/.cache
ENV XDG_STATE_HOME=/home/coder/.local/state
# Ensure Node.js is in PATH and add code-server CLI
ENV PATH="/usr/bin:/usr/local/bin:/home/coder/.local/bin:/home/coder/.local/node/bin:/usr/lib/code-server/lib/vscode/bin/remote-cli:${PATH}"
# ============================================================================
# PATH PRIORITY ORDER (volume paths FIRST, image paths LAST)
# This ensures user-installed tools on the volume take precedence
# ============================================================================
# Set entrypoint.d to the persistent volume for custom startup scripts
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)
ENV ENTRYPOINTD=/home/coder/entrypoint.d
# Create necessary directories
RUN mkdir -p /home/coder/.local/share \
# ============================================================================
# DIRECTORY SETUP
# ============================================================================
RUN mkdir -p \
/home/coder/.local/share \
/home/coder/.config \
/home/coder/.cache \
/home/coder/.local/state \
/home/coder/.local/bin \
/home/coder/.local/node \
/home/coder/.claude \
/home/coder/entrypoint.d \
/home/coder/workspace \
&& chown -R 1000:1000 /home/coder
# Copy custom entrypoint
COPY railway-entrypoint.sh /usr/bin/railway-entrypoint.sh
RUN chmod +x /usr/bin/railway-entrypoint.sh
# ============================================================================
# FALLBACK CLAUDE CODE CLI INSTALLATION
# Installed to /usr/local/bin as fallback - volume version takes priority
# ============================================================================
RUN curl -fsSL https://claude.ai/install.sh | bash \
&& if [ -f /root/.claude/local/claude ]; then \
mv /root/.claude/local/claude /usr/local/bin/claude; \
chmod +x /usr/local/bin/claude; \
fi \
&& rm -rf /root/.claude
# ============================================================================
# RUNTIME
# Note: We run as root for compatibility with existing volumes
# The entrypoint creates symlinks to ensure persistence
# ============================================================================
WORKDIR /home/coder/workspace
EXPOSE 8080
# Use our custom entrypoint that handles Railway's root user
ENTRYPOINT ["/usr/bin/railway-entrypoint.sh"]
CMD ["--bind-addr", "0.0.0.0:8080", "."]
CMD ["--bind-addr", "0.0.0.0:8080", "/home/coder/workspace"]

94
README.md Normal file
View File

@ -0,0 +1,94 @@
# VSCode Cloud IDE
**Browser-based VSCode with Claude Code & Node.js**
[![Deploy on Railway](https://railway.com/button.svg)](https://railway.com/template/TEMPLATE_ID)
Cloud IDE with persistent extensions, settings, and tools. Zero configuration.
---
## Features
- **Claude Code** & **Node.js 20** pre-installed
- Extensions persist across redeployments
- Volume-installed tools take priority (update when YOU want)
- Custom startup scripts supported
---
## Quick Start
```bash
# Claude Code ready to use
claude
# Node.js ready to use
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 |
---
## Custom Volume Path
If you change the volume mount location:
```
CODER_HOME=/your/volume/path
```
Everything adapts automatically.
---
## Custom Startup Scripts
Add to `$CODER_HOME/entrypoint.d/`:
```bash
#!/bin/bash
git config --global user.name "Your Name"
```
Make executable: `chmod +x script.sh`
---
## 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 |
---
## Credits
- [code-server](https://github.com/coder/code-server) by Coder
- [Claude Code](https://github.com/anthropics/claude-code) by Anthropic
**License:** MIT

View File

@ -1,68 +1,185 @@
#!/bin/bash
set -e
# Railway runs containers as root, but we want all data in /home/coder (the volume)
# This script ensures proper environment setup for persistence
# ============================================================================
# VSCode Cloud IDE - Railway Entrypoint
# Robust entrypoint with volume-first tool priority
# ============================================================================
echo "=== Railway Code-Server Startup ==="
echo "User: $(whoami) (UID: $(id -u))"
echo "HOME: $HOME"
echo "XDG_DATA_HOME: $XDG_DATA_HOME"
echo "XDG_CONFIG_HOME: $XDG_CONFIG_HOME"
echo "╔══════════════════════════════════════════════════════════════════════╗"
echo "║ VSCode Cloud IDE - Claude Code & Node.js Ready ║"
echo "╚══════════════════════════════════════════════════════════════════════╝"
echo ""
# Ensure HOME is set correctly (Railway might override it)
export HOME=/home/coder
# ============================================================================
# CONFIGURABLE PATHS
# Users can override CODER_HOME to change the volume mount point
# ============================================================================
# Ensure XDG directories exist and are writable
mkdir -p "$XDG_DATA_HOME" "$XDG_CONFIG_HOME" "$XDG_CACHE_HOME" "$XDG_STATE_HOME"
mkdir -p "$HOME/.local/bin" "$HOME/entrypoint.d"
CODER_HOME="${CODER_HOME:-/home/coder}"
# Ensure the code-server data directory exists
mkdir -p "$XDG_DATA_HOME/code-server"
export HOME="$CODER_HOME"
export XDG_DATA_HOME="$CODER_HOME/.local/share"
export XDG_CONFIG_HOME="$CODER_HOME/.config"
export XDG_CACHE_HOME="$CODER_HOME/.cache"
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
# ============================================================================
create_dirs() {
mkdir -p "$XDG_DATA_HOME" \
"$XDG_CONFIG_HOME" \
"$XDG_CACHE_HOME" \
"$XDG_STATE_HOME" \
"$HOME/.local/bin" \
"$HOME/.local/node" \
"$HOME/.claude" \
"$HOME/entrypoint.d" \
"$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
# ============================================================================
# Set up VS Code Server data directory symlink if running as root
# This ensures extensions installed by code-server persist
if [ "$(id -u)" = "0" ]; then
# Create root's directories pointing to volume
mkdir -p /root/.local
echo "→ Running as root - creating persistence symlinks..."
# Symlink root's local share to the volume (for VS Code extensions)
if [ ! -L /root/.local/share ]; then
rm -rf /root/.local/share 2>/dev/null || true
ln -sf "$XDG_DATA_HOME" /root/.local/share
fi
mkdir -p /root/.local 2>/dev/null || true
# Symlink root's config to the volume
if [ ! -L /root/.config ]; then
rm -rf /root/.config 2>/dev/null || true
ln -sf "$XDG_CONFIG_HOME" /root/.config
fi
for dir in ".local/share" ".local/node" ".config" ".cache" ".claude"; do
target="$CODER_HOME/$dir"
link="/root/$dir"
# Symlink root's cache to the volume
if [ ! -L /root/.cache ]; then
rm -rf /root/.cache 2>/dev/null || true
ln -sf "$XDG_CACHE_HOME" /root/.cache
fi
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 "Created symlinks from /root to $HOME for persistence"
echo " ✓ Root directories symlinked to $CODER_HOME"
fi
# Ensure Node.js is accessible
echo "Node.js version: $(node --version 2>/dev/null || echo 'Not found in PATH')"
echo "npm version: $(npm --version 2>/dev/null || echo 'Not found in PATH')"
echo "PATH: $PATH"
# ============================================================================
# FIRST RUN SETUP
# ============================================================================
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
# Welcome to VSCode Cloud IDE
Your cloud development environment is ready!
## Features
- **Claude Code CLI** - Pre-installed and ready to use
- **Node.js 20 LTS** - Pre-installed and ready to use
- **Persistent Extensions** - Install once, keep forever
- **Full Terminal** - npm, git, and more
## 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
claude
```
You'll need to authenticate with your Anthropic API key on first use.
Happy coding! 🚀
WELCOME
fi
touch "$FIRST_RUN_MARKER" 2>/dev/null || true
echo " ✓ Initialization complete"
fi
# ============================================================================
# ENVIRONMENT VERIFICATION
# Shows which version is being used (volume vs image)
# ============================================================================
echo ""
echo "Environment:"
# Node.js - show source
if [ -x "$CODER_HOME/.local/node/bin/node" ]; then
echo " → Node.js: $(node --version 2>/dev/null) [volume]"
else
echo " → Node.js: $(node --version 2>/dev/null || echo 'not found') [image]"
fi
# npm
echo " → npm: $(npm --version 2>/dev/null || echo 'not found')"
# git
echo " → git: $(git --version 2>/dev/null | cut -d' ' -f3 || echo 'not found')"
# Claude Code - show source
if [ -x "$CODER_HOME/.claude/local/claude" ]; then
echo " → claude: $(claude --version 2>/dev/null || echo 'installed') [volume]"
elif command -v claude &>/dev/null; then
echo " → claude: $(claude --version 2>/dev/null || echo 'installed') [image]"
else
echo " → claude: not installed"
fi
# Extensions count
if [ -d "$XDG_DATA_HOME/code-server/extensions" ]; then
EXT_COUNT=$(find "$XDG_DATA_HOME/code-server/extensions" -maxdepth 1 -type d 2>/dev/null | wc -l)
EXT_COUNT=$((EXT_COUNT - 1))
if [ $EXT_COUNT -gt 0 ]; then
echo " → Extensions: $EXT_COUNT installed"
fi
fi
# ============================================================================
# CUSTOM STARTUP SCRIPTS
# ============================================================================
# Run any custom startup scripts from entrypoint.d
if [ -d "$HOME/entrypoint.d" ]; then
for script in "$HOME/entrypoint.d"/*.sh; do
if [ -f "$script" ] && [ -x "$script" ]; then
echo "Running startup script: $script"
"$script"
echo ""
echo "Running: $(basename "$script")"
"$script" || echo " ⚠ Script exited with code $?"
fi
done
fi
echo "=== Starting code-server ==="
# ============================================================================
# START CODE-SERVER
# ============================================================================
echo ""
echo "════════════════════════════════════════════════════════════════════════"
echo "Starting code-server..."
echo "════════════════════════════════════════════════════════════════════════"
echo ""
# Start code-server with dumb-init for proper signal handling
exec dumb-init /usr/bin/code-server "$@"

13
railway.toml Normal file
View File

@ -0,0 +1,13 @@
# ============================================================================
# VSCode Cloud IDE - Railway Configuration
# ============================================================================
[build]
builder = "DOCKERFILE"
dockerfilePath = "Dockerfile"
[deploy]
healthcheckPath = "/healthz"
healthcheckTimeout = 300
restartPolicyType = "ON_FAILURE"
restartPolicyMaxRetries = 10