# 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 # one-time ./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` (UID 1000) with sudo - **Optional runtimes** — Python, Go via build args (Node.js always included — required for opencode v1.x) - **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 --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 devbox bash # Or run a single command inside it docker compose exec 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` | | `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` | ### Custom opencode config Mount your own `opencode.json` for full control (MCP servers, custom models, etc.): ```yaml volumes: - ./my-opencode.json:/home/developer/.config/opencode/opencode.json:ro ``` ### Custom skills Mount your host's opencode skills into the container: ```yaml volumes: - ~/.config/opencode/skills:/home/developer/.config/opencode/skills:ro - ~/.agents/skills:/home/developer/.agents/skills:ro ``` ### 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 | ## AWS Bedrock Authentication When using AWS Bedrock as your LLM provider, you need to authenticate via AWS SSO from inside the container. Since the container runs headless (no browser), use the device-code flow: ```bash # Start the container interactively docker compose run --rm devbox bash # Authenticate — prints a URL and code you open in your local browser aws sso login --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. ## Secret Scanning A [gitleaks](https://github.com/gitleaks/gitleaks) pre-commit hook prevents accidentally committing API keys, passwords, or other secrets. ### Setup ```bash brew install gitleaks # one-time install ./setup-hooks.sh # installs the pre-commit hook ``` 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) └── .env ──env vars───▶ provider config + API keys Container (Debian bookworm) ├── opencode binary ├── AWS CLI v2 (SSO + Bedrock auth) ├── git, ssh, ripgrep, fd, jq, curl, fzf ├── Node.js (for MCP servers) ├── entrypoint.sh (SSH perms, 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/.local/share/opencode` | Named volume `devbox-data` | ✅ Yes | Session history, memory | | `/home/developer/.config/opencode/opencode.json` | Generated by entrypoint | ❌ No | Provider/model config | | `/home/developer/.aws` | Not mounted by default | ❌ No | AWS SSO tokens | **opencode config** (`opencode.json`) is auto-generated from `OPENCODE_PROVIDER` on each start. It sets provider and model only — no MCP servers. To use MCP servers or custom settings, mount your own config file (see Custom opencode config above). To persist AWS SSO sessions across restarts, uncomment the `~/.aws` volume mount in `docker-compose.yml`. ## License MIT