Implement authentication persistence for Claude Docker

- Add persistent volume mount for Claude home directory (~/.claude)
- Create non-root user in Docker container for better security
- Mount host ~/.claude-docker/claude-home to container ~/.claude
- Update install script to create claude-home directory
- Check for existing credentials on startup
- Authentication tokens now persist across container restarts
This commit is contained in:
Vishal Jain 2025-06-12 14:09:10 +01:00
parent c99bc9c561
commit dcc936dc10
5 changed files with 87 additions and 17 deletions

View File

@ -9,8 +9,13 @@ RUN apt-get update && apt-get install -y \
curl \ curl \
python3 \ python3 \
build-essential \ build-essential \
sudo \
&& rm -rf /var/lib/apt/lists/* && 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 # Create app directory
WORKDIR /app WORKDIR /app
@ -24,7 +29,7 @@ ENV PATH="/usr/local/bin:${PATH}"
RUN npm install -g @twilio-alpha/mcp RUN npm install -g @twilio-alpha/mcp
# Create directories for configuration # 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 MCP configuration
COPY config/mcp-config.json /app/config/ COPY config/mcp-config.json /app/config/
@ -33,11 +38,18 @@ COPY config/mcp-config.json /app/config/
COPY scripts/startup.sh /app/ COPY scripts/startup.sh /app/
RUN chmod +x /app/startup.sh 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 # Set working directory to mounted volume
WORKDIR /workspace WORKDIR /workspace
# Environment variables will be passed from host # Environment variables will be passed from host
ENV NODE_ENV=production ENV NODE_ENV=production
ENV HOME=/home/claude-user
# Start both MCP server and Claude Code # Start both MCP server and Claude Code
ENTRYPOINT ["/app/startup.sh"] ENTRYPOINT ["/app/startup.sh"]

View File

@ -19,21 +19,62 @@ Building a Docker container that runs Claude Code with full autonomous permissio
## Next Steps 🎯 ## Next Steps 🎯
**Phase 2 - Security & Persistence Enhancements:** **Phase 2 - Security & Persistence Enhancements:**
### 1. Authentication Persistence (HIGH Priority) ### 1. Authentication Persistence (HIGH Priority) - CURRENT FOCUS
- Avoid repeated Claude account logins every session **Problem:** Need to re-login to Claude Code every time container starts
- Research how to persist Claude Code authentication tokens
- Investigate mounting Claude authentication data from host
- Study Anthropic's dev container auth persistence approach
### 2. Network Security (High Priority) **Research Findings:**
- Implement firewall to restrict network access (study Anthropic's dev container) - Claude Code stores auth tokens in temporary locations that get cleared
- Whitelist only essential domains: - Known issues: #1222 (persistent auth warnings), #1676 (logout after restart)
- api.anthropic.com (Claude API) - The devcontainer mounts `/home/node/.claude` for config persistence
- api.twilio.com (SMS notifications) - But auth tokens are NOT persisted properly even in devcontainer
- github.com, raw.githubusercontent.com (git operations)
- npm registry domains (package management) **Implementation Plan:**
- Common documentation sites (if needed) 1. **Mount Claude config directory from host:**
- Block all other outbound connections for security - 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) ### 3. Shell History Persistence (Medium Priority)
- Add persistent bash/zsh history between container sessions - 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) - Simplified settings.json to only include MCP config (no redundant allowedTools)
- **NEW:** Adding firewall for network security - **NEW:** Adding firewall for network security
- **NEW:** Adding shell history persistence like Claude dev container - **NEW:** Adding shell history persistence like Claude dev container
- **NEW (2024-12-06):** Focus on auth persistence first before firewall implementation
## Notes & Context ## Notes & Context
- Repository: https://github.com/VishalJ99/claude-docker - 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 - Added explicit PATH for npm global binaries
- Maintained separation: `claude-docker` (host) vs `claude` (container) - Maintained separation: `claude-docker` (host) vs `claude` (container)
- **Current working state:** Container launches successfully, authentication required each session - **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 ## Quick References
- Install: `./scripts/install.sh` - Install: `./scripts/install.sh`

View File

@ -38,12 +38,16 @@ if ! docker images | grep -q "claude-docker"; then
docker build -t claude-docker:latest "$PROJECT_ROOT" docker build -t claude-docker:latest "$PROJECT_ROOT"
fi fi
# Ensure the claude-home directory exists
mkdir -p "$HOME/.claude-docker/claude-home"
# Run Claude Code in Docker # Run Claude Code in Docker
echo "Starting Claude Code in Docker..." echo "Starting Claude Code in Docker..."
docker run -it --rm \ docker run -it --rm \
-v "$CURRENT_DIR:/workspace" \ -v "$CURRENT_DIR:/workspace" \
-v "$ENV_FILE:/app/.env:ro" \ -v "$ENV_FILE:/app/.env:ro" \
-v "$HOME/.claude-docker/config:/app/.claude:rw" \ -v "$HOME/.claude-docker/config:/app/.claude:rw" \
-v "$HOME/.claude-docker/claude-home:/home/claude-user/.claude:rw" \
--workdir /workspace \ --workdir /workspace \
--name claude-docker-session \ --name claude-docker-session \
claude-docker:latest "$@" claude-docker:latest "$@"

View File

@ -5,8 +5,9 @@
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" 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/config"
mkdir -p "$HOME/.claude-docker/claude-home"
# Copy example env file if doesn't exist # Copy example env file if doesn't exist
if [ ! -f "$HOME/.claude-docker/.env" ]; then if [ ! -f "$HOME/.claude-docker/.env" ]; then

View File

@ -12,6 +12,14 @@ fi
# Configure Claude Code to use the MCP server # Configure Claude Code to use the MCP server
export CLAUDE_MCP_CONFIG=/app/config/mcp-config.json 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 # Start Claude Code with permissions bypass
echo "Starting Claude Code..." echo "Starting Claude Code..."
if [ -n "$TWILIO_ACCOUNT_SID" ] && [ -n "$TWILIO_API_KEY" ]; then 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 else
echo "No Twilio credentials found, MCP features will be unavailable" echo "No Twilio credentials found, MCP features will be unavailable"
fi fi
echo "Note: If prompted for authentication, follow the interactive prompts"
exec claude --dangerously-skip-permissions "$@" exec claude --dangerously-skip-permissions "$@"