diff --git a/Dockerfile b/Dockerfile index cac1e341..1029ce8e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,41 +1,50 @@ -FROM oven/bun:1.3.9 AS base +# syntax=docker/dockerfile:1 +FROM archlinux:latest AS base WORKDIR /app -RUN apt-get update && apt-get install -y --no-install-recommends python3 make g++ && rm -rf /var/lib/apt/lists/* + +# Install build dependencies in base stage +RUN pacman -Sy --noconfirm --needed bun && \ + pacman -Scc --noconfirm FROM base AS deps -COPY . . +WORKDIR /app +COPY package.json bun.lock ./ +COPY packages/ui/package.json ./packages/ui/ +COPY packages/web/package.json ./packages/web/ +COPY packages/desktop/package.json ./packages/desktop/ +COPY packages/vscode/package.json ./packages/vscode/ RUN bun install --frozen-lockfile --ignore-scripts FROM deps AS builder +WORKDIR /app +COPY . . RUN bun run build:web -FROM oven/bun:1.3.9 AS runtime -WORKDIR /app +FROM base AS runtime + +RUN pacman -Sy --noconfirm --needed base-devel python openssh cloudflared git nodejs npm && \ + pacman -Scc --noconfirm ENV NODE_ENV=production -ENV OPENCHAMBER_PORT=3000 -ENV BUN_INSTALL=/home/bun/.bun -ENV PATH=${BUN_INSTALL}/bin:${PATH} -USER root +# Create openchamber user +RUN useradd -m -s /bin/bash openchamber -RUN apt-get update && apt-get install -y --no-install-recommends git npm openssh-client && rm -rf /var/lib/apt/lists/* +# Switch to openchamber user +USER openchamber -# 配置 npm 全局安装到用户可写目录 -RUN npm config set prefix /home/bun/.npm-global && mkdir -p /home/bun/.npm-global - -ENV NPM_CONFIG_PREFIX=/home/bun/.npm-global +RUN npm config set prefix /home/openchamber/.npm-global && mkdir -p /home/openchamber/.npm-global +ENV NPM_CONFIG_PREFIX=/home/openchamber/.npm-global ENV PATH=${NPM_CONFIG_PREFIX}/bin:${PATH} -# 确保 bun 用户对全局 npm 目录有写权限 -RUN chown -R bun:bun /home/bun/.npm-global -USER bun +# Create necessary directories and set ownership +RUN mkdir -p /home/openchamber/.local /home/openchamber/.config /home/openchamber/.ssh +# Install npm packages as root RUN npm install -g opencode-ai -RUN mkdir -p /home/bun/.local /home/bun/.config /home/bun/.ssh - +WORKDIR /home/openchamber COPY --from=deps /app/node_modules ./node_modules COPY --from=deps /app/packages/web/node_modules ./packages/web/node_modules COPY --from=builder /app/package.json ./package.json diff --git a/README.md b/README.md index 2b07831c..a8a0969b 100644 --- a/README.md +++ b/README.md @@ -128,11 +128,37 @@ docker compose up -d The service will be available at `http://localhost:3000`. +**UI Password (optional):** To enable password-protected access, uncomment and set the `UI_PASSWORD` environment variable in `docker-compose.yml`: + +```yaml +environment: + UI_PASSWORD: your_secure_password +``` + +Or pass it via command line: + +```bash +UI_PASSWORD=secret docker compose up -d +``` + +**Cloudflare Tunnel (optional):** To enable Cloudflare Quick Tunnel for remote access, set the `CF_TUNNEL` environment variable: + +```yaml +environment: + CF_TUNNEL: "true" # Options: true, qr, password, full +``` + +| Value | Description | +| ---------- | ------------------------------- | +| `true` | Enable tunnel only | +| `qr` | Enable tunnel + QR code | +| `password` | Enable tunnel + password in URL | + **Data Directory Permission Note:** The `data/` directory is mounted into the container for persistent storage (config, sessions, SSH keys, workspaces). Before running, ensure the directory exists and has proper permissions: ```bash # Create data directories with correct ownership -mkdir -p data/openchamber data/opencode/share data/opencode/config data/ssh data/workspaces +mkdir -p data/openchamber data/opencode/share data/opencode/config data/ssh # Fix permissions (replace $USER with your username) chown -R 1000:1000 data/ @@ -140,6 +166,8 @@ chown -R 1000:1000 data/ Without proper permissions, the container may fail to start or encounter permission denied errors when writing to these directories. +**SSH/Git Authentication Note:** If git pull/push fails. Run `ssh -T git@github.com` in terminal. + ## Prerequisites - [OpenCode CLI](https://opencode.ai) installed diff --git a/docker-compose.yml b/docker-compose.yml index 9a7eef03..4af4fcfa 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,11 +10,16 @@ services: extra_hosts: - "host.docker.internal:host-gateway" volumes: - - ./data/openchamber:/home/bun/.config/openchamber - - ./data/opencode/share:/home/bun/.local/share/opencode - - ./data/opencode/config:/home/bun/.config/opencode - - ./data/ssh:/home/bun/.ssh - - ./workspaces:/home/bun/workspaces - # environment: - # OH_MY_OPENCODE: true # enable oh-my-opencode + - ./data/openchamber:/home/openchamber/.config/openchamber + - ./data/opencode/share:/home/openchamber/.local/share/opencode + - ./data/opencode/state:/home/openchamber/.local/state/opencode + - ./data/opencode/config:/home/openchamber/.config/opencode + - ./data/ssh:/home/openchamber/.ssh + - ./workspaces:/home/openchamber/workspaces + #environment: + # UI_PASSWORD: your_secure_password_here # Uncomment to set UI password + # CF_TUNNEL: true # Enable Cloudflare Tunnel (true/qr/password) + # OH_MY_OPENCODE: true # enable oh-my-opencode + # OPENCODE_HOST: http://172.17.0.1:4096 # Connect to external OpenCode server + # OPENCODE_SKIP_START: true # skip start opencode restart: unless-stopped diff --git a/scripts/docker-entrypoint.sh b/scripts/docker-entrypoint.sh index e7521526..f8a3b90f 100644 --- a/scripts/docker-entrypoint.sh +++ b/scripts/docker-entrypoint.sh @@ -1,13 +1,7 @@ #!/usr/bin/env sh set -eu -if [ -z "${HOME:-}" ]; then - HOME="$(getent passwd "$(id -u)" | cut -d: -f6 2>/dev/null || true)" -fi - -if [ -z "${HOME:-}" ]; then - HOME="/home/bun" -fi +HOME="/home/openchamber" OPENCODE_CONFIG_DIR="${OPENCODE_CONFIG_DIR:-${HOME}/.config/opencode}" export OPENCODE_CONFIG_DIR @@ -42,7 +36,31 @@ fi echo "[entrypoint] SSH public key:" cat "${SSH_PUBLIC_KEY_PATH}" -OMO_INSTALL_ARGS="--no-tui --claude=no --openai=no --gemini=no --copilot=no --opencode-zen=no --zai-coding-plan=no --kimi-for-coding=no --skip-auth" +# Handle UI_PASSWORD environment variable +OPENCHAMBER_ARGS="" + +if [ -n "${UI_PASSWORD:-}" ]; then + echo "[entrypoint] UI password set, enabling authentication" + OPENCHAMBER_ARGS="${OPENCHAMBER_ARGS} --ui-password ${UI_PASSWORD}" +fi + +# Handle Cloudflare Tunnel (CF_TUNNEL: true/qr/password/full) +if [ -n "${CF_TUNNEL:-}" ] && [ "${CF_TUNNEL:-false}" != "false" ]; then + echo "[entrypoint] Cloudflare Tunnel enabled (${CF_TUNNEL})" + OPENCHAMBER_ARGS="${OPENCHAMBER_ARGS} --try-cf-tunnel" + + case "${CF_TUNNEL}" in + "qr") + OPENCHAMBER_ARGS="${OPENCHAMBER_ARGS} --tunnel-qr" + ;; + esac + + case "${CF_TUNNEL}" in + "password") + OPENCHAMBER_ARGS="${OPENCHAMBER_ARGS} --tunnel-password-url" + ;; + esac +fi if [ "${OH_MY_OPENCODE:-false}" = "true" ]; then @@ -51,6 +69,8 @@ if [ "${OH_MY_OPENCODE:-false}" = "true" ]; then OMO_CONFIG_FILE="${OPENCODE_CONFIG_DIR}/oh-my-opencode.json" + OMO_INSTALL_ARGS="--no-tui --claude=no --openai=no --gemini=no --copilot=no --opencode-zen=no --zai-coding-plan=no --kimi-for-coding=no --skip-auth" + if [ ! -f "${OMO_CONFIG_FILE}" ]; then echo "[entrypoint] oh-my-opencode installing..." oh-my-opencode install ${OMO_INSTALL_ARGS} @@ -63,4 +83,4 @@ if [ "$#" -gt 0 ]; then exec "$@" fi -exec bun packages/web/server/index.js --port "${OPENCHAMBER_PORT:-3000}" +exec bun packages/web/bin/cli.js ${OPENCHAMBER_ARGS}