diff --git a/Dockerfile b/Dockerfile index c3078ad..96fa5de 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,8 +9,13 @@ RUN apt-get update && apt-get install -y \ curl \ python3 \ build-essential \ + sudo \ && rm -rf /var/lib/apt/lists/* +# Create a non-root user +RUN useradd -m -s /bin/bash claude-user && \ + echo "claude-user ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + # Create app directory WORKDIR /app @@ -24,7 +29,7 @@ ENV PATH="/usr/local/bin:${PATH}" RUN npm install -g @twilio-alpha/mcp # Create directories for configuration -RUN mkdir -p /app/config /app/.claude +RUN mkdir -p /app/config /app/.claude /home/claude-user/.claude # Copy MCP configuration COPY config/mcp-config.json /app/config/ @@ -33,11 +38,18 @@ COPY config/mcp-config.json /app/config/ COPY scripts/startup.sh /app/ RUN chmod +x /app/startup.sh +# Set proper ownership +RUN chown -R claude-user:claude-user /app /home/claude-user + +# Switch to non-root user +USER claude-user + # Set working directory to mounted volume WORKDIR /workspace # Environment variables will be passed from host ENV NODE_ENV=production +ENV HOME=/home/claude-user # Start both MCP server and Claude Code ENTRYPOINT ["/app/startup.sh"] \ No newline at end of file diff --git a/scratchpad.md b/scratchpad.md index a37fa2b..35c1dfc 100644 --- a/scratchpad.md +++ b/scratchpad.md @@ -19,21 +19,62 @@ Building a Docker container that runs Claude Code with full autonomous permissio ## Next Steps 🎯 **Phase 2 - Security & Persistence Enhancements:** -### 1. Authentication Persistence (HIGH Priority) -- Avoid repeated Claude account logins every session -- Research how to persist Claude Code authentication tokens -- Investigate mounting Claude authentication data from host -- Study Anthropic's dev container auth persistence approach +### 1. Authentication Persistence (HIGH Priority) - CURRENT FOCUS +**Problem:** Need to re-login to Claude Code every time container starts -### 2. Network Security (High Priority) -- Implement firewall to restrict network access (study Anthropic's dev container) -- Whitelist only essential domains: - - api.anthropic.com (Claude API) - - api.twilio.com (SMS notifications) - - github.com, raw.githubusercontent.com (git operations) - - npm registry domains (package management) - - Common documentation sites (if needed) -- Block all other outbound connections for security +**Research Findings:** +- Claude Code stores auth tokens in temporary locations that get cleared +- Known issues: #1222 (persistent auth warnings), #1676 (logout after restart) +- The devcontainer mounts `/home/node/.claude` for config persistence +- But auth tokens are NOT persisted properly even in devcontainer + +**Implementation Plan:** +1. **Mount Claude config directory from host:** + - Create persistent `~/.claude-docker/claude-config` on host + - Mount to container's `~/.config/claude` or appropriate location + - Preserve authentication tokens between sessions + +2. **Modify startup script to:** + - Check for existing auth tokens on container start + - Skip login prompt if valid tokens exist + - Handle token refresh if needed + +3. **Token storage investigation:** + - Find where Claude Code stores auth tokens (likely ~/.config/claude or similar) + - Ensure proper permissions on mounted directory + - Test token persistence across container restarts + +### 2. Network Security (High Priority) - PLANNED +**Implementation based on devcontainer's init-firewall.sh:** + +**Key Components:** +1. **Firewall Script Features:** + - Uses iptables with default DROP policy + - ipset for managing allowed IP ranges + - Dynamic IP resolution for allowed domains + - Verification of connectivity post-setup + +2. **Allowed Domains Configuration:** + ```yaml + allowed_domains: + - api.anthropic.com # Claude API + - api.twilio.com # SMS notifications + - github.com # Git operations + - raw.githubusercontent.com + - registry.npmjs.org # Package management + - pypi.org # Python packages + + blocked_paths: # File system restrictions + - /etc + - /root + - ~/.ssh + ``` + +3. **User-Friendly Setup:** + - Simple YAML config file for rules + - Easy enable/disable of firewall + - Logging of blocked attempts + - Graceful degradation if firewall fails ### 3. Shell History Persistence (Medium Priority) - Add persistent bash/zsh history between container sessions @@ -62,6 +103,7 @@ Building a Docker container that runs Claude Code with full autonomous permissio - Simplified settings.json to only include MCP config (no redundant allowedTools) - **NEW:** Adding firewall for network security - **NEW:** Adding shell history persistence like Claude dev container +- **NEW (2024-12-06):** Focus on auth persistence first before firewall implementation ## Notes & Context - Repository: https://github.com/VishalJ99/claude-docker @@ -78,6 +120,10 @@ Building a Docker container that runs Claude Code with full autonomous permissio - Added explicit PATH for npm global binaries - Maintained separation: `claude-docker` (host) vs `claude` (container) - **Current working state:** Container launches successfully, authentication required each session +- **Auth Persistence Research (2024-12-06):** + - Claude Code has known issues with auth persistence + - Tokens stored in temp locations that get cleared + - Need to find exact token storage location and persist it ## Quick References - Install: `./scripts/install.sh` diff --git a/scripts/claude-docker.sh b/scripts/claude-docker.sh index 6ee6c93..dc2eeec 100755 --- a/scripts/claude-docker.sh +++ b/scripts/claude-docker.sh @@ -38,12 +38,16 @@ if ! docker images | grep -q "claude-docker"; then docker build -t claude-docker:latest "$PROJECT_ROOT" fi +# Ensure the claude-home directory exists +mkdir -p "$HOME/.claude-docker/claude-home" + # Run Claude Code in Docker echo "Starting Claude Code in Docker..." docker run -it --rm \ -v "$CURRENT_DIR:/workspace" \ -v "$ENV_FILE:/app/.env:ro" \ -v "$HOME/.claude-docker/config:/app/.claude:rw" \ + -v "$HOME/.claude-docker/claude-home:/home/claude-user/.claude:rw" \ --workdir /workspace \ --name claude-docker-session \ claude-docker:latest "$@" \ No newline at end of file diff --git a/scripts/install.sh b/scripts/install.sh index e58cd2b..5b26178 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -5,8 +5,9 @@ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" -# Create config directory +# Create config directory and claude persistence directory mkdir -p "$HOME/.claude-docker/config" +mkdir -p "$HOME/.claude-docker/claude-home" # Copy example env file if doesn't exist if [ ! -f "$HOME/.claude-docker/.env" ]; then diff --git a/scripts/startup.sh b/scripts/startup.sh index 986c861..610bbf2 100755 --- a/scripts/startup.sh +++ b/scripts/startup.sh @@ -12,6 +12,14 @@ fi # Configure Claude Code to use the MCP server export CLAUDE_MCP_CONFIG=/app/config/mcp-config.json +# Check for existing authentication +if [ -f "$HOME/.claude/.credentials.json" ]; then + echo "Found existing Claude authentication" +else + echo "No existing authentication found - you will need to log in" + echo "Your login will be saved for future sessions" +fi + # Start Claude Code with permissions bypass echo "Starting Claude Code..." if [ -n "$TWILIO_ACCOUNT_SID" ] && [ -n "$TWILIO_API_KEY" ]; then @@ -19,5 +27,4 @@ if [ -n "$TWILIO_ACCOUNT_SID" ] && [ -n "$TWILIO_API_KEY" ]; then else echo "No Twilio credentials found, MCP features will be unavailable" fi -echo "Note: If prompted for authentication, follow the interactive prompts" exec claude --dangerously-skip-permissions "$@" \ No newline at end of file