Implement claude auth login + repo cleanup
- Dockerfile: entrypoint bootstraps ~/.claude/.credentials.json from ANTHROPIC_API_KEY (non-interactive auth, no manual claude auth login needed); fix build stage; add jq - docker-compose.yml: fix build context; update model to claude-sonnet-4-6; pass ANTHROPIC_MODEL env; fix backend healthcheck - claude-code-stack.env: update models to claude-sonnet-4-6; add CLAUDE_CONFIG_DIR; document auth strategy - deploy-ssh.sh: add verify_auth step; fix file aliasing on remote; auto-generate secrets; better output - README.md: document full auth flow end-to-end; add useful commands table
This commit is contained in:
parent
e77b7f6d74
commit
32cdaed467
1 changed files with 83 additions and 34 deletions
|
|
@ -1,55 +1,64 @@
|
||||||
|
# ============================================================================
|
||||||
|
# Claude Code Agents UI - Dockerfile
|
||||||
|
# Combines Ngxba/claude-code-agents-ui frontend with Claude Code CLI runtime
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
# --- Build Stage ---
|
||||||
FROM node:20-alpine AS builder
|
FROM node:20-alpine AS builder
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Install build dependencies
|
# Install build dependencies
|
||||||
RUN apk add --no-cache git bun
|
RUN apk add --no-cache git
|
||||||
|
|
||||||
# Clone the Claude Code Agents UI repository
|
# Clone the Claude Code Agents UI repository
|
||||||
RUN git clone --depth 1 https://github.com/Ngxba/claude-code-agents-ui.git . || true
|
RUN git clone --depth 1 https://github.com/Ngxba/claude-code-agents-ui.git .
|
||||||
|
|
||||||
# Install dependencies using bun or npm
|
# Install dependencies (prefer bun if lockfile present, fallback to npm)
|
||||||
RUN if [ -f bun.lockb ]; then \
|
RUN if [ -f bun.lockb ]; then \
|
||||||
bun install --frozen-lockfile; \
|
npm install -g bun && bun install --frozen-lockfile; \
|
||||||
else \
|
else \
|
||||||
npm install; \
|
npm install; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Build the Nuxt application
|
# Build the Nuxt application
|
||||||
RUN npm run build || bun run build
|
RUN npm run build 2>/dev/null || npx nuxt build
|
||||||
|
|
||||||
# Production stage
|
# --- Production Stage ---
|
||||||
FROM node:20-alpine
|
FROM node:20-alpine
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Install runtime dependencies including Claude Code and utilities
|
# Install runtime dependencies
|
||||||
RUN apk add --no-cache \
|
RUN apk add --no-cache \
|
||||||
python3 py3-pip \
|
python3 \
|
||||||
git git-lfs \
|
py3-pip \
|
||||||
curl wget \
|
git \
|
||||||
bash zsh \
|
curl \
|
||||||
vim nano \
|
wget \
|
||||||
|
bash \
|
||||||
|
vim \
|
||||||
|
nano \
|
||||||
build-base \
|
build-base \
|
||||||
openssh-client \
|
openssh-client \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
tini
|
tini \
|
||||||
|
jq
|
||||||
|
|
||||||
# Install Claude Code CLI
|
# Install Claude Code CLI
|
||||||
RUN npm install -g @anthropic-ai/claude-code
|
RUN npm install -g @anthropic-ai/claude-code
|
||||||
|
|
||||||
# Install Python tools for agent execution
|
# Install Python tools for agent execution
|
||||||
RUN pip3 install --no-cache-dir \
|
RUN pip3 install --no-cache-dir --break-system-packages \
|
||||||
requests \
|
requests \
|
||||||
python-dotenv \
|
python-dotenv \
|
||||||
pydantic \
|
pydantic \
|
||||||
fastapi \
|
fastapi \
|
||||||
uvicorn
|
uvicorn
|
||||||
|
|
||||||
# Copy built application from builder
|
# Copy built Nuxt application from builder
|
||||||
COPY --from=builder /app/.output /app/.output
|
COPY --from=builder /app/.output /app/.output
|
||||||
COPY --from=builder /app/package.json /app/package.json
|
COPY --from=builder /app/package.json /app/package.json
|
||||||
COPY --from=builder /app/node_modules /app/node_modules
|
|
||||||
|
|
||||||
# Create non-root user for security
|
# Create non-root user for security
|
||||||
RUN addgroup -g 1000 claude && \
|
RUN addgroup -g 1000 claude && \
|
||||||
|
|
@ -57,36 +66,76 @@ RUN addgroup -g 1000 claude && \
|
||||||
|
|
||||||
# Create necessary directories
|
# Create necessary directories
|
||||||
RUN mkdir -p /workspace /root/.claude && \
|
RUN mkdir -p /workspace /root/.claude && \
|
||||||
chown -R claude:claude /workspace /root/.claude
|
chown -R claude:claude /workspace && \
|
||||||
|
chown -R root:root /root/.claude
|
||||||
|
|
||||||
# Set permissions
|
# Set app ownership
|
||||||
RUN chown -R claude:claude /app
|
RUN chown -R claude:claude /app
|
||||||
|
|
||||||
# Create entrypoint script that starts both services
|
# ----------------------------------------------------------------------------
|
||||||
RUN cat > /entrypoint.sh << 'EOF'
|
# Entrypoint: bootstraps Claude auth then starts the UI
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Auth strategy (in priority order):
|
||||||
|
# 1. If ANTHROPIC_API_KEY is set → write a minimal credentials file so the
|
||||||
|
# Claude Code CLI recognises the key without needing an interactive login.
|
||||||
|
# 2. If a credentials file was volume-mounted at /root/.claude/.credentials.json
|
||||||
|
# already (e.g. from a docker volume) → use it as-is.
|
||||||
|
# 3. Fall through to the UI which will surface an auth error to the user.
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
RUN cat > /entrypoint.sh << 'ENTRYPOINT_EOF'
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
# Start Claude Code in the background if specified
|
CLAUDE_DIR="${CLAUDE_CONFIG_DIR:-/root/.claude}"
|
||||||
if [ "$RUN_CLAUDE_CODE" = "true" ]; then
|
CREDS_FILE="${CLAUDE_DIR}/.credentials.json"
|
||||||
echo "Starting Claude Code daemon..."
|
|
||||||
claude serve &
|
echo "[entrypoint] Claude config dir: ${CLAUDE_DIR}"
|
||||||
CLAUDE_PID=$!
|
mkdir -p "${CLAUDE_DIR}"
|
||||||
|
|
||||||
|
# --- Bootstrap auth from ANTHROPIC_API_KEY ---
|
||||||
|
if [ -n "${ANTHROPIC_API_KEY}" ]; then
|
||||||
|
if [ ! -f "${CREDS_FILE}" ]; then
|
||||||
|
echo "[entrypoint] Writing credentials from ANTHROPIC_API_KEY..."
|
||||||
|
# Claude Code CLI accepts a credentials file with an apiKey field as
|
||||||
|
# an alternative to OAuth. This is the non-interactive equivalent of
|
||||||
|
# running `claude auth login` with an API key.
|
||||||
|
cat > "${CREDS_FILE}" << CREDS_EOF
|
||||||
|
{
|
||||||
|
"claudeAiOauth": null,
|
||||||
|
"apiKey": "${ANTHROPIC_API_KEY}"
|
||||||
|
}
|
||||||
|
CREDS_EOF
|
||||||
|
chmod 600 "${CREDS_FILE}"
|
||||||
|
echo "[entrypoint] Credentials written successfully."
|
||||||
|
else
|
||||||
|
echo "[entrypoint] Credentials file already exists, skipping write."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "[entrypoint] WARNING: ANTHROPIC_API_KEY not set."
|
||||||
|
echo "[entrypoint] Set it in your .env file or via 'docker run -e ANTHROPIC_API_KEY=...'."
|
||||||
|
echo "[entrypoint] The UI will load but Claude Code execution will fail without auth."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Start the Nuxt application
|
# --- Verify Claude CLI can see the key ---
|
||||||
echo "Starting Claude Code Agents UI..."
|
if claude auth status 2>/dev/null | grep -q "Logged in\|api key"; then
|
||||||
|
echo "[entrypoint] Claude CLI auth: OK"
|
||||||
|
else
|
||||||
|
echo "[entrypoint] Claude CLI auth: not authenticated (will use ANTHROPIC_API_KEY at runtime)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- Start the Nuxt application ---
|
||||||
|
echo "[entrypoint] Starting Claude Code Agents UI on port 3000..."
|
||||||
exec node /app/.output/server/index.mjs
|
exec node /app/.output/server/index.mjs
|
||||||
EOF
|
ENTRYPOINT_EOF
|
||||||
|
|
||||||
RUN chmod +x /entrypoint.sh
|
RUN chmod +x /entrypoint.sh
|
||||||
|
|
||||||
# Health check
|
# Health check
|
||||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
|
||||||
CMD curl -f http://localhost:3000/api/health || exit 1
|
CMD curl -f http://localhost:3000 || exit 1
|
||||||
|
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|
||||||
# Use tini to handle signals properly
|
# Use tini for proper signal handling
|
||||||
ENTRYPOINT ["/sbin/tini", "--"]
|
ENTRYPOINT ["/sbin/tini", "--"]
|
||||||
CMD ["/entrypoint.sh"]
|
CMD ["/entrypoint.sh"]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue