diff --git a/.dockerignore b/.dockerignore index 4b25f4d0..3ba6be7f 100644 --- a/.dockerignore +++ b/.dockerignore @@ -18,3 +18,9 @@ yarn-error.log* pnpm-debug.log* .env .env.* +.opencode +data +workspaces +packages/desktop/src-tauri +packages/desktop/target +packages/intellij diff --git a/.gitignore b/.gitignore index e02d955e..0565d35a 100644 --- a/.gitignore +++ b/.gitignore @@ -51,3 +51,8 @@ packages/intellij/ # OS Thumbs.db + +# Local runtime state (docker/dev) +data/ +workspaces/ +*.pid diff --git a/Dockerfile b/Dockerfile index d7dc8782..523a32fd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,7 @@ # syntax=docker/dockerfile:1 -FROM archlinux:latest AS base +FROM oven/bun:1 AS base WORKDIR /app -# Install build dependencies in base stage -RUN pacman -Sy --noconfirm --needed bun && \ - pacman -Scc --noconfirm - FROM base AS deps WORKDIR /app COPY package.json bun.lock ./ @@ -20,15 +16,26 @@ WORKDIR /app COPY . . RUN bun run build:web -FROM base AS runtime +FROM oven/bun:1 AS runtime +WORKDIR /home/openchamber -RUN pacman -Sy --noconfirm --needed base-devel python openssh cloudflared git nodejs npm less && \ - pacman -Scc --noconfirm +RUN apt-get update && apt-get install -y --no-install-recommends \ + bash \ + ca-certificates \ + git \ + less \ + nodejs \ + npm \ + openssh-client \ + python3 \ + && rm -rf /var/lib/apt/lists/* + +COPY --from=cloudflare/cloudflared:latest /usr/local/bin/cloudflared /usr/local/bin/cloudflared ENV NODE_ENV=production # Create openchamber user -RUN useradd -m -s /bin/bash openchamber +RUN useradd -m -s /bin/bash openchamber && mkdir -p /home/openchamber && chown -R openchamber:openchamber /home/openchamber # Switch to openchamber user USER openchamber @@ -40,7 +47,6 @@ RUN npm config set prefix /home/openchamber/.npm-global && mkdir -p /home/opench mkdir -p /home/openchamber/.local /home/openchamber/.config /home/openchamber/.ssh && \ npm install -g opencode-ai -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 @@ -48,8 +54,8 @@ COPY --from=builder /app/packages/web/package.json ./packages/web/package.json COPY --from=builder /app/packages/web/bin ./packages/web/bin COPY --from=builder /app/packages/web/server ./packages/web/server COPY --from=builder /app/packages/web/dist ./packages/web/dist -COPY --chmod=755 scripts/docker-entrypoint.sh /app/openchamber-entrypoint.sh +COPY scripts/docker-entrypoint.sh /home/openchamber/openchamber-entrypoint.sh EXPOSE 3000 -ENTRYPOINT ["/app/openchamber-entrypoint.sh"] +ENTRYPOINT ["sh", "/home/openchamber/openchamber-entrypoint.sh"] diff --git a/README.md b/README.md index 8da5417a..7e44d96a 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,7 @@ _requires Node.js 20+_ ```bash curl -fsSL https://raw.githubusercontent.com/btriapitsyn/openchamber/main/scripts/install.sh | bash -openchamber --ui-password be-creative-here --daemon +openchamber --ui-password be-creative-here ```
@@ -153,27 +153,31 @@ environment: UI_PASSWORD: your_secure_password ``` -**Cloudflare Tunnel:** +**Cloudflare Tunnel (optional):** ```yaml environment: - CF_TUNNEL: "true" # Options: true, qr, password + OPENCHAMBER_TUNNEL_MODE: quick # quick | managed-remote | managed-local + OPENCHAMBER_TUNNEL_PROVIDER: cloudflare ``` -| Value | Description | -| ---------- | ------------------------------- | -| `true` | Enable tunnel only | -| `qr` | Enable tunnel + QR code | -| `password` | Enable tunnel + password in URL | +For `managed-remote` mode, provide: -### Managed Cloudflare Tunnel (persistent hostname) +```yaml +environment: + OPENCHAMBER_TUNNEL_MODE: managed-remote + OPENCHAMBER_TUNNEL_HOSTNAME: app.example.com + OPENCHAMBER_TUNNEL_TOKEN: +``` -OpenChamber also supports managed-remote mode for more reliable long-lived access with your Cloudflare account and custom hostname. +For `managed-local` mode, optionally provide: -- Configure it in-app at **Settings -> OpenChamber -> Tunnel** and switch mode to **Managed Remote Tunnel**. -- Managed-remote tunnels require a domain in your Cloudflare account. -- Cloudflare setup guide: https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/get-started/create-remote-tunnel/ -- Managed-local mode uses your local cloudflared config, for example: - - `openchamber tunnel start --provider cloudflare --mode managed-local --config ~/.cloudflared/config.yml` +```yaml +environment: + OPENCHAMBER_TUNNEL_MODE: managed-local + OPENCHAMBER_TUNNEL_CONFIG: /home/openchamber/.cloudflared/config.yml +``` + +Managed-local path note: `OPENCHAMBER_TUNNEL_CONFIG` must point to a path inside the container user home (`/home/openchamber/...`). If your Cloudflare config references a credentials JSON file, that file path must also be accessible inside the container (mount with `volumes`). ### Tunnel behavior notes @@ -237,7 +241,7 @@ chown -R 1000:1000 data/
Web / PWA -- Cloudflare tunnel with Quick and Named modes, secure one-time connect links, and QR onboarding +- Cloudflare tunnel with quick, managed-remote, and managed-local modes, secure one-time connect links, and QR onboarding - Mobile-first: optimized chat controls, keyboard-safe layouts, drag-to-reorder projects - Background notifications and cross-tab session tracking - Self-update + restart flow that keeps your server settings intact diff --git a/docker-compose.yml b/docker-compose.yml index 9972e7d1..1877b14c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -17,7 +17,11 @@ services: - ./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) + # OPENCHAMBER_TUNNEL_PROVIDER: cloudflare + # OPENCHAMBER_TUNNEL_MODE: quick # quick | managed-remote | managed-local + # OPENCHAMBER_TUNNEL_HOSTNAME: app.example.com # required for managed-remote + # OPENCHAMBER_TUNNEL_TOKEN: your_cloudflare_token # required for managed-remote + # OPENCHAMBER_TUNNEL_CONFIG: /home/openchamber/.cloudflared/config.yml # optional for managed-local # 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 diff --git a/packages/web/README.md b/packages/web/README.md index 586cb51d..94031174 100644 --- a/packages/web/README.md +++ b/packages/web/README.md @@ -50,9 +50,29 @@ openchamber update # Update to latest version ```yaml environment: UI_PASSWORD: your_secure_password - CF_TUNNEL: "true" # Options: true, qr, password + OPENCHAMBER_TUNNEL_MODE: quick # quick | managed-remote | managed-local + OPENCHAMBER_TUNNEL_PROVIDER: cloudflare ``` +For `managed-remote` mode, also set: + +```yaml +environment: + OPENCHAMBER_TUNNEL_MODE: managed-remote + OPENCHAMBER_TUNNEL_HOSTNAME: app.example.com + OPENCHAMBER_TUNNEL_TOKEN: +``` + +For `managed-local` mode, you can set: + +```yaml +environment: + OPENCHAMBER_TUNNEL_MODE: managed-local + OPENCHAMBER_TUNNEL_CONFIG: /home/openchamber/.cloudflared/config.yml +``` + +Managed-local path note: `OPENCHAMBER_TUNNEL_CONFIG` must use a container path under `/home/openchamber/...`. If the config file references `credentials-file`, ensure that JSON path is also mounted and reachable inside the container. + **Data directory:** mount `data/` for persistent storage. Ensure permissions: ```bash mkdir -p data/openchamber data/opencode/share data/opencode/config data/ssh @@ -65,7 +85,7 @@ chown -R 1000:1000 data/ Background & daemon mode ```bash -openchamber --daemon # Run in background +openchamber # Runs in background by default openchamber stop # Stop background server ``` @@ -79,7 +99,7 @@ openchamber stop # Stop background server - **Self-update** - update and restart from the UI, server settings stay intact - **Cross-tab tracking** - session activity stays in sync across browser tabs -- Cloudflare tunnel access with Quick, managed-remote, and managed-local modes +- Cloudflare tunnel access with quick, managed-remote, and managed-local modes - One-scan onboarding with tunnel QR + password URL helpers - Mobile-first experience: optimized chat controls, keyboard-safe layouts, and attachment-friendly UI - Background notifications plus reliable cross-tab session activity tracking diff --git a/scripts/docker-entrypoint.sh b/scripts/docker-entrypoint.sh index 3b6bfa7c..19d54a38 100644 --- a/scripts/docker-entrypoint.sh +++ b/scripts/docker-entrypoint.sh @@ -36,30 +36,9 @@ fi echo "[entrypoint] SSH public key:" cat "${SSH_PUBLIC_KEY_PATH}" -# Handle UI_PASSWORD environment variable -OPENCHAMBER_ARGS="" - +# Handle UI password environment variable 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 @@ -82,5 +61,10 @@ if [ "$#" -gt 0 ]; then exec "$@" fi -bun packages/web/bin/cli.js ${OPENCHAMBER_ARGS} +set -- bun packages/web/bin/cli.js +if [ -n "${UI_PASSWORD:-}" ]; then + set -- "$@" --ui-password "$UI_PASSWORD" +fi +"$@" + bun packages/web/bin/cli.js logs