Added clauder user and backward compatibility

This commit is contained in:
SAGE 2026-01-29 18:47:18 +08:00
parent 8077b23bd4
commit 82ca4283e2
3 changed files with 78 additions and 210 deletions

View File

@ -36,48 +36,47 @@ RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
# ============================================================================
# PERSISTENCE CONFIGURATION
# BACKWARD COMPATIBLE: Defaults to /home/coder for existing volumes
# ============================================================================
ENV HOME=/home/clauder
ENV USER=clauder
ENV HOME=/home/coder
ENV USER=coder
# XDG Base Directory Specification
ENV XDG_DATA_HOME=/home/clauder/.local/share
ENV XDG_CONFIG_HOME=/home/clauder/.config
ENV XDG_CACHE_HOME=/home/clauder/.cache
ENV XDG_STATE_HOME=/home/clauder/.local/state
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
# PATH: Volume paths FIRST (user installs), image paths LAST (fallbacks)
ENV PATH="/home/clauder/.local/bin:/home/clauder/.local/node/bin:/home/clauder/.claude/local:/home/clauder/node_modules/.bin:/usr/local/bin:/usr/bin:/usr/lib/code-server/lib/vscode/bin/remote-cli:${PATH}"
ENV PATH="/home/coder/.local/bin:/home/coder/.local/node/bin:/home/coder/.claude/local:/home/coder/node_modules/.bin:/usr/local/bin:/usr/bin:/usr/lib/code-server/lib/vscode/bin/remote-cli:${PATH}"
# Custom startup scripts directory
ENV ENTRYPOINTD=/home/clauder/entrypoint.d
ENV ENTRYPOINTD=/home/coder/entrypoint.d
# ============================================================================
# USER SETUP
# Create clauder user with same UID as coder for compatibility
# The base image already has coder user with UID 1000
# ============================================================================
RUN groupadd -g 1000 clauder 2>/dev/null || true \
&& useradd -m -s /bin/bash -u 1000 -g 1000 clauder 2>/dev/null || true \
&& usermod -l clauder coder 2>/dev/null || true \
&& groupmod -n clauder coder 2>/dev/null || true
# Ensure coder user exists with correct UID/GID
RUN id -u coder &>/dev/null || useradd -m -s /bin/bash -u 1000 -g 1000 coder 2>/dev/null || true
# ============================================================================
# DIRECTORY SETUP
# ============================================================================
RUN mkdir -p \
/home/clauder/.local/share \
/home/clauder/.config \
/home/clauder/.cache \
/home/clauder/.local/state \
/home/clauder/.local/bin \
/home/clauder/.local/node \
/home/clauder/.claude \
/home/clauder/entrypoint.d \
/home/clauder/workspace \
&& chown -R 1000:1000 /home/clauder
/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 our custom entrypoint (replaces base image's entrypoint)
COPY railway-entrypoint.sh /usr/bin/railway-entrypoint.sh
@ -101,8 +100,9 @@ RUN curl -fsSL https://claude.ai/install.sh | bash \
# Stay as root - entrypoint handles user switching based on RUN_AS_USER
# ============================================================================
WORKDIR /home/clauder/workspace
WORKDIR /home/coder/workspace
EXPOSE 8080
# Use our entrypoint which calls code-server directly
ENTRYPOINT ["/usr/bin/railway-entrypoint.sh"]

112
README.md
View File

@ -1,102 +1,75 @@
# Claude Code Server
# VSCode Cloud IDE
**Browser-based VS Code with Claude Code & AI Coding Assistants**
**Browser-based VSCode with Claude Code & Node.js**
[![Deploy on Railway](https://railway.com/button.svg)](https://railway.com/template/claude-code-server)
[![Deploy on Railway](https://railway.com/button.svg)](https://railway.com/template/TEMPLATE_ID)
Cloud IDE with persistent extensions, settings, and tools. Pre-installed Claude Code CLI.
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 `clauder` user (UID 1000)
- Extensions persist across redeployments
- Volume permissions auto-fixed on startup
---
## Quick Start
```bash
# Claude Code with auto-accept
# Claude Code with auto-accept (for automation)
claude --dangerously-skip-permissions
# Or use the alias
claude-auto
# Interactive mode
claude
# Node.js ready
node --version
npm --version
```
---
## ⚠️ Claude Code Authentication
## Environment Variables
When running `claude` for the first time:
1. The CLI will display an authentication URL
2. **Copy the URL to a different browser** (not this code-server browser)
3. Complete the login in that browser
4. Copy the code displayed after login
5. Paste the code back into the CLI
Your credentials persist in `~/.claude/` across redeployments.
---
## 📍 Railway Deployment
> **Region**: Set your Railway region to **US West** for the fastest performance.
### Required Variables
| Variable | Description |
|----------|-------------|
| `PASSWORD` | Login password for code-server |
### User Configuration
| Variable | Default | Description |
|----------|---------|-------------|
| `CLAUDER_HOME` | `/home/clauder` | Volume mount path |
| `CLAUDER_UID` | `1000` | User ID for clauder |
| `CLAUDER_GID` | `1000` | Group ID for clauder |
| `RUN_AS_USER` | `root` | Set to `clauder` for non-root execution |
### Pre-Install AI CLIs
Set to `1` to install on startup (default: `0`):
| Variable | CLI | Description |
|----------|-----|-------------|
| `INSTALL_OPENCODE` | OpenCode | Google's agentic AI IDE |
| `INSTALL_GEMINI` | Gemini CLI | Google Gemini assistant |
| `INSTALL_KILOCODE` | KiloCode | VS Code AI coding |
| `INSTALL_CONTINUE` | Continue | Open-source AI code assistant |
| `INSTALL_CODEX` | Codex | OpenAI Codex CLI |
> **Note**: Claude Code is **always installed** and cannot be disabled.
### Pre-Install Development Frameworks
| Variable | Framework | Description |
|----------|-----------|-------------|
| `INSTALL_BMAD` | BMAD Method | Spec-driven development workflow |
| `INSTALL_OPENSPEC` | OpenSpec | AI-powered spec generation |
| `INSTALL_SPECKIT` | Spec-Kit | GitHub's specification toolkit |
| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `PASSWORD` | Yes | - | Login password |
| `CLAUDER_HOME` | **Yes** | `/home/clauder` | Volume mount path (REQUIRED) |
| `CLAUDER_UID` | No | `1000` | User ID |
| `CLAUDER_GID` | No | `1000` | Group ID |
---
## How It Works
1. **Starts as root** fixes volume permissions
2. **Installs optional CLIs** based on environment variables
3. **Switches to clauder** uses `gosu` for clean handoff
4. **Runs code-server** as non-root user
1. **Starts as root** - fixes volume permissions
2. **Switches to clauder** - uses `gosu` for clean handoff
3. **Runs code-server** - as non-root user
This means:
- ✅ No root permission warnings
- ✅ Existing volumes work fine
- ✅ No root permission warnings in code-server
- ✅ Existing volumes with root-owned files work fine
- ✅ Claude `--dangerously-skip-permissions` works
---
## 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)
---
## Custom Startup Scripts
Add scripts to `$CLAUDER_HOME/entrypoint.d/`:
Add to `$CLAUDER_HOME/entrypoint.d/`:
```bash
#!/bin/bash
@ -111,7 +84,7 @@ Make executable: `chmod +x script.sh`
| Component | Behavior |
|-----------|----------|
| **Volume tools** | You control install to `~/.local/bin/` |
| **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 |
@ -127,7 +100,6 @@ Logs show `[volume]` or `[image]` next to each tool.
| Permission denied | Check `CLAUDER_UID` matches your volume owner |
| Claude not found | Run `which claude` to check PATH |
| Extensions missing | Verify volume mounted at `CLAUDER_HOME` |
| Auth URL won't open | Copy URL to a different browser |
---

View File

@ -2,13 +2,12 @@
set -e
# ============================================================================
# Claude Code Server - Railway Entrypoint
# Handles permission fix, optional user switching, and CLI installations
# https://github.com/sphinxcode/claude-code-server
# VSCode Cloud IDE - Railway Entrypoint
# Handles permission fix and optional user switching
# ============================================================================
echo "╔══════════════════════════════════════════════════════════════════════╗"
echo "║ Claude Code Server - AI Coding Assistants Ready ║"
echo "║ VSCode Cloud IDE - Claude Code & Node.js Ready ║"
echo "╚══════════════════════════════════════════════════════════════════════╝"
echo ""
@ -16,11 +15,11 @@ echo ""
# CONFIGURABLE PATHS AND USER
# ============================================================================
CLAUDER_HOME="${CLAUDER_HOME:-/home/clauder}"
CLAUDER_HOME="${CLAUDER_HOME:-/home/coder}"
CLAUDER_UID="${CLAUDER_UID:-1000}"
CLAUDER_GID="${CLAUDER_GID:-1000}"
# RUN_AS_USER: Set to "clauder" to run as non-root, or "root" (default) to stay as root
# RUN_AS_USER: Set to "coder" to run as non-root, or "root" (default) to stay as root
RUN_AS_USER="${RUN_AS_USER:-root}"
export HOME="$CLAUDER_HOME"
@ -57,94 +56,6 @@ if [ "$(id -u)" = "0" ]; then
"$XDG_DATA_HOME/code-server/extensions" \
"$XDG_CONFIG_HOME/code-server" 2>/dev/null || true
# ========================================================================
# OPTIONAL CLI INSTALLATIONS
# Install CLIs based on environment variables (only if not already present)
# ========================================================================
echo ""
echo "→ Checking optional CLI installations..."
# OpenCode
if [ "${INSTALL_OPENCODE:-0}" = "1" ]; then
if ! command -v opencode &>/dev/null; then
echo " → Installing OpenCode..."
curl -fsSL https://raw.githubusercontent.com/opencode-ai/opencode/refs/heads/main/install | bash || echo " ⚠ OpenCode install failed"
else
echo " ✓ OpenCode already installed"
fi
fi
# Gemini CLI
if [ "${INSTALL_GEMINI:-0}" = "1" ]; then
if ! command -v gemini &>/dev/null; then
echo " → Installing Gemini CLI..."
npm install -g @google/gemini-cli || echo " ⚠ Gemini CLI install failed"
else
echo " ✓ Gemini CLI already installed"
fi
fi
# KiloCode CLI
if [ "${INSTALL_KILOCODE:-0}" = "1" ]; then
if ! command -v kilocode &>/dev/null; then
echo " → Installing KiloCode CLI..."
npm install -g @kilocode/cli || echo " ⚠ KiloCode CLI install failed"
else
echo " ✓ KiloCode CLI already installed"
fi
fi
# Continue CLI
if [ "${INSTALL_CONTINUE:-0}" = "1" ]; then
if ! command -v continue &>/dev/null; then
echo " → Installing Continue CLI..."
npm install -g @continuedev/cli || echo " ⚠ Continue CLI install failed"
else
echo " ✓ Continue CLI already installed"
fi
fi
# Codex CLI
if [ "${INSTALL_CODEX:-0}" = "1" ]; then
if ! command -v codex &>/dev/null; then
echo " → Installing Codex CLI..."
npm install -g @openai/codex || echo " ⚠ Codex CLI install failed"
else
echo " ✓ Codex CLI already installed"
fi
fi
# ========================================================================
# OPTIONAL DEVELOPMENT FRAMEWORK INSTALLATIONS
# ========================================================================
# BMAD Method
if [ "${INSTALL_BMAD:-0}" = "1" ]; then
echo " → Installing BMAD Method..."
npx bmad-method install || echo " ⚠ BMAD install failed"
fi
# OpenSpec
if [ "${INSTALL_OPENSPEC:-0}" = "1" ]; then
if ! command -v openspec &>/dev/null; then
echo " → Installing OpenSpec..."
npm install -g @fission-ai/openspec@latest || echo " ⚠ OpenSpec install failed"
else
echo " ✓ OpenSpec already installed"
fi
fi
# Spec-Kit
if [ "${INSTALL_SPECKIT:-0}" = "1" ]; then
if ! command -v specify &>/dev/null; then
echo " → Installing Spec-Kit..."
uv tool install specify-cli --from git+https://github.com/github/spec-kit.git || echo " ⚠ Spec-Kit install failed"
else
echo " ✓ Spec-Kit already installed"
fi
fi
# ========================================================================
# SHELL PROFILE SETUP
# ========================================================================
@ -156,7 +67,7 @@ if [ "$(id -u)" = "0" ]; then
cat >> "$PROFILE_FILE" << 'PROFILE'
# ============================================================================
# Claude Code Server - PATH Configuration
# VSCode Cloud IDE - PATH Configuration
# ============================================================================
export PATH="$HOME/.local/bin:$HOME/.local/node/bin:$HOME/.claude/local:$PATH"
@ -222,14 +133,14 @@ echo "→ Running as: $(whoami) (UID: $(id -u))"
# FIRST RUN SETUP
# ============================================================================
FIRST_RUN_MARKER="$XDG_DATA_HOME/.claude-code-server-initialized"
FIRST_RUN_MARKER="$XDG_DATA_HOME/.vscode-cloud-initialized"
if [ ! -f "$FIRST_RUN_MARKER" ]; then
echo "→ First run detected - initializing..."
if [ ! -f "$HOME/workspace/README.md" ]; then
cat > "$HOME/workspace/README.md" << 'WELCOME'
# Welcome to Claude Code Server
# Welcome to VSCode Cloud IDE
Your cloud development environment is ready!
@ -253,21 +164,13 @@ claude-auto
claude
```
## Claude Code Authentication
⚠️ **Important**: When authenticating Claude Code:
1. Copy the authentication URL
2. Open it in a **different browser** (not this code-server browser)
3. Complete the login there
4. Copy the code and paste it back into the CLI
Your credentials persist across redeployments.
You'll need to authenticate with your Anthropic API key on first use.
## Configuration
Set these environment variables in Railway:
- `RUN_AS_USER=clauder` - Run as non-root user (recommended)
- `RUN_AS_USER=coder` - Run as non-root user (recommended for Claude)
- `RUN_AS_USER=root` - Stay as root (default)
Happy coding! 🚀
@ -298,7 +201,7 @@ 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 (always installed)
# Claude Code - show source
if [ -x "$CLAUDER_HOME/.local/bin/claude" ]; then
echo " → claude: $(claude --version 2>/dev/null || echo 'installed') [volume ~/.local/bin]"
elif [ -x "$CLAUDER_HOME/.claude/local/claude" ]; then
@ -309,13 +212,6 @@ else
echo " → claude: not installed"
fi
# Show optional CLIs if installed
command -v opencode &>/dev/null && echo " → opencode: installed"
command -v gemini &>/dev/null && echo " → gemini: installed"
command -v kilocode &>/dev/null && echo " → kilocode: installed"
command -v continue &>/dev/null && echo " → continue: installed"
command -v codex &>/dev/null && echo " → codex: installed"
# 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)
@ -349,4 +245,4 @@ echo "Starting code-server as $(whoami)..."
echo "════════════════════════════════════════════════════════════════════════"
echo ""
exec dumb-init /usr/bin/code-server --bind-addr 0.0.0.0:8080 "$HOME/workspace"
exec dumb-init /usr/bin/code-server --bind-addr 0.0.0.0:8080 /home/coder/workspace