Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Dependencies
node_modules/
**/node_modules/
# Keep bun.lock for Docker builds
# *.lock

# Build outputs (will be generated in container)
dist/
client/dist/

# State and runtime data
.openui/
.env
.env.local

# IDE and editor files
.vscode/
.idea/
*.swp
*.swo
*~
.DS_Store
*.sublime-*

# Git
.git/
.gitignore

# CI/CD
.github/
.gitlab-ci.yml

# Documentation (keep README.md)
*.md
!README.md

# Test files
**/*.test.ts
**/*.test.js
**/__tests__/
**/coverage/

# Logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Temporary files
*.tmp
.cache/

# Claude Code plugin (installed at runtime)
claude-code-plugin/

# Docker files (don't include in image)
Dockerfile*
docker-compose*.yml
.dockerignore

# Plans and development files
.claude/
plans/
80 changes: 80 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# ============================================
# OpenUI Docker Configuration
# ============================================

# Server Configuration
NODE_ENV=production
PORT=6968
OPENUI_QUIET=1

# ============================================
# Project Directory (HYBRID MODE ONLY)
# ============================================
# Absolute path to your project directory on host
# This path must match both host and container mount points
# PROJECT_DIR=/path/to/your/projects

# Example: PROJECT_DIR=/home/user/code
# Example: PROJECT_DIR=$(pwd)/projects

# ============================================
# Git Configuration
# ============================================
# Used for commits made by AI agents
GIT_AUTHOR_NAME=Your Name
GIT_AUTHOR_EMAIL=your.email@example.com

# ============================================
# API Keys (OPTIONAL)
# ============================================
# Only required if your AI tools need API access
# ANTHROPIC_API_KEY=your_anthropic_api_key_here
# GITHUB_TOKEN=your_github_token_here
# LINEAR_API_KEY=your_linear_api_key_here

# ============================================
# Deployment Mode
# ============================================
# Options: full | hybrid
DEPLOYMENT_MODE=full

# ============================================
# Claude Code Configuration (FULL MODE ONLY)
# ============================================
# Claude Code will be auto-installed in container
# But you can specify a version or custom install path
# CLAUDE_VERSION=latest
# CLAUDE_INSTALL_DIR=/usr/local/bin

# ============================================
# Resource Limits (FULL MODE ONLY)
# ============================================
# Adjust based on your host's available resources
MAX_CPUS=4
MAX_MEMORY=4G

# ============================================
# Hybrid Mode Agent Execution (HYBRID MODE ONLY)
# ============================================
# How should agents be spawned in hybrid mode?
# Options: ssh | docker-cli | named-pipe
# HYBRID_AGENT_SPAWN_METHOD=ssh

# SSH configuration for ssh method
# SSH_HOST=localhost
# SSH_USER=root
# SSH_PORT=22

# ============================================
# Volume Configuration
# ============================================
# Where to persist OpenUI state
STATE_VOLUME_NAME=openui-state
PLUGIN_VOLUME_NAME=openui-plugin

# ============================================
# Development Settings (OPTIONAL)
# ============================================
# Enable for debugging
# DEBUG=1
# LOG_LEVEL=verbose
88 changes: 88 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Stage 1: Build frontend (Alpine is fine for building)
FROM oven/bun:1.3-alpine AS builder

WORKDIR /app

# Install build dependencies
RUN apk add --no-cache \
git \
python3 \
make \
g++

# Copy package files
COPY package.json bun.lock ./
COPY client/package.json client/bun.lock* ./client/

# Install dependencies
RUN bun install
WORKDIR /app/client
RUN bun install
WORKDIR /app

# Copy source code
COPY . .

# Build frontend
WORKDIR /app/client
RUN bun run build

# Stage 2: Production image (Debian for glibc compatibility with bun-pty)
FROM oven/bun:1.3-debian

WORKDIR /app

# Install runtime dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
bash \
git \
python3 \
curl \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*

# Install Node.js using NodeSource (more reliable than Debian npm)
RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && \
apt-get install -y nodejs && \
rm -rf /var/lib/apt/lists/*

# Install AI Agent CLI tools globally via npm
RUN npm install -g @anthropic-ai/claude-code opencode-ai

# Install Ralph (autonomous Claude Code loop)
RUN git clone --depth 1 https://github.com/frankbria/ralph-claude-code.git /opt/ralph && \
chmod +x /opt/ralph/install.sh && \
cd /opt/ralph && ./install.sh || true && \
ln -sf /opt/ralph/ralph /usr/local/bin/ralph && \
ln -sf /opt/ralph/ralph-setup /usr/local/bin/ralph-setup

# Copy backend dependencies
COPY package.json bun.lock ./
RUN bun install --production

# Copy built frontend from builder
COPY --from=builder /app/client/dist ./client/dist

# Copy server and bin directories
COPY server ./server
COPY bin ./bin

# Create directories for runtime
RUN mkdir -p /app/.openui && \
chmod 755 /app/bin/openui.ts

# Expose ports
# 6968: Backend server + WebSocket
EXPOSE 6968

# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:6968/api/config || exit 1

# Set environment defaults
ENV NODE_ENV=production \
PORT=6968 \
OPENUI_QUIET=1

# Run the server
CMD ["bun", "run", "/app/server/index.ts"]
73 changes: 73 additions & 0 deletions docker-compose.full.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
services:
openui:
build:
context: .
dockerfile: Dockerfile
container_name: openui-full
restart: unless-stopped

# Port mappings
ports:
- "6968:6968" # Backend + WebSocket

# Project directory mounts
# Mount your projects here so agents can work on them
volumes:
# State persistence
- openui-state:/root/.openui

# Plugin directory
- openui-plugin:/root/.openui/claude-code-plugin

# Project directories - MOUNT YOUR PROJECTS HERE
# Examples:
- ./projects:/projects

# Or mount specific projects:
# - /path/to/project1:/projects/project1
# - /path/to/project2:/projects/project2

# Git credentials for cloning
- ${HOME}/.gitconfig:/root/.gitconfig:ro
- ${HOME}/.ssh:/root/.ssh:ro

# Environment variables
environment:
- NODE_ENV=production
- PORT=6968
- LAUNCH_CWD=/projects
- OPENUI_QUIET=1

# Git configuration
- GIT_AUTHOR_NAME=${GIT_AUTHOR_NAME:-OpenUI}
- GIT_AUTHOR_EMAIL=${GIT_AUTHOR_EMAIL:-openui@local}

# Claude Code API key (if using Claude API)
- ${ANTHROPIC_API_KEY:+ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}}

# Working directory inside container
working_dir: /app

# Network mode
network_mode: bridge

# Resource limits (optional but recommended)
deploy:
resources:
limits:
cpus: '4'
memory: 4G
reservations:
cpus: '1'
memory: 1G

# Keep container running
stdin_open: true
tty: true

volumes:
# Persist OpenUI state and plugin
openui-state:
driver: local
openui-plugin:
driver: local
68 changes: 68 additions & 0 deletions docker-compose.hybrid.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# HYBRID MODE - OpenUI UI in container, AI agents on host
# For Linux/Ubuntu systems where host networking works correctly.
# NOTE: This mode runs the UI in a container but expects AI tools (claude, opencode, ralph)
# to be installed on the HOST system, not inside the container.

services:
openui:
build:
context: .
dockerfile: Dockerfile
container_name: openui-hybrid
restart: unless-stopped

# NOTE: When using network_mode: host, the ports directive is ignored.
# The container uses the host's network directly, so port 6968 is exposed on localhost.

# Volume mounts for hybrid mode
volumes:
# State persistence
- openui-state:/root/.openui

# Plugin directory (synced with host)
- ${HOME}/.openui/claude-code-plugin:/root/.openui/claude-code-plugin

# Project directories - MUST MATCH HOST PATHS for agents to work correctly
# When agents spawn on the host, they need to see the same paths
- ${PROJECT_DIR:-./projects}:${PROJECT_DIR:-/projects}

# Docker socket for spawning containers/commands on host
- /var/run/docker.sock:/var/run/docker.sock

# Mount host AI tools into container (required for hybrid mode)
# These paths may vary based on your installation method
- /usr/local/bin/claude:/usr/local/bin/host-claude:ro
- /usr/local/bin/opencode:/usr/local/bin/host-opencode:ro
- /usr/local/bin/ralph:/usr/local/bin/host-ralph:ro

# Git credentials
- ${HOME}/.gitconfig:/root/.gitconfig:ro
- ${HOME}/.ssh:/root/.ssh:ro

# Environment variables
environment:
- NODE_ENV=production
- PORT=6968
- LAUNCH_CWD=${PROJECT_DIR:-/projects}
- OPENUI_QUIET=1

# Hybrid mode flag
- OPENUI_HYBRID_MODE=true

# Anthropic API key (required for Claude Code)
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}

# Working directory (must be /app for static file serving)
working_dir: /app

# Network mode: host gives full access to host network
# This works properly on Linux but NOT on macOS/Windows Docker Desktop
network_mode: host

# Keep container running
stdin_open: true
tty: true

volumes:
openui-state:
driver: local