mirror of
https://github.com/coder/code-server.git
synced 2026-02-19 18:01:15 +08:00
Merge f148984d6d34947ccd44ab000c27ebeea992ca56 into 9184b645cc7aa41b750e2f2ef956f2896512dd84
This commit is contained in:
commit
4f2bdbb2ee
@ -1,3 +1,7 @@
|
||||
# Ignore everything by default
|
||||
**
|
||||
!release-packages
|
||||
!ci
|
||||
|
||||
# Include only what's needed for the Railway build
|
||||
!Dockerfile
|
||||
!railway-entrypoint.sh
|
||||
!railway.json
|
||||
|
||||
46
.github/workflows/deploy-image.yml
vendored
Normal file
46
.github/workflows/deploy-image.yml
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
# Builds and pushes the Docker image to GitHub Container Registry
|
||||
name: Publish Docker Image
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata (tags, labels) for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
type=raw,value=latest
|
||||
type=sha,prefix=
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
116
Dockerfile
Normal file
116
Dockerfile
Normal file
@ -0,0 +1,116 @@
|
||||
# ============================================================================
|
||||
# Claude Code Server - Browser-based VS Code with AI Coding Assistants
|
||||
# https://github.com/sphinxcode/claude-code-server
|
||||
# ============================================================================
|
||||
|
||||
FROM codercom/code-server:4.108.0
|
||||
|
||||
USER root
|
||||
|
||||
# ============================================================================
|
||||
# SYSTEM DEPENDENCIES
|
||||
# Install gosu, Node.js 22, Python/uv, and essential tools
|
||||
# Cache bust: 2026-01-30-v6
|
||||
# ============================================================================
|
||||
|
||||
RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
gosu \
|
||||
nodejs \
|
||||
python3 \
|
||||
python3-pip \
|
||||
python3-venv \
|
||||
pipx \
|
||||
git \
|
||||
curl \
|
||||
wget \
|
||||
unzip \
|
||||
jq \
|
||||
htop \
|
||||
vim \
|
||||
nano \
|
||||
ripgrep \
|
||||
&& npm install -g npm@latest \
|
||||
&& pip3 install --break-system-packages uv \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# ============================================================================
|
||||
# PERSISTENCE CONFIGURATION
|
||||
# Default to /home/clauder for new deployments
|
||||
# ============================================================================
|
||||
|
||||
ENV HOME=/home/clauder
|
||||
ENV USER=clauder
|
||||
|
||||
# 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
|
||||
|
||||
# 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}"
|
||||
|
||||
# Custom startup scripts directory
|
||||
ENV ENTRYPOINTD=/home/clauder/entrypoint.d
|
||||
|
||||
# ============================================================================
|
||||
# USER SETUP
|
||||
# Create clauder user (UID 1000) with passwordless sudo
|
||||
# - Stays non-root for Claude YOLO mode compatibility
|
||||
# - Can use sudo for package installs (apt, npm -g, pip, etc.)
|
||||
# ============================================================================
|
||||
|
||||
# Install sudo if not present, then configure user
|
||||
RUN apt-get update && apt-get install -y sudo \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& (groupadd -g 1000 clauder 2>/dev/null || true) \
|
||||
&& (useradd -m -s /bin/bash -u 1000 -g 1000 clauder 2>/dev/null || usermod -l clauder -d /home/clauder -m coder 2>/dev/null || true) \
|
||||
&& (groupmod -n clauder coder 2>/dev/null || true) \
|
||||
&& mkdir -p /etc/sudoers.d \
|
||||
&& echo "clauder ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/clauder \
|
||||
&& chmod 0440 /etc/sudoers.d/clauder \
|
||||
&& chown root:root /etc/sudoers.d/clauder
|
||||
|
||||
# ============================================================================
|
||||
# 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
|
||||
|
||||
# Copy our custom entrypoint (replaces base image's entrypoint)
|
||||
COPY railway-entrypoint.sh /usr/bin/railway-entrypoint.sh
|
||||
RUN chmod +x /usr/bin/railway-entrypoint.sh
|
||||
|
||||
# ============================================================================
|
||||
# CLAUDE CODE CLI INSTALLATION
|
||||
# Install globally via npm - this is the official package
|
||||
# ============================================================================
|
||||
|
||||
RUN npm install -g @anthropic-ai/claude-code \
|
||||
&& echo "Claude CLI installed: $(claude --version 2>/dev/null || echo 'checking...')"
|
||||
|
||||
# ============================================================================
|
||||
# RUNTIME
|
||||
# Stay as root - entrypoint handles user switching based on RUN_AS_USER
|
||||
# ============================================================================
|
||||
|
||||
WORKDIR /home/clauder/workspace
|
||||
EXPOSE 8080
|
||||
|
||||
# Use our entrypoint which calls code-server directly
|
||||
ENTRYPOINT ["/usr/bin/railway-entrypoint.sh"]
|
||||
|
||||
|
||||
222
PROJECT_BRIEF.md
Normal file
222
PROJECT_BRIEF.md
Normal file
@ -0,0 +1,222 @@
|
||||
# Project Brief: Code-Server Railway Template
|
||||
|
||||
**Project:** VSCode Cloud IDE with Claude Code Integration
|
||||
**Repository:** `sphinxcode/code-server`
|
||||
**Railway Service:** `code-ajna` (claude.sphinx.codes)
|
||||
**Status:** In Progress
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
Create a production-ready, marketable Railway template that provides browser-based VS Code (code-server) with pre-installed Claude Code CLI, persistent extensions, and configurable user permissions.
|
||||
|
||||
---
|
||||
|
||||
## Original Problems
|
||||
|
||||
### 1. Root User Permission Issues
|
||||
- **Symptom:** code-server displayed security warnings about running as root
|
||||
- **Cause:** `RAILWAY_RUN_UID=0` was set, forcing container to run as root
|
||||
- **Impact:** Couldn't bypass certain settings, security warnings in UI
|
||||
|
||||
### 2. Non-Persistent Tools
|
||||
- **Symptom:** npm, npx, extensions disappeared after redeployment
|
||||
- **Cause:** Container running as root with `HOME=/root` (ephemeral), while volume mounted at `/home/coder`
|
||||
- **Impact:** Users lost installed tools and configurations on each deploy
|
||||
|
||||
### 3. Claude Code Not Pre-installed
|
||||
- **Request:** Template users should have Claude Code CLI available out-of-the-box
|
||||
- **Requirement:** Support for `claude --dangerously-skip-permissions` flag
|
||||
|
||||
---
|
||||
|
||||
## Solution Architecture
|
||||
|
||||
### Infrastructure
|
||||
| Component | Value |
|
||||
|-----------|-------|
|
||||
| Base Image | `codercom/code-server:latest` |
|
||||
| Volume Mount | `/home/coder` (Railway volume) |
|
||||
| Service URL | `claude.sphinx.codes` |
|
||||
| Project ID | `59ae99d7-dc99-4642-ae06-642cd8d8c83a` |
|
||||
| Service ID | `34522d52-ba69-4fcf-83b7-210a765a0a76` |
|
||||
| Environment ID | `a921a831-e480-451b-b9c7-04ce2f647c68` |
|
||||
|
||||
### Key Files Modified
|
||||
|
||||
#### [Dockerfile](file:///E:/AI-Terminal/sphinxcode/code-server/Dockerfile)
|
||||
- Installs `gosu` for proper user switching
|
||||
- Installs Node.js 20 LTS as fallback
|
||||
- Installs Claude Code CLI to `/usr/local/bin/claude`
|
||||
- Installs essential tools: ripgrep, jq, htop, vim, nano
|
||||
- Sets up XDG directories for persistence
|
||||
- PATH prioritizes volume paths over image paths
|
||||
|
||||
#### [railway-entrypoint.sh](file:///E:/AI-Terminal/sphinxcode/code-server/railway-entrypoint.sh)
|
||||
- Configurable user via `RUN_AS_USER` variable
|
||||
- Shell profile setup (`.bashrc`, `.profile`) with PATH
|
||||
- Permission fixing via `chown` when switching users
|
||||
- User switching via `gosu` when `RUN_AS_USER=coder`
|
||||
- Root symlinks for persistence when staying as root
|
||||
- First-run initialization with welcome README
|
||||
- Environment verification logging
|
||||
|
||||
#### [README.md](file:///E:/AI-Terminal/sphinxcode/code-server/README.md)
|
||||
- Documentation for all configuration variables
|
||||
- Quick start guide for Claude Code
|
||||
- Update behavior explanation
|
||||
- Troubleshooting guide
|
||||
|
||||
---
|
||||
|
||||
## Configuration Variables
|
||||
|
||||
| Variable | Required | Default | Description |
|
||||
|----------|----------|---------|-------------|
|
||||
| `PASSWORD` | Yes | - | code-server login password |
|
||||
| `RUN_AS_USER` | No | `root` | Set to `coder` for non-root execution |
|
||||
| `CODER_HOME` | No | `/home/coder` | Volume mount path |
|
||||
| `CODER_UID` | No | `1000` | User ID when switching to coder |
|
||||
| `CODER_GID` | No | `1000` | Group ID when switching to coder |
|
||||
| `GIT_REPO` | No | - | Repository to auto-clone on startup |
|
||||
|
||||
---
|
||||
|
||||
## Persistence Strategy
|
||||
|
||||
### Volume-First PATH Priority
|
||||
```
|
||||
$HOME/.local/bin ← User-installed tools (Claude, etc.)
|
||||
$HOME/.local/node/bin ← User-installed Node.js
|
||||
$HOME/.claude/local ← Claude Code from volume
|
||||
/usr/local/bin ← Image fallback (Claude)
|
||||
/usr/bin ← Image fallback (Node.js)
|
||||
```
|
||||
|
||||
### What Persists (on volume)
|
||||
- Extensions: `~/.local/share/code-server/extensions/`
|
||||
- Claude Code: `~/.local/bin/claude` or `~/.claude/`
|
||||
- Claude auth: `~/.claude/` (API keys, settings)
|
||||
- Node.js: `~/.local/node/` (if user installs)
|
||||
- Shell config: `~/.bashrc`, `~/.profile`
|
||||
- Workspace: `~/workspace/`
|
||||
|
||||
### What Auto-Updates (from image)
|
||||
- Node.js fallback in `/usr/bin/node`
|
||||
- Claude Code fallback in `/usr/local/bin/claude`
|
||||
- System packages (git, curl, etc.)
|
||||
|
||||
---
|
||||
|
||||
## User Modes
|
||||
|
||||
### Root Mode (Default)
|
||||
```
|
||||
RUN_AS_USER=root (or not set)
|
||||
```
|
||||
- Stays as root user
|
||||
- Creates symlinks from `/root/` → `/home/coder/` for persistence
|
||||
- Compatible with existing volumes owned by root
|
||||
|
||||
### Coder Mode (Recommended for Claude)
|
||||
```
|
||||
RUN_AS_USER=coder
|
||||
```
|
||||
- Switches to coder user (UID 1000) via gosu
|
||||
- Fixes volume permissions before switching
|
||||
- No root warnings in code-server UI
|
||||
- Required for `claude --dangerously-skip-permissions`
|
||||
|
||||
---
|
||||
|
||||
## Issues Encountered & Resolved
|
||||
|
||||
### 1. Railway Start Command Override
|
||||
- **Problem:** Railway had a custom start command that bypassed our ENTRYPOINT
|
||||
- **Solution:** Cleared the start command via `mcp_railway_service_update`
|
||||
|
||||
### 2. Docker Layer Caching
|
||||
- **Problem:** Railway used cached layers, ignoring our changes
|
||||
- **Solution:** Added cache-bust comments to force rebuild
|
||||
|
||||
### 3. Claude Installs to ~/.local/bin
|
||||
- **Problem:** Assumed Claude installed to `~/.claude/local/`
|
||||
- **Solution:** Updated PATH to include `$HOME/.local/bin` first
|
||||
|
||||
### 4. Shell Profile Not Configured
|
||||
- **Problem:** New terminals didn't have PATH set
|
||||
- **Solution:** Entrypoint now writes to `.bashrc` and `.profile`
|
||||
|
||||
---
|
||||
|
||||
## Current Status
|
||||
|
||||
### Completed ✅
|
||||
- Dockerfile with gosu, Node.js, Claude Code
|
||||
- Entrypoint with RUN_AS_USER variable
|
||||
- Shell profile auto-configuration
|
||||
- PATH priority for volume-installed tools
|
||||
- README documentation
|
||||
- Removed conflicting `railway.json`
|
||||
- Cleared Railway start command override
|
||||
- Set `RUN_AS_USER=coder` on Railway
|
||||
|
||||
### Pending Verification 🔄
|
||||
- Confirm entrypoint output appears in Railway logs
|
||||
- Verify user switches to `coder` (not `root@xxx`)
|
||||
- Test `claude --dangerously-skip-permissions` works
|
||||
- Confirm Claude authentication persists
|
||||
|
||||
---
|
||||
|
||||
## Expected Startup Logs
|
||||
|
||||
```
|
||||
╔══════════════════════════════════════════════════════════════════════════╗
|
||||
║ VSCode Cloud IDE - Claude Code & Node.js Ready ║
|
||||
╚══════════════════════════════════════════════════════════════════════════╝
|
||||
|
||||
→ Initial user: root (UID: 0)
|
||||
→ RUN_AS_USER: coder
|
||||
→ HOME: /home/coder
|
||||
|
||||
→ Running setup as root...
|
||||
→ Setting up shell profile...
|
||||
✓ Shell profile configured
|
||||
→ Fixing permissions for coder user (UID: 1000)...
|
||||
✓ Permissions fixed
|
||||
→ Switching to coder user via gosu...
|
||||
|
||||
→ Running as: coder (UID: 1000)
|
||||
|
||||
Environment:
|
||||
→ Node.js: v20.x.x [volume/image]
|
||||
→ npm: x.x.x
|
||||
→ git: x.x.x
|
||||
→ claude: x.x.x [volume/image]
|
||||
|
||||
════════════════════════════════════════════════════════════════════════
|
||||
Starting code-server as coder...
|
||||
════════════════════════════════════════════════════════════════════════
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Files Summary
|
||||
|
||||
| File | Location | Purpose |
|
||||
|------|----------|---------|
|
||||
| `Dockerfile` | sphinxcode/code-server | Image build configuration |
|
||||
| `railway-entrypoint.sh` | sphinxcode/code-server | Container startup script |
|
||||
| `README.md` | sphinxcode/code-server | User documentation |
|
||||
| `railway.toml` | sphinxcode/code-server | Railway deployment config |
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. **Verify Deployment** - Check if entrypoint runs and user switches properly
|
||||
2. **Test Claude** - Authenticate and run `claude --dangerously-skip-permissions`
|
||||
3. **Create Railway Template** - Make template public for others to deploy
|
||||
4. **Update Template Docs** - Include volume attachment instructions
|
||||
82
README.md
Normal file
82
README.md
Normal file
@ -0,0 +1,82 @@
|
||||
# Claude Code Server
|
||||
|
||||

|
||||
|
||||
**Browser-based VS Code with Claude Code CLI pre-installed**
|
||||
|
||||
[](https://railway.com/template/claude-code-server)
|
||||
|
||||

|
||||
|
||||
Deploy a full VS Code development environment in the cloud with Claude Code CLI ready to go. Access it from any browser, on any device. Code with AI assistance anywhere.
|
||||
|
||||
---
|
||||
|
||||
## Features
|
||||
|
||||
- **Claude Code CLI Pre-installed** – Start AI-assisted coding immediately with `claude` or `claude-auto` (YOLO mode)
|
||||
- **Browser-Based VS Code** – Full IDE experience accessible from any device
|
||||
- **Persistent Storage** – Your extensions, settings, and projects survive redeploys
|
||||
- **Non-Root Security** – Runs as the `clauder` user with optional sudo access
|
||||
- **One-Click Deploy** – Deploy to Railway in 60 seconds
|
||||
|
||||
---
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Deploy to Railway
|
||||
|
||||
Click the button above, or:
|
||||
|
||||
1. Go to [Railway Templates](https://railway.com/templates)
|
||||
2. Search for "Claude Code Server"
|
||||
3. Click **Deploy** and set your `PASSWORD`
|
||||
4. Attach a volume to `/home/clauder`
|
||||
5. Open the generated domain in your browser
|
||||
|
||||
### First Login
|
||||
|
||||
1. Enter the password you set
|
||||
2. Open the terminal in VS Code
|
||||
3. Run `claude` to start coding with AI
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
### Required Variables
|
||||
|
||||
| Variable | Description |
|
||||
|------------|------------------------------------|
|
||||
| `PASSWORD` | Login password for the web IDE |
|
||||
|
||||
### Optional Variables
|
||||
|
||||
| Variable | Default | Description |
|
||||
|----------------|--------------------------------|------------------------------------------|
|
||||
| `CLAUDER_HOME` | `/home/clauder` | Volume mount path |
|
||||
| `RUN_AS_USER` | `clauder` | Set to `root` if you need root access |
|
||||
| `APP_NAME` | `Claude Code Server` | Login page title |
|
||||
| `WELCOME_TEXT` | `Welcome to Claude Code Server`| Login page message |
|
||||
|
||||
### Volume Configuration
|
||||
|
||||
> ⚠️ **CRITICAL**: Without a volume, ALL data is lost on every redeploy!
|
||||
|
||||
| Setting | Value |
|
||||
|----------------|------------------|
|
||||
| **Mount Path** | `/home/clauder` |
|
||||
| **Size** | 5GB+ recommended |
|
||||
|
||||
---
|
||||
|
||||
## Built With
|
||||
|
||||
- [code-server](https://github.com/coder/code-server) – VS Code in the browser
|
||||
- [Claude Code CLI](https://claude.ai/code) – AI coding assistant by Anthropic
|
||||
|
||||
---
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
BIN
public/claude-code-server-logo.png
Normal file
BIN
public/claude-code-server-logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 240 KiB |
19
public/claude-code-server-logo.svg
Normal file
19
public/claude-code-server-logo.svg
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="512" height="512" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<linearGradient id="orangeGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" stop-color="#ff7b5c"/>
|
||||
<stop offset="100%" stop-color="#e05a3a"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="blueGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" stop-color="#5b9fff"/>
|
||||
<stop offset="100%" stop-color="#3d7ed8"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- Outer C shape -->
|
||||
<path d="M380 120 C320 60 200 60 140 120 C80 180 80 332 140 392 C200 452 320 452 380 392 L340 352 C300 392 212 392 172 352 C132 312 132 200 172 160 C212 120 300 120 340 160 Z" fill="url(#orangeGrad)"/>
|
||||
|
||||
<!-- Inner code bracket < -->
|
||||
<path d="M320 180 L220 256 L320 332 L280 372 L140 256 L280 140 Z" fill="url(#blueGrad)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 948 B |
BIN
public/iphone_mockup.png
Normal file
BIN
public/iphone_mockup.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 372 KiB |
BIN
public/social-preview.png
Normal file
BIN
public/social-preview.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 412 KiB |
267
railway-entrypoint.sh
Normal file
267
railway-entrypoint.sh
Normal file
@ -0,0 +1,267 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# ============================================================================
|
||||
# VSCode Cloud IDE - Railway Entrypoint
|
||||
# Handles permission fix and optional user switching
|
||||
# ============================================================================
|
||||
|
||||
echo "╔══════════════════════════════════════════════════════════════════════╗"
|
||||
echo "║ VSCode Cloud IDE - Claude Code & Node.js Ready ║"
|
||||
echo "╚══════════════════════════════════════════════════════════════════════╝"
|
||||
echo ""
|
||||
|
||||
# ============================================================================
|
||||
# CONFIGURABLE PATHS AND USER
|
||||
# ============================================================================
|
||||
|
||||
CLAUDER_HOME="${CLAUDER_HOME:-/home/clauder}"
|
||||
CLAUDER_UID="${CLAUDER_UID:-1000}"
|
||||
CLAUDER_GID="${CLAUDER_GID:-1000}"
|
||||
|
||||
# RUN_AS_USER: Defaults to "clauder" for non-root. Set to "root" if needed.
|
||||
RUN_AS_USER="${RUN_AS_USER:-clauder}"
|
||||
|
||||
export HOME="$CLAUDER_HOME"
|
||||
export XDG_DATA_HOME="$CLAUDER_HOME/.local/share"
|
||||
export XDG_CONFIG_HOME="$CLAUDER_HOME/.config"
|
||||
export XDG_CACHE_HOME="$CLAUDER_HOME/.cache"
|
||||
export XDG_STATE_HOME="$CLAUDER_HOME/.local/state"
|
||||
|
||||
# PATH: Include all possible locations for installed tools
|
||||
# - ~/.local/bin: pip user installs, pipx, local scripts
|
||||
# - ~/.npm-global/bin: npm global installs (non-root)
|
||||
# - /usr/local/bin: system-wide installs
|
||||
# - /usr/lib/node_modules/.bin: npm global installs (root/sudo)
|
||||
export PATH="$CLAUDER_HOME/.local/bin:$CLAUDER_HOME/.npm-global/bin:$CLAUDER_HOME/.local/node/bin:$CLAUDER_HOME/.claude/local:$CLAUDER_HOME/node_modules/.bin:/usr/local/bin:/usr/bin:/usr/lib/node_modules/.bin:/usr/lib/code-server/lib/vscode/bin/remote-cli:$PATH"
|
||||
|
||||
echo "→ Initial user: $(whoami) (UID: $(id -u))"
|
||||
echo "→ RUN_AS_USER: $RUN_AS_USER"
|
||||
echo "→ HOME: $HOME"
|
||||
|
||||
# ============================================================================
|
||||
# DIRECTORY CREATION AND PERMISSION FIX
|
||||
# ============================================================================
|
||||
|
||||
if [ "$(id -u)" = "0" ]; then
|
||||
echo ""
|
||||
echo "→ Running setup as root..."
|
||||
|
||||
# Create directories if they don't exist
|
||||
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
|
||||
|
||||
# ========================================================================
|
||||
# SHELL PROFILE SETUP
|
||||
# ========================================================================
|
||||
|
||||
PROFILE_FILE="$HOME/.bashrc"
|
||||
|
||||
if [ ! -f "$PROFILE_FILE" ] || ! grep -q '.npm-global' "$PROFILE_FILE" 2>/dev/null; then
|
||||
echo "→ Setting up shell profile..."
|
||||
cat >> "$PROFILE_FILE" << 'PROFILE'
|
||||
|
||||
# ============================================================================
|
||||
# VSCode Cloud IDE - PATH Configuration
|
||||
# ============================================================================
|
||||
export PATH="$HOME/.local/bin:$HOME/.npm-global/bin:$HOME/.local/node/bin:$HOME/.claude/local:$PATH"
|
||||
|
||||
# npm global prefix for non-root installs
|
||||
export NPM_CONFIG_PREFIX="$HOME/.npm-global"
|
||||
|
||||
# Claude Code alias with --dangerously-skip-permissions
|
||||
alias claude-auto='claude --dangerously-skip-permissions'
|
||||
PROFILE
|
||||
|
||||
# Create npm global directory
|
||||
mkdir -p "$HOME/.npm-global/bin" 2>/dev/null || true
|
||||
|
||||
echo " ✓ Shell profile configured"
|
||||
fi
|
||||
|
||||
# Also set up .profile for login shells
|
||||
if [ ! -f "$HOME/.profile" ] || ! grep -q '.local/bin' "$HOME/.profile" 2>/dev/null; then
|
||||
cat >> "$HOME/.profile" << 'PROFILE'
|
||||
|
||||
# Load .bashrc for interactive shells
|
||||
if [ -f "$HOME/.bashrc" ]; then
|
||||
. "$HOME/.bashrc"
|
||||
fi
|
||||
PROFILE
|
||||
fi
|
||||
|
||||
# ========================================================================
|
||||
# USER SWITCHING (if RUN_AS_USER=clauder)
|
||||
# ========================================================================
|
||||
|
||||
if [ "$RUN_AS_USER" = "clauder" ]; then
|
||||
echo "→ Fixing permissions for clauder user (UID: $CLAUDER_UID)..."
|
||||
chown -R "$CLAUDER_UID:$CLAUDER_GID" "$CLAUDER_HOME" 2>/dev/null || true
|
||||
echo " ✓ Permissions fixed"
|
||||
|
||||
# Check if gosu is available
|
||||
if command -v gosu &>/dev/null; then
|
||||
echo "→ Switching to clauder user via gosu..."
|
||||
exec gosu "$CLAUDER_UID:$CLAUDER_GID" "$0" "$@"
|
||||
else
|
||||
echo " ⚠ gosu not found, staying as root"
|
||||
fi
|
||||
else
|
||||
echo "→ Staying as root (set RUN_AS_USER=clauder to switch)"
|
||||
|
||||
# Create symlinks from /root to volume for persistence
|
||||
mkdir -p /root/.local 2>/dev/null || true
|
||||
for dir in ".local/share" ".local/bin" ".local/node" ".config" ".cache" ".claude"; do
|
||||
target="$CLAUDER_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 $CLAUDER_HOME"
|
||||
fi
|
||||
fi
|
||||
|
||||
# ============================================================================
|
||||
# RUNNING AS FINAL USER
|
||||
# ============================================================================
|
||||
|
||||
echo ""
|
||||
echo "→ Running as: $(whoami) (UID: $(id -u))"
|
||||
|
||||
# ============================================================================
|
||||
# FIRST RUN SETUP
|
||||
# ============================================================================
|
||||
|
||||
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 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
|
||||
|
||||
```bash
|
||||
# Start Claude Code (with auto-accept for automation)
|
||||
claude --dangerously-skip-permissions
|
||||
|
||||
# Or use the alias
|
||||
claude-auto
|
||||
|
||||
# Interactive mode
|
||||
claude
|
||||
```
|
||||
|
||||
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 for Claude)
|
||||
- `RUN_AS_USER=root` - Stay as root
|
||||
|
||||
Happy coding! 🚀
|
||||
WELCOME
|
||||
fi
|
||||
|
||||
touch "$FIRST_RUN_MARKER" 2>/dev/null || true
|
||||
echo " ✓ Initialization complete"
|
||||
fi
|
||||
|
||||
# ============================================================================
|
||||
# ENVIRONMENT VERIFICATION
|
||||
# ============================================================================
|
||||
|
||||
echo ""
|
||||
echo "Environment:"
|
||||
|
||||
# Node.js - show source
|
||||
if [ -x "$CLAUDER_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 "$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
|
||||
echo " → claude: $(claude --version 2>/dev/null || echo 'installed') [volume ~/.claude/local]"
|
||||
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
|
||||
# ============================================================================
|
||||
|
||||
if [ -d "$HOME/entrypoint.d" ]; then
|
||||
for script in "$HOME/entrypoint.d"/*.sh; do
|
||||
if [ -f "$script" ] && [ -x "$script" ]; then
|
||||
echo ""
|
||||
echo "Running: $(basename "$script")"
|
||||
"$script" || echo " ⚠ Script exited with code $?"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# ============================================================================
|
||||
# START CODE-SERVER
|
||||
# ============================================================================
|
||||
|
||||
# Branding customization
|
||||
APP_NAME="${APP_NAME:-Claude Code Server}"
|
||||
WELCOME_TEXT="${WELCOME_TEXT:-Welcome to Claude Code Server}"
|
||||
|
||||
echo ""
|
||||
echo "════════════════════════════════════════════════════════════════════════"
|
||||
echo "Starting $APP_NAME as $(whoami)..."
|
||||
echo "════════════════════════════════════════════════════════════════════════"
|
||||
echo ""
|
||||
|
||||
exec dumb-init /usr/bin/code-server \
|
||||
--bind-addr 0.0.0.0:8080 \
|
||||
--app-name "$APP_NAME" \
|
||||
--welcome-text "$WELCOME_TEXT" \
|
||||
"$CLAUDER_HOME/workspace"
|
||||
18
railway.toml
Normal file
18
railway.toml
Normal file
@ -0,0 +1,18 @@
|
||||
# ============================================================================
|
||||
# Claude Code Server - Railway Configuration
|
||||
# https://github.com/sphinxcode/claude-code-server
|
||||
# ============================================================================
|
||||
|
||||
[build]
|
||||
builder = "DOCKERFILE"
|
||||
dockerfilePath = "Dockerfile"
|
||||
|
||||
[deploy]
|
||||
healthcheckPath = "/healthz"
|
||||
healthcheckTimeout = 300
|
||||
restartPolicyType = "ON_FAILURE"
|
||||
restartPolicyMaxRetries = 10
|
||||
|
||||
# Auto-generate a Railway domain on deployment
|
||||
[[services.networking.external]]
|
||||
port = 8080
|
||||
Loading…
x
Reference in New Issue
Block a user