mirror of
https://github.com/coder/code-server.git
synced 2026-03-30 00:02:16 +08:00
Added deployment options
This commit is contained in:
parent
8299614992
commit
8077b23bd4
67
Dockerfile
67
Dockerfile
@ -1,20 +1,25 @@
|
||||
# ============================================================================
|
||||
# VSCode Cloud IDE - Claude Code & Node.js Ready
|
||||
# Browser-based VSCode with persistent extensions and Node.js
|
||||
# https://github.com/sphinxcode/code-server
|
||||
# Claude Code Server - Browser-based VS Code with AI Coding Assistants
|
||||
# https://github.com/sphinxcode/claude-code-server
|
||||
# ============================================================================
|
||||
|
||||
FROM codercom/code-server:latest
|
||||
FROM codercom/code-server:4.108.0
|
||||
|
||||
USER root
|
||||
|
||||
# Install gosu for proper user switching, Node.js, and essential tools
|
||||
# Cache bust: 2026-01-29-v3
|
||||
# ============================================================================
|
||||
# SYSTEM DEPENDENCIES
|
||||
# Install gosu, Node.js 20, Python/uv, and essential tools
|
||||
# Cache bust: 2026-01-29-v4
|
||||
# ============================================================================
|
||||
|
||||
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
gosu \
|
||||
nodejs \
|
||||
python3 \
|
||||
python3-pip \
|
||||
git \
|
||||
curl \
|
||||
wget \
|
||||
@ -25,6 +30,7 @@ RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
|
||||
nano \
|
||||
ripgrep \
|
||||
&& npm install -g npm@latest \
|
||||
&& pip3 install --break-system-packages uv \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
@ -32,36 +38,46 @@ RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
|
||||
# PERSISTENCE CONFIGURATION
|
||||
# ============================================================================
|
||||
|
||||
ENV HOME=/home/coder
|
||||
ENV USER=coder
|
||||
ENV HOME=/home/clauder
|
||||
ENV USER=clauder
|
||||
|
||||
# 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
|
||||
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/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}"
|
||||
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/coder/entrypoint.d
|
||||
ENV ENTRYPOINTD=/home/clauder/entrypoint.d
|
||||
|
||||
# ============================================================================
|
||||
# USER SETUP
|
||||
# Create clauder user with same UID as coder for compatibility
|
||||
# ============================================================================
|
||||
|
||||
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
|
||||
|
||||
# ============================================================================
|
||||
# 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
|
||||
/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
|
||||
@ -70,6 +86,7 @@ RUN chmod +x /usr/bin/railway-entrypoint.sh
|
||||
# ============================================================================
|
||||
# FALLBACK CLAUDE CODE CLI INSTALLATION
|
||||
# Installed to /usr/local/bin as fallback - volume version takes priority
|
||||
# Claude Code is ALWAYS installed (cannot be disabled)
|
||||
# ============================================================================
|
||||
|
||||
RUN curl -fsSL https://claude.ai/install.sh | bash \
|
||||
@ -84,7 +101,7 @@ RUN curl -fsSL https://claude.ai/install.sh | bash \
|
||||
# Stay as root - entrypoint handles user switching based on RUN_AS_USER
|
||||
# ============================================================================
|
||||
|
||||
WORKDIR /home/coder/workspace
|
||||
WORKDIR /home/clauder/workspace
|
||||
EXPOSE 8080
|
||||
|
||||
# Use our entrypoint which calls code-server directly
|
||||
|
||||
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
|
||||
133
README.md
133
README.md
@ -1,26 +1,17 @@
|
||||
# VSCode Cloud IDE
|
||||
# Claude Code Server
|
||||
|
||||
**Browser-based VSCode with Claude Code & Node.js**
|
||||
**Browser-based VS Code with Claude Code & AI Coding Assistants**
|
||||
|
||||
[](https://railway.com/template/TEMPLATE_ID)
|
||||
[](https://railway.com/template/claude-code-server)
|
||||
|
||||
Cloud IDE with persistent extensions, settings, and tools.
|
||||
|
||||
---
|
||||
|
||||
## Features
|
||||
|
||||
- **Claude Code** & **Node.js 20** pre-installed
|
||||
- Extensions persist across redeployments
|
||||
- Configurable user (root or coder)
|
||||
- Shell profile auto-configured with PATH
|
||||
Cloud IDE with persistent extensions, settings, and tools. Pre-installed Claude Code CLI.
|
||||
|
||||
---
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Claude Code with auto-accept (for automation)
|
||||
# Claude Code with auto-accept
|
||||
claude --dangerously-skip-permissions
|
||||
|
||||
# Or use the alias
|
||||
@ -32,46 +23,80 @@ claude
|
||||
|
||||
---
|
||||
|
||||
## Environment Variables
|
||||
## ⚠️ Claude Code Authentication
|
||||
|
||||
| Variable | Required | Default | Description |
|
||||
|----------|----------|---------|-------------|
|
||||
| `PASSWORD` | Yes | - | Login password |
|
||||
| `RUN_AS_USER` | No | `root` | Set to `coder` for non-root |
|
||||
| `CODER_HOME` | No | `/home/coder` | Volume mount path |
|
||||
| `CODER_UID` | No | `1000` | User ID (when RUN_AS_USER=coder) |
|
||||
| `CODER_GID` | No | `1000` | Group ID (when RUN_AS_USER=coder) |
|
||||
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.
|
||||
|
||||
---
|
||||
|
||||
## Running as Non-Root (Recommended for Claude)
|
||||
## 📍 Railway Deployment
|
||||
|
||||
Set in Railway variables:
|
||||
```
|
||||
RUN_AS_USER=coder
|
||||
```
|
||||
> **Region**: Set your Railway region to **US West** for the fastest performance.
|
||||
|
||||
This enables:
|
||||
### 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 |
|
||||
|
||||
---
|
||||
|
||||
## 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
|
||||
|
||||
This means:
|
||||
- ✅ No root permission warnings
|
||||
- ✅ `claude --dangerously-skip-permissions` works properly
|
||||
- ✅ Better security
|
||||
|
||||
---
|
||||
|
||||
## Update Behavior
|
||||
|
||||
| Component | Behavior |
|
||||
|-----------|----------|
|
||||
| **Volume tools** | You control - install to `~/.local/bin/` |
|
||||
| **Image tools** | Auto-update on redeploy (fallback) |
|
||||
| **Extensions** | Persist on volume |
|
||||
| **Claude auth** | Persists in `~/.claude/` |
|
||||
- ✅ Existing volumes work fine
|
||||
- ✅ Claude `--dangerously-skip-permissions` works
|
||||
|
||||
---
|
||||
|
||||
## Custom Startup Scripts
|
||||
|
||||
Add to `$CODER_HOME/entrypoint.d/`:
|
||||
Add scripts to `$CLAUDER_HOME/entrypoint.d/`:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
@ -82,6 +107,30 @@ Make executable: `chmod +x script.sh`
|
||||
|
||||
---
|
||||
|
||||
## Update Behavior
|
||||
|
||||
| Component | Behavior |
|
||||
|-----------|----------|
|
||||
| **Volume tools** | You control – install to `~/.local/bin/` |
|
||||
| **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 | Solution |
|
||||
|-------|----------|
|
||||
| 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 |
|
||||
|
||||
---
|
||||
|
||||
## Credits
|
||||
|
||||
- [code-server](https://github.com/coder/code-server) by Coder
|
||||
|
||||
@ -2,12 +2,13 @@
|
||||
set -e
|
||||
|
||||
# ============================================================================
|
||||
# VSCode Cloud IDE - Railway Entrypoint
|
||||
# Handles permission fix and optional user switching
|
||||
# Claude Code Server - Railway Entrypoint
|
||||
# Handles permission fix, optional user switching, and CLI installations
|
||||
# https://github.com/sphinxcode/claude-code-server
|
||||
# ============================================================================
|
||||
|
||||
echo "╔══════════════════════════════════════════════════════════════════════╗"
|
||||
echo "║ VSCode Cloud IDE - Claude Code & Node.js Ready ║"
|
||||
echo "║ Claude Code Server - AI Coding Assistants Ready ║"
|
||||
echo "╚══════════════════════════════════════════════════════════════════════╝"
|
||||
echo ""
|
||||
|
||||
@ -15,21 +16,21 @@ echo ""
|
||||
# CONFIGURABLE PATHS AND USER
|
||||
# ============================================================================
|
||||
|
||||
CODER_HOME="${CODER_HOME:-/home/coder}"
|
||||
CODER_UID="${CODER_UID:-1000}"
|
||||
CODER_GID="${CODER_GID:-1000}"
|
||||
CLAUDER_HOME="${CLAUDER_HOME:-/home/clauder}"
|
||||
CLAUDER_UID="${CLAUDER_UID:-1000}"
|
||||
CLAUDER_GID="${CLAUDER_GID:-1000}"
|
||||
|
||||
# RUN_AS_USER: Set to "coder" to run as non-root, or "root" (default) to stay as root
|
||||
# RUN_AS_USER: Set to "clauder" to run as non-root, or "root" (default) to stay as root
|
||||
RUN_AS_USER="${RUN_AS_USER:-root}"
|
||||
|
||||
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"
|
||||
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 ~/.local/bin where Claude installs by default
|
||||
export PATH="$CODER_HOME/.local/bin:$CODER_HOME/.local/node/bin:$CODER_HOME/.claude/local:$CODER_HOME/node_modules/.bin:/usr/local/bin:/usr/bin:/usr/lib/code-server/lib/vscode/bin/remote-cli:$PATH"
|
||||
export PATH="$CLAUDER_HOME/.local/bin:$CLAUDER_HOME/.local/node/bin:$CLAUDER_HOME/.claude/local:$CLAUDER_HOME/node_modules/.bin:/usr/local/bin:/usr/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"
|
||||
@ -56,6 +57,94 @@ 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
|
||||
# ========================================================================
|
||||
@ -67,7 +156,7 @@ if [ "$(id -u)" = "0" ]; then
|
||||
cat >> "$PROFILE_FILE" << 'PROFILE'
|
||||
|
||||
# ============================================================================
|
||||
# VSCode Cloud IDE - PATH Configuration
|
||||
# Claude Code Server - PATH Configuration
|
||||
# ============================================================================
|
||||
export PATH="$HOME/.local/bin:$HOME/.local/node/bin:$HOME/.claude/local:$PATH"
|
||||
|
||||
@ -89,28 +178,28 @@ PROFILE
|
||||
fi
|
||||
|
||||
# ========================================================================
|
||||
# USER SWITCHING (if RUN_AS_USER=coder)
|
||||
# USER SWITCHING (if RUN_AS_USER=clauder)
|
||||
# ========================================================================
|
||||
|
||||
if [ "$RUN_AS_USER" = "coder" ]; then
|
||||
echo "→ Fixing permissions for coder user (UID: $CODER_UID)..."
|
||||
chown -R "$CODER_UID:$CODER_GID" "$CODER_HOME" 2>/dev/null || true
|
||||
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 coder user via gosu..."
|
||||
exec gosu "$CODER_UID:$CODER_GID" "$0" "$@"
|
||||
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=coder to switch)"
|
||||
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="$CODER_HOME/$dir"
|
||||
target="$CLAUDER_HOME/$dir"
|
||||
link="/root/$dir"
|
||||
if [ -d "$target" ] && [ ! -L "$link" ]; then
|
||||
rm -rf "$link" 2>/dev/null || true
|
||||
@ -118,7 +207,7 @@ PROFILE
|
||||
ln -sf "$target" "$link" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
echo " ✓ Root directories symlinked to $CODER_HOME"
|
||||
echo " ✓ Root directories symlinked to $CLAUDER_HOME"
|
||||
fi
|
||||
fi
|
||||
|
||||
@ -133,14 +222,14 @@ echo "→ Running as: $(whoami) (UID: $(id -u))"
|
||||
# FIRST RUN SETUP
|
||||
# ============================================================================
|
||||
|
||||
FIRST_RUN_MARKER="$XDG_DATA_HOME/.vscode-cloud-initialized"
|
||||
FIRST_RUN_MARKER="$XDG_DATA_HOME/.claude-code-server-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
|
||||
# Welcome to Claude Code Server
|
||||
|
||||
Your cloud development environment is ready!
|
||||
|
||||
@ -164,13 +253,21 @@ claude-auto
|
||||
claude
|
||||
```
|
||||
|
||||
You'll need to authenticate with your Anthropic API key on first use.
|
||||
## 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.
|
||||
|
||||
## Configuration
|
||||
|
||||
Set these environment variables in Railway:
|
||||
|
||||
- `RUN_AS_USER=coder` - Run as non-root user (recommended for Claude)
|
||||
- `RUN_AS_USER=clauder` - Run as non-root user (recommended)
|
||||
- `RUN_AS_USER=root` - Stay as root (default)
|
||||
|
||||
Happy coding! 🚀
|
||||
@ -189,7 +286,7 @@ echo ""
|
||||
echo "Environment:"
|
||||
|
||||
# Node.js - show source
|
||||
if [ -x "$CODER_HOME/.local/node/bin/node" ]; then
|
||||
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]"
|
||||
@ -201,10 +298,10 @@ 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/.local/bin/claude" ]; then
|
||||
# Claude Code - show source (always installed)
|
||||
if [ -x "$CLAUDER_HOME/.local/bin/claude" ]; then
|
||||
echo " → claude: $(claude --version 2>/dev/null || echo 'installed') [volume ~/.local/bin]"
|
||||
elif [ -x "$CODER_HOME/.claude/local/claude" ]; then
|
||||
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]"
|
||||
@ -212,6 +309,13 @@ 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)
|
||||
@ -245,4 +349,4 @@ echo "Starting code-server as $(whoami)..."
|
||||
echo "════════════════════════════════════════════════════════════════════════"
|
||||
echo ""
|
||||
|
||||
exec dumb-init /usr/bin/code-server --bind-addr 0.0.0.0:8080 /home/coder/workspace
|
||||
exec dumb-init /usr/bin/code-server --bind-addr 0.0.0.0:8080 "$HOME/workspace"
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
# ============================================================================
|
||||
# VSCode Cloud IDE - Railway Configuration
|
||||
# Claude Code Server - Railway Configuration
|
||||
# https://github.com/sphinxcode/claude-code-server
|
||||
# ============================================================================
|
||||
|
||||
[build]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user