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
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.
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
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
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
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
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
Documentation for all configuration variables
Quick start guide for Claude Code
Update behavior explanation
Troubleshooting guide
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
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.)
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)
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
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
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
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
╔══════════════════════════════════════════════════════════════════════════╗
║ 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...
════════════════════════════════════════════════════════════════════════
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
Verify Deployment - Check if entrypoint runs and user switches properly
Test Claude - Authenticate and run claude --dangerously-skip-permissions
Create Railway Template - Make template public for others to deploy
Update Template Docs - Include volume attachment instructions