1b97d98155
Install uv from GitHub releases (~23MB). Users can install Python with 'uv python install 3.12' — persists across restarts via devbox-uv volume. Eliminates need for a separate Python image variant.
372 lines
13 KiB
Markdown
372 lines
13 KiB
Markdown
# opencode-devbox
|
||
|
||
Portable AI developer environment in a Docker container. Run [opencode](https://opencode.ai) on any Docker-capable machine with configurable LLM providers, dev tools, and host filesystem access.
|
||
|
||
## Why?
|
||
|
||
The official `ghcr.io/anomalyco/opencode` image (now archived) was Alpine-based and minimal — no git, no dev tools, broken PTY support due to musl/glibc incompatibility. This project provides a **Debian-based, production-ready** alternative using the current v1.x release.
|
||
|
||
## Quick Start
|
||
|
||
```bash
|
||
# Clone
|
||
git clone ssh://gitea.jordbo.se:2222/joakimp/opencode-devbox.git
|
||
cd opencode-devbox
|
||
|
||
# Configure
|
||
cp .env.example .env
|
||
# Edit .env with your provider, API key, workspace path, git config
|
||
|
||
# Install git hooks (secret scanning)
|
||
brew install gitleaks # macOS / Linuxbrew
|
||
./setup-hooks.sh
|
||
|
||
# Build and run
|
||
docker compose run --rm devbox
|
||
```
|
||
|
||
## Features
|
||
|
||
- **Debian bookworm** base — glibc, full PTY/terminal support
|
||
- **Configurable providers** — Anthropic, OpenAI, AWS Bedrock via env vars
|
||
- **Host filesystem access** — bind mount any directory as `/workspace`
|
||
- **SSH key forwarding** — git push/pull to private repos
|
||
- **MCP server support** — Node.js included for `npx`-based MCP servers
|
||
- **Non-root user** — runs as `developer` with UID auto-matched to workspace owner (sudo available)
|
||
- **Python via uv** — `uv` package manager included; install Python on demand with `uv python install`
|
||
- **Optional runtimes** — Python (apt), Go via build args (Node.js always included — required for opencode v1.x)
|
||
- **Multi-agent orchestration** — optional [oh-my-opencode-slim](https://github.com/alvinunreal/oh-my-opencode-slim) integration via build arg
|
||
- **AWS CLI v2** — built-in SSO/Bedrock authentication with headless device-code flow
|
||
- **Multi-arch** — amd64 and arm64
|
||
|
||
## Usage
|
||
|
||
### Connecting to the container
|
||
|
||
From your laptop, SSH into the remote server where Docker is running, then start the container:
|
||
|
||
```bash
|
||
# 1. SSH into the remote server
|
||
ssh user@remote-server
|
||
|
||
# 2. Navigate to the project
|
||
cd opencode-devbox
|
||
|
||
# 3. Start the container with an interactive shell
|
||
docker compose run --rm devbox bash
|
||
|
||
# You're now inside the container — run commands here
|
||
aws sso login --sso-session <your-sso-session> --use-device-code
|
||
opencode
|
||
```
|
||
|
||
### Running modes
|
||
|
||
**Interactive shell** — enter the container, run multiple commands:
|
||
```bash
|
||
docker compose run --rm devbox bash
|
||
```
|
||
|
||
**Direct to opencode** — skips the shell, launches opencode immediately:
|
||
```bash
|
||
docker compose run --rm devbox
|
||
```
|
||
|
||
**Background container** — keep it running, attach when needed:
|
||
```bash
|
||
# Start in background
|
||
docker compose up -d
|
||
|
||
# Attach a shell to the running container
|
||
docker compose exec -u developer devbox bash
|
||
|
||
# Or run a single command inside it
|
||
docker compose exec -u developer devbox aws --version
|
||
```
|
||
|
||
> `run` creates a new container (cleaned up with `--rm`). `exec` attaches to an already running one.
|
||
|
||
## Configuration
|
||
|
||
### Environment Variables
|
||
|
||
| Variable | Description | Default |
|
||
|---|---|---|
|
||
| `OPENCODE_PROVIDER` | LLM provider (`anthropic`, `openai`, `amazon-bedrock`) | `anthropic` |
|
||
| `OPENCODE_MODEL` | Model override | Provider default |
|
||
| `ANTHROPIC_API_KEY` | Anthropic API key | — |
|
||
| `OPENAI_API_KEY` | OpenAI API key | — |
|
||
| `AWS_REGION` | AWS region for Bedrock | `us-east-1` |
|
||
| `AWS_PROFILE` | AWS SSO profile name | `default` |
|
||
| `GIT_USER_NAME` | Git commit author name | — |
|
||
| `GIT_USER_EMAIL` | Git commit author email | — |
|
||
| `WORKSPACE_PATH` | Host path to mount | `.` |
|
||
| `SSH_KEY_PATH` | Host SSH key directory | `~/.ssh` |
|
||
| `USER_UID` | Override container user UID | Auto-detect from `/workspace` |
|
||
| `USER_GID` | Override container user GID | Auto-detect from `/workspace` |
|
||
| `ENABLE_OMOS` | Enable oh-my-opencode-slim multi-agent orchestration | `false` |
|
||
| `OMOS_TMUX` | Enable tmux pane integration for OMOS | `false` |
|
||
| `OMOS_SKILLS` | Install OMOS recommended skills on first run | `true` |
|
||
| `OMOS_RESET` | Force regenerate OMOS config on next start | `false` |
|
||
|
||
### Custom opencode config
|
||
|
||
For full control over opencode settings (MCP servers, custom models, oh-my-opencode-slim agents, etc.), mount the entire config directory from the host:
|
||
|
||
```yaml
|
||
volumes:
|
||
- ~/.config/opencode:/home/developer/.config/opencode
|
||
```
|
||
|
||
This persists all configuration changes across container restarts, including `opencode.json`, `oh-my-opencode-slim.json`, and skills. When an existing `opencode.json` is found, the `OPENCODE_PROVIDER` auto-config is skipped.
|
||
|
||
### Custom skills
|
||
|
||
Mount agent skills from the host:
|
||
|
||
```yaml
|
||
volumes:
|
||
- ~/.agents/skills:/home/developer/.agents/skills:ro
|
||
```
|
||
|
||
### Neovim configuration
|
||
|
||
The image includes neovim 0.12 with `EDITOR=nvim` set by default. To use your own neovim config (and have plugins auto-install via lazy.nvim on first start), mount it from the host:
|
||
|
||
```yaml
|
||
volumes:
|
||
- ~/.config/nvim:/home/developer/.config/nvim:ro
|
||
```
|
||
|
||
### Python development with uv
|
||
|
||
The image includes [uv](https://docs.astral.sh/uv/), a fast Python package manager that replaces pip, venv, and pyenv. Python is not pre-installed but can be installed on demand:
|
||
|
||
```bash
|
||
# Install Python (persists across restarts with devbox-uv volume)
|
||
uv python install 3.12
|
||
|
||
# Create a virtual environment and install dependencies
|
||
uv venv
|
||
uv pip install -r requirements.txt
|
||
|
||
# Or use uv's project workflow (reads pyproject.toml)
|
||
uv sync
|
||
|
||
# Run a Python script
|
||
uv run python script.py
|
||
|
||
# Install standalone Python tools
|
||
uvx ruff check .
|
||
```
|
||
|
||
Python installations are stored in `~/.local/share/uv/`. To persist them across container restarts, add the `devbox-uv` named volume to your `docker-compose.yml`:
|
||
|
||
```yaml
|
||
volumes:
|
||
- devbox-uv:/home/developer/.local/share/uv
|
||
|
||
volumes:
|
||
devbox-uv:
|
||
```
|
||
|
||
Project virtual environments (`.venv`) are stored in your workspace directory and persist automatically via the `/workspace` bind mount.
|
||
|
||
### Rebuilding the Image
|
||
|
||
`docker compose run` and `docker compose up` use the existing image — they **do not rebuild** when you change the Dockerfile or build args (e.g. updating `OPENCODE_VERSION`). Rebuild explicitly:
|
||
|
||
```bash
|
||
# Rebuild then run
|
||
docker compose build
|
||
docker compose run --rm devbox
|
||
|
||
# Or rebuild and run in one step
|
||
docker compose run --rm --build devbox
|
||
```
|
||
|
||
### Build Args
|
||
|
||
Enable optional language runtimes or pin a specific opencode version:
|
||
|
||
```bash
|
||
docker compose build --build-arg INSTALL_PYTHON=true --build-arg INSTALL_GO=true
|
||
docker compose build --build-arg OPENCODE_VERSION=1.5.0
|
||
```
|
||
|
||
| Arg | Default | Description |
|
||
|---|---|---|
|
||
| `INSTALL_PYTHON` | `false` | Python 3 + pip + venv |
|
||
| `INSTALL_GO` | `false` | Go toolchain |
|
||
| `INSTALL_OMOS` | `false` | [oh-my-opencode-slim](https://github.com/alvinunreal/oh-my-opencode-slim) multi-agent orchestration (installs Bun and plugin) |
|
||
| `OMOS_VERSION` | `latest` | Pin a specific oh-my-opencode-slim version |
|
||
|
||
## oh-my-opencode-slim (Multi-Agent Orchestration)
|
||
|
||
[oh-my-opencode-slim](https://github.com/alvinunreal/oh-my-opencode-slim) adds a multi-agent layer on top of opencode — an Orchestrator delegates tasks to specialized agents (Explorer, Oracle, Librarian, Designer, Fixer), each configurable with different models and providers.
|
||
|
||
### Setup
|
||
|
||
A pre-built OMOS image is available on Docker Hub as `joakimp/opencode-devbox:latest-omos`. Alternatively, build from source:
|
||
|
||
**1. Build the image with OMOS support:**
|
||
|
||
```bash
|
||
docker compose build --build-arg INSTALL_OMOS=true
|
||
```
|
||
|
||
This installs Bun and the oh-my-opencode-slim package into the image.
|
||
|
||
**2. Enable in `.env`:**
|
||
|
||
```bash
|
||
ENABLE_OMOS=true
|
||
```
|
||
|
||
**3. Run as normal:**
|
||
|
||
```bash
|
||
docker compose run --rm devbox
|
||
```
|
||
|
||
On first start, the entrypoint runs the oh-my-opencode-slim installer in non-interactive mode. It generates agent configuration at `~/.config/opencode/oh-my-opencode-slim.json` inside the container. The default preset uses OpenAI models — edit the generated config or mount your own to customize.
|
||
|
||
### OMOS Environment Variables
|
||
|
||
| Variable | Default | Description |
|
||
|---|---|---|
|
||
| `ENABLE_OMOS` | `false` | Activate oh-my-opencode-slim on container start |
|
||
| `OMOS_TMUX` | `false` | Enable tmux pane integration (tmux is included in the base image) |
|
||
| `OMOS_SKILLS` | `true` | Install recommended skills (simplify, agent-browser, cartography) |
|
||
| `OMOS_RESET` | `false` | Force regenerate config on next start (backs up existing config) |
|
||
|
||
### Custom Configuration
|
||
|
||
If you mount the opencode config directory (see Custom opencode config above), the `oh-my-opencode-slim.json` file is included and persists across restarts. Edit it directly to control which models power each agent, fallback chains, council setup, and more.
|
||
|
||
See the [oh-my-opencode-slim configuration docs](https://github.com/alvinunreal/oh-my-opencode-slim/blob/master/docs/configuration.md) for the full reference.
|
||
|
||
### Verifying Agents
|
||
|
||
After starting opencode with OMOS enabled, run inside the opencode session:
|
||
|
||
```
|
||
ping all agents
|
||
```
|
||
|
||
All six agents should respond if your provider authentication is working.
|
||
|
||
## AWS Bedrock Authentication
|
||
|
||
When using AWS Bedrock as your LLM provider, you need:
|
||
|
||
### 1. AWS config on the host
|
||
|
||
The container needs access to your `~/.aws/config` with SSO session configuration. If you already have this on another machine, copy it:
|
||
|
||
```bash
|
||
scp -r user@other-machine:~/.aws ~/.aws
|
||
```
|
||
|
||
Or configure from scratch on the host:
|
||
|
||
```bash
|
||
aws configure sso
|
||
```
|
||
|
||
### 2. Mount `~/.aws` into the container
|
||
|
||
Uncomment the AWS volume mount in `docker-compose.yml`:
|
||
|
||
```yaml
|
||
- ~/.aws:/home/developer/.aws
|
||
```
|
||
|
||
Note: do **not** use `:ro` — SSO writes token cache files to this directory.
|
||
|
||
### 3. Authenticate inside the container
|
||
|
||
Since the container runs headless (no browser), use the device-code flow:
|
||
|
||
```bash
|
||
# Start the container
|
||
docker compose up -d
|
||
docker compose exec -u developer devbox bash
|
||
|
||
# Authenticate — prints a URL and code you open in your local browser
|
||
aws sso login --sso-session <your-sso-session> --use-device-code
|
||
|
||
# Once approved in the browser, start opencode
|
||
opencode
|
||
```
|
||
|
||
The `--use-device-code` flag outputs a URL and short code instead of trying to open a browser. Copy the URL into any browser (on your laptop, phone, etc.), enter the code, and complete the 2FA flow. The CLI in the container picks up the session automatically.
|
||
|
||
SSO sessions typically last 8–12 hours before requiring re-authentication. Since `~/.aws` is mounted from the host, tokens persist across container restarts.
|
||
|
||
## Secret Scanning
|
||
|
||
A [gitleaks](https://github.com/gitleaks/gitleaks) pre-commit hook prevents accidentally committing API keys, passwords, or other secrets.
|
||
|
||
### Setup
|
||
|
||
```bash
|
||
# macOS / Linuxbrew
|
||
brew install gitleaks
|
||
|
||
# Debian/Ubuntu (download binary)
|
||
curl -sSL https://github.com/gitleaks/gitleaks/releases/latest/download/gitleaks_$(uname -s)_$(uname -m).tar.gz | sudo tar -xz -C /usr/local/bin gitleaks
|
||
```
|
||
|
||
The hook runs automatically on every `git commit`. If gitleaks isn't installed, the hook prints a warning and allows the commit (no hard dependency on collaborators).
|
||
|
||
### Bypass
|
||
|
||
For legitimate cases (test data, documentation with example keys):
|
||
|
||
```bash
|
||
git commit --no-verify -m "Add test fixtures"
|
||
```
|
||
|
||
### Configuration
|
||
|
||
Allowlisted paths and rules are in `.gitleaks.toml`. The defaults extend gitleaks' built-in rules and allow `.env.example` and documentation files.
|
||
|
||
## Architecture
|
||
|
||
```
|
||
Host Machine
|
||
├── ~/projects/my-app ──bind mount──▶ /workspace (container)
|
||
├── ~/.ssh ──bind mount──▶ /home/developer/.ssh (ro)
|
||
├── ~/.aws ──bind mount──▶ /home/developer/.aws (Bedrock SSO)
|
||
└── .env ──env vars───▶ provider config + API keys
|
||
|
||
Container (Debian bookworm)
|
||
├── opencode binary
|
||
├── oh-my-opencode-slim (optional — multi-agent orchestration plugin, includes Bun)
|
||
├── AWS CLI v2 (SSO + Bedrock auth)
|
||
├── neovim 0.12, tmux, htop, bat, eza, zoxide, uv, make
|
||
├── git, ssh, ripgrep, fd, fzf, jq, curl, tree
|
||
├── Node.js (for MCP servers)
|
||
├── Bun (optional — included with oh-my-opencode-slim)
|
||
├── entrypoint.sh (UID adjustment, git config, provider setup)
|
||
└── /workspace ← your code lives here
|
||
```
|
||
|
||
### Data persistence
|
||
|
||
| Path in container | Source | Survives `--rm`? | Contains |
|
||
|---|---|---|---|
|
||
| `/workspace` | Host bind mount | ✅ Yes | Your project files |
|
||
| `/home/developer/.ssh` | Host bind mount (ro) | ✅ Yes | SSH keys |
|
||
| `/home/developer/.aws` | Host bind mount (if configured) | ✅ Yes | AWS credentials/SSO cache |
|
||
| `/home/developer/.local/share/opencode` | Named volume `devbox-data` | ✅ Yes | Session history, memory |
|
||
| `/home/developer/.local/share/uv` | Named volume `devbox-uv` (if configured) | ✅ Yes | Python installs, uv tool installs |
|
||
| `/home/developer/.config/opencode` | Host bind mount (if configured) | ✅ Yes | opencode.json, oh-my-opencode-slim.json, skills |
|
||
|
||
**opencode config** (`opencode.json`) is auto-generated from `OPENCODE_PROVIDER` on each start. It sets provider and model only — no MCP servers. To persist config changes and use custom settings, mount the config directory from the host (see Custom opencode config above).
|
||
|
||
## License
|
||
|
||
MIT
|