Linux + macOS · Docker-only host

Your cloud dev environment, in containers

A thin host and a compose stack: code-server, opencode v2, openchamber, a browser terminal, Obsidian, T3 Code and local models. One image, opt-in profiles, and cloudflared as the only ingress — the host needs Docker and nothing else.

one image · six services

Quick start

One bootstrap script on the host, then everything else is compose.

first run
cp .env.example .envsudo ./setup.sh --dry-run   # print the plansudo ./setup.sh             # ask, build, upsudo ./setup.sh --tunnel    # + cloudflared routes

Then

Load code.<domain> once the tunnel is up, or work locally on 127.0.0.1:8080. The full walkthrough — cookbook included — lives in the docs.

code-server — VS Code in the browser
opencode v2 — API and web UI
openchamber — a second UI on the same server
ttyd — terminal in the browser
Obsidian streamed to the browser
ollama — local models
cloudflared — the only ingress

What runs

Pick services per run; every one is a compose profile, and nothing auto-starts.

code-server

VS Code in the browser, with the openchamber, ChatGPT and Claude Code extensions installed.

opencode

opencode v2 — one port for the API and the web UI, password-protected out of the box.

openchamber

A second UI on the same opencode server, so both see one set of sessions and auth.

terminal

ttyd — a root shell in the browser. Loopback-only; basic auth when TTYD_CREDENTIALS is set.

obsidian

Obsidian streamed to the browser (Selkies). Vaults live in a named volume; auth is opt-in.

t3code

T3 Code — an agent control surface: drive the stack's coding agents from a web app. Clients pair with a one-time link.

T3 Code is not yet supported — it has not migrated to opencode v2 yet.

ollama

A local model server — CPU everywhere, with an ollama-gpu variant for NVIDIA hosts.

Why it stays small

The old host script installed everything globally. Here, the host installs Docker and stops.

Thin host

Docker is the only host dependency. node, gcloud/aws CLIs, code-server, opencode — all in containers.

Opt-in everything

Every service is a compose profile. setup.sh asks what to run each time and turns the answer into --profile flags.

Loopback by default

Nothing is published. cloudflared joins the compose network as the only ingress, and only starts with --tunnel.

DooD, not DinD

The host socket plus a docker client baked into the image — docker and compose work inside, no nested daemon.

Docker-only hostLinux and macOSMIT licenseObsidianopencode v2T3 CodeOllama