mirror of
https://github.com/coder/code-server.git
synced 2026-02-19 18:01:15 +08:00
Add RUN_AS_USER variable - default root, set to coder for non-root
This commit is contained in:
parent
5dd4e6a446
commit
d384d20fa5
71
README.md
71
README.md
@ -4,16 +4,16 @@
|
||||
|
||||
[](https://railway.com/template/TEMPLATE_ID)
|
||||
|
||||
Cloud IDE with persistent extensions, settings, and tools. Runs as non-root user.
|
||||
Cloud IDE with persistent extensions, settings, and tools.
|
||||
|
||||
---
|
||||
|
||||
## Features
|
||||
|
||||
- **Claude Code** & **Node.js 20** pre-installed
|
||||
- **Non-root execution** - runs as `coder` user (UID 1000)
|
||||
- Extensions persist across redeployments
|
||||
- Volume permissions auto-fixed on startup
|
||||
- Configurable user (root or coder)
|
||||
- Shell profile auto-configured with PATH
|
||||
|
||||
---
|
||||
|
||||
@ -23,12 +23,11 @@ Cloud IDE with persistent extensions, settings, and tools. Runs as non-root user
|
||||
# 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
|
||||
```
|
||||
|
||||
---
|
||||
@ -38,32 +37,35 @@ npm --version
|
||||
| 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 for coder |
|
||||
| `CODER_GID` | No | `1000` | Group ID for coder |
|
||||
| `CODER_UID` | No | `1000` | User ID (when RUN_AS_USER=coder) |
|
||||
| `CODER_GID` | No | `1000` | Group ID (when RUN_AS_USER=coder) |
|
||||
|
||||
---
|
||||
|
||||
## How It Works
|
||||
## Running as Non-Root (Recommended for Claude)
|
||||
|
||||
1. **Starts as root** - fixes volume permissions
|
||||
2. **Switches to coder** - uses `gosu` for clean handoff
|
||||
3. **Runs code-server** - as non-root user
|
||||
Set in Railway variables:
|
||||
```
|
||||
RUN_AS_USER=coder
|
||||
```
|
||||
|
||||
This means:
|
||||
- ✅ No root permission warnings in code-server
|
||||
- ✅ Existing volumes with root-owned files work fine
|
||||
- ✅ Claude `--dangerously-skip-permissions` works
|
||||
This enables:
|
||||
- ✅ No root permission warnings
|
||||
- ✅ `claude --dangerously-skip-permissions` works properly
|
||||
- ✅ Better security
|
||||
|
||||
---
|
||||
|
||||
## Claude Code Authentication
|
||||
## Update Behavior
|
||||
|
||||
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)
|
||||
| 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/` |
|
||||
|
||||
---
|
||||
|
||||
@ -80,29 +82,6 @@ Make executable: `chmod +x script.sh`
|
||||
|
||||
---
|
||||
|
||||
## Update Behavior
|
||||
|
||||
| Component | Behavior |
|
||||
|-----------|----------|
|
||||
| **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 |
|
||||
|
||||
Logs show `[volume]` or `[image]` next to each tool.
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Issue | Solution |
|
||||
|-------|----------|
|
||||
| Permission denied | Check `CODER_UID` matches your volume owner |
|
||||
| Claude not found | Run `which claude` to check PATH |
|
||||
| Extensions missing | Verify volume mounted at `CODER_HOME` |
|
||||
|
||||
---
|
||||
|
||||
## Credits
|
||||
|
||||
- [code-server](https://github.com/coder/code-server) by Coder
|
||||
|
||||
@ -3,7 +3,7 @@ set -e
|
||||
|
||||
# ============================================================================
|
||||
# VSCode Cloud IDE - Railway Entrypoint
|
||||
# Handles permission fix and user switching for non-root execution
|
||||
# Handles permission fix and optional user switching
|
||||
# ============================================================================
|
||||
|
||||
echo "╔══════════════════════════════════════════════════════════════════════╗"
|
||||
@ -12,13 +12,16 @@ echo "╚═══════════════════════
|
||||
echo ""
|
||||
|
||||
# ============================================================================
|
||||
# CONFIGURABLE PATHS
|
||||
# CONFIGURABLE PATHS AND USER
|
||||
# ============================================================================
|
||||
|
||||
CODER_HOME="${CODER_HOME:-/home/coder}"
|
||||
CODER_UID="${CODER_UID:-1000}"
|
||||
CODER_GID="${CODER_GID:-1000}"
|
||||
|
||||
# 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="$CODER_HOME"
|
||||
export XDG_DATA_HOME="$CODER_HOME/.local/share"
|
||||
export XDG_CONFIG_HOME="$CODER_HOME/.config"
|
||||
@ -28,12 +31,17 @@ export XDG_STATE_HOME="$CODER_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"
|
||||
|
||||
echo "→ Initial user: $(whoami) (UID: $(id -u))"
|
||||
echo "→ RUN_AS_USER: $RUN_AS_USER"
|
||||
echo "→ HOME: $HOME"
|
||||
|
||||
# ============================================================================
|
||||
# PERMISSION FIX (runs as root, then switches to coder)
|
||||
# DIRECTORY CREATION AND PERMISSION FIX
|
||||
# ============================================================================
|
||||
|
||||
if [ "$(id -u)" = "0" ]; then
|
||||
echo "→ Running initial setup as root..."
|
||||
echo ""
|
||||
echo "→ Running setup as root..."
|
||||
|
||||
# Create directories if they don't exist
|
||||
mkdir -p "$XDG_DATA_HOME" \
|
||||
@ -50,11 +58,9 @@ if [ "$(id -u)" = "0" ]; then
|
||||
|
||||
# ========================================================================
|
||||
# SHELL PROFILE SETUP
|
||||
# Ensure PATH includes ~/.local/bin for Claude and other user tools
|
||||
# ========================================================================
|
||||
|
||||
PROFILE_FILE="$HOME/.bashrc"
|
||||
PATH_EXPORT='export PATH="$HOME/.local/bin:$HOME/.local/node/bin:$PATH"'
|
||||
|
||||
if [ ! -f "$PROFILE_FILE" ] || ! grep -q '.local/bin' "$PROFILE_FILE" 2>/dev/null; then
|
||||
echo "→ Setting up shell profile..."
|
||||
@ -82,24 +88,46 @@ fi
|
||||
PROFILE
|
||||
fi
|
||||
|
||||
# Fix ownership on the entire home directory
|
||||
echo "→ Fixing permissions for coder user (UID: $CODER_UID)..."
|
||||
chown -R "$CODER_UID:$CODER_GID" "$CODER_HOME" 2>/dev/null || true
|
||||
# ========================================================================
|
||||
# USER SWITCHING (if RUN_AS_USER=coder)
|
||||
# ========================================================================
|
||||
|
||||
echo " ✓ Permissions fixed"
|
||||
echo ""
|
||||
|
||||
# Re-exec this script as coder user using gosu
|
||||
echo "→ Switching to coder user..."
|
||||
exec gosu "$CODER_UID:$CODER_GID" "$0" "$@"
|
||||
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
|
||||
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" "$@"
|
||||
else
|
||||
echo " ⚠ gosu not found, staying as root"
|
||||
fi
|
||||
else
|
||||
echo "→ Staying as root (set RUN_AS_USER=coder 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"
|
||||
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 $CODER_HOME"
|
||||
fi
|
||||
fi
|
||||
|
||||
# ============================================================================
|
||||
# RUNNING AS CODER USER FROM HERE
|
||||
# RUNNING AS FINAL USER
|
||||
# ============================================================================
|
||||
|
||||
echo "→ User: $(whoami) (UID: $(id -u))"
|
||||
echo "→ HOME: $HOME"
|
||||
echo ""
|
||||
echo "→ Running as: $(whoami) (UID: $(id -u))"
|
||||
|
||||
# ============================================================================
|
||||
# FIRST RUN SETUP
|
||||
@ -138,10 +166,12 @@ claude
|
||||
|
||||
You'll need to authenticate with your Anthropic API key on first use.
|
||||
|
||||
## Persist Claude Authentication
|
||||
## Configuration
|
||||
|
||||
Your Claude config at `~/.claude/` persists across redeployments.
|
||||
After authenticating once, you won't need to re-authenticate.
|
||||
Set these environment variables in Railway:
|
||||
|
||||
- `RUN_AS_USER=coder` - Run as non-root user (recommended for Claude)
|
||||
- `RUN_AS_USER=root` - Stay as root (default)
|
||||
|
||||
Happy coding! 🚀
|
||||
WELCOME
|
||||
@ -171,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 (check ~/.local/bin first, then ~/.claude/local, then /usr/local/bin)
|
||||
# Claude Code - show source
|
||||
if [ -x "$CODER_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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user