You’ve heard about AI coding assistants like Cursor and GitHub Copilot, but what if you want full control over your infrastructure, custom AI models, and zero vendor lock-in? OpenChamber is a self-hosted AI coding environment that manages OpenCode as its backend. This guide covers deploying OpenChamber with Docker Compose, exposing it securely through Cloudflare Tunnel, and configuring custom AI providers.
This is Part 1 of a two-part series covering infrastructure setup. Part 2 will cover GitLab integration and development workflows.
What you’ll learn: OpenChamber architecture, Docker volume mapping, Cloudflare Tunnel configuration, custom AI provider integration, and critical pitfalls to avoid.
Prerequisites: Linux server with Docker and Docker Compose, domain with Cloudflare DNS, basic Docker knowledge, Cloudflare account with Tunnel access.
Time to complete: 30-45 minutes
Understanding the Architecture
OpenChamber is the frontend UI running as a web server. OpenCode is the AI coding backend that OpenChamber spawns and manages as a child process. OpenCode is not configured through a separate user account—it’s managed entirely through OpenChamber’s container environment.
Process flow:
Browser → Cloudflare Tunnel → OpenChamber (port 3000) → OpenCode (port 42069)
This managed architecture means all configuration happens through Docker volumes and environment variables.
Installation Directory Structure
Use /opt/openchamber as your installation root:
/opt/openchamber/
├── docker-compose.yml
├── data/
│ ├── openchamber/
│ ├── opencode/
│ │ ├── config/
│ │ ├── share/
│ │ └── state/
│ └── ssh/
└── workspaces/
Create the structure:
sudo mkdir -p /opt/openchamber/{data/{openchamber,opencode/{config,share,state},ssh},workspaces}
Critical: Docker Volume Mapping
Understanding host-to-container path mapping is essential. Here’s the configuration:
volumes:
- ./data/openchamber:/home/openchamber/.config/openchamber
- ./data/opencode/share:/home/openchamber/.local/share/opencode
- ./data/opencode/state:/home/openchamber/.local/state/opencode
- ./data/opencode/config:/home/openchamber/.config/opencode
- ./data/ssh:/home/openchamber/.ssh
- ./workspaces:/home/openchamber/workspaces
Critical rule: Always use container paths in configuration files, never host paths. OpenChamber and OpenCode run inside the container and can’t see /opt/openchamber.
Wrong: /opt/openchamber/workspaces/myproject
Correct: /home/openchamber/workspaces/myproject
Docker Compose Configuration
Create /opt/openchamber/docker-compose.yml:
version: '3.8'
services:
openchamber:
image: openchamber/openchamber:latest
container_name: openchamber
restart: unless-stopped
environment:
OPENCHAMBER_HOST: 0.0.0.0
OPENCHAMBER_TUNNEL_PROVIDER: cloudflare
OPENCHAMBER_TUNNEL_MODE: managed-remote
OPENCHAMBER_TUNNEL_HOSTNAME: opencode.yourdomain.com
OPENCHAMBER_TUNNEL_TOKEN:
OPENCHAMBER_TUNNEL_SERVICE: http://openchamber:3000
CUSTOM_GATEWAY_API_KEY:
volumes:
- ./data/openchamber:/home/openchamber/.config/openchamber
- ./data/opencode/share:/home/openchamber/.local/share/opencode
- ./data/opencode/state:/home/openchamber/.local/state/opencode
- ./data/opencode/config:/home/openchamber/.config/opencode
- ./data/ssh:/home/openchamber/.ssh
- ./workspaces:/home/openchamber/workspaces
ports:
- "127.0.0.1:3030:3000"
Cloudflare Tunnel Setup
Cloudflare Tunnel provides secure access without exposing ports directly to the internet.
Step 1: In Cloudflare dashboard, go to Zero Trust → Access → Tunnels → Create a tunnel. Choose Cloudflared, name it (e.g., openchamber-tunnel), and copy the tunnel token.
Step 2: Add the token to docker-compose.yml as OPENCHAMBER_TUNNEL_TOKEN.
Step 3: In Cloudflare DNS, add a CNAME record pointing opencode to <tunnel-id>.cfargotunnel.com with proxy enabled (orange cloud).
Step 4: Start OpenChamber:
cd /opt/openchamber
docker compose up -d
docker logs openchamber --tail=50
Look for: Tunnel active (cloudflare): https://opencode.yourdomain.com
Cloudflare Access Authentication
Cloudflare Access adds authentication so only authorized users can access your instance. It supports email-based auth, Google/GitHub OAuth, one-time PINs, and IP restrictions.
Setup: In Cloudflare Zero Trust, go to Access → Applications → Add an application → Self-hosted. Configure the application name, session duration (24 hours recommended), and domain (opencode.yourdomain.com). Add a policy with Action: Allow, Include: Emails, and add your email.
Now visitors will see a Cloudflare Access login page before reaching OpenChamber. The managed-remote tunnel mode handles this automatically without double-auth issues.
Custom AI Provider Integration
OpenCode supports OpenAI-compatible APIs, allowing you to use custom model routers (Custom-Gateway, LiteLLM), self-hosted models (Ollama, vLLM), or alternative providers.
Example: Custom-Gateway Integration
Edit /opt/openchamber/data/opencode/config/opencode.jsonc:
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"custom-gateway": {
"npm": "@ai-sdk/openai-compatible",
"name": "Custom-Gateway",
"options": {
"baseURL": "https://gateway.yourdomain.com/v1",
"apiKey": "{env:CUSTOM_GATEWAY_API_KEY}"
},
"models": {
"kr/claude-sonnet-4.5": {
"name": "Claude Sonnet 4.5 via Custom-Gateway"
},
"cx/gpt-5.5": {
"name": "GPT 5.5 via Custom-Gateway"
}
}
}
},
"model": "custom-gateway/kr/claude-sonnet-4.5"
}
Key points: Use @ai-sdk/openai-compatible adapter, reference environment variables with {env:VAR_NAME} syntax, and set the default model in provider/model-id format.
Restart and verify:
cd /opt/openchamber
docker compose restart openchamber
docker exec openchamber /home/openchamber/.npm-global/bin/opencode providers list
Verification Commands
Check container status:
docker ps --format 'table {{.ID}}\t{{.Names}}\t{{.Image}}\t{{.Ports}}'
View logs:
docker logs openchamber --tail=200
Test tunnel connectivity:
curl -I https://opencode.yourdomain.com
Expected response with Cloudflare Access enabled: HTTP/2 302 redirect to Cloudflare Access login.
Common Pitfalls
Wrong config location: Always edit /opt/openchamber/data/opencode/config/opencode.jsonc, not /home/opencode/.config/ on the host.
Using host paths: Use container paths like /home/openchamber/workspaces/myproject, not /opt/openchamber/workspaces/myproject.
Tunnel not active: Verify token in Cloudflare dashboard, check CNAME record points to <tunnel-id>.cfargotunnel.com, ensure proxy is enabled, and restart the container.
API key not working: Verify env var in docker-compose.yml, use {env:VAR_NAME} syntax in opencode.jsonc, restart after env changes, and test with docker exec openchamber env | grep CUSTOM_GATEWAY.
What’s Next?
You now have a fully functional OpenChamber instance with Docker containerization, secure Cloudflare Tunnel access, Cloudflare Access authentication, and custom AI provider integration.
In Part 2, we’ll cover GitLab repository integration (SSH and HTTPS methods), cloning and registering projects, Git branch management, running development servers inside containers, and port exposure strategies.
Related Resources:
– OpenChamber Documentation
– OpenCode GitHub Repository
– Cloudflare Tunnel Guide


