OpenCode como agente de desarrollo con acceso al filesystem del host, expuesto vía Traefik con autenticación forward auth de Authentik. Incluye configuración de systemd para modo web y ejemplos de .env. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
OpenCode Web UI
Este stack ejecuta OpenCode en un contenedor con aislamiento fuerte para exponerlo solo por HTTPS detras de Traefik + Authentik.
Objetivo
- Dominio sandboxed:
https://ocode.sherlockhomeless.net - Dominio clasico host/systemd:
https://opencode.sherlockhomeless.net - Acceso: solo usuarios autorizados en Authentik
- Aislamiento: sin privilegios, filesystem raiz de solo lectura y workspace dedicado
Archivos
- Compose:
opencode/docker-compose.yml - Variables:
opencode/.env(copiar desdeopencode/.env.example) - Middleware Traefik (inyecta
Authorization):/opt/traefik/dynamic/opencode-auth.yml - Config de legado host/systemd:
opencode/systemd/yopencode/traefik/opencode.yml
Despliegue en contenedor
cp opencode/.env.example opencode/.env
mkdir -p /opt/opencode/home /opt/opencode/config /opt/opencode/workspace
docker compose --env-file opencode/.env -f opencode/docker-compose.yml up -d
Para SSO directo (sin segundo login de OpenCode), crea tambien este middleware dinamico en Traefik:
http:
middlewares:
opencode-inject-auth:
headers:
customRequestHeaders:
Authorization: "Basic <base64(usuario:password-opencode)>"
El router sandboxed usa la cadena ths-authentik@docker,opencode-inject-auth@file, asi Authentik valida al usuario y Traefik pasa despues la cabecera Basic al backend.
Endurecimiento aplicado
user: 1000:1000cap_drop: [ALL]security_opt: [no-new-privileges:true]read_only: true/tmpentmpfsconexec, necesario para que Bun/OpenCode cargue librerias temporales- Home persistente aislada en
/opt/opencode/home - Workspace aislado en
/opt/opencode/workspace, montado dentro de la home como/home/opencode/workspace - Sin
docker.sockni montajes del host fuera de los paths definidos
Authentik (acceso solo a esta app)
En Authentik, cada dominio necesita su propio Proxy Provider publicado en el authentik Embedded Outpost:
- Provider/app para
ocode.sherlockhomeless.net(sandboxed). - Provider/app independiente para
opencode.sherlockhomeless.net(clasico). - Ambos providers deben estar anadidos al
authentik Embedded Outpost. - Para aislar el acceso sandboxed, crea un grupo exclusivo, por ejemplo
opencode-ocode-users. - Crea una
Policy Bindingpara la app sandboxed que permita solo ese grupo. - Crea el usuario del colega y anadelo solo a
opencode-ocode-users. - No lo anadas a grupos con acceso a otras aplicaciones.
Si el clasico devuelve una pagina Not Found de Authentik, normalmente significa que el provider de opencode.sherlockhomeless.net no esta asociado al outpost o fue sustituido por el provider de ocode.sherlockhomeless.net.
Arquitectura de modelos LLM
Hay dos instancias de OpenCode con modelos distintos:
| Instancia | Tipo | Modelos |
|---|---|---|
opencode.sherlockhomeless.net |
Host (systemd) | DeepSeek + Gemma 4 (Ollama) |
ocode.sherlockhomeless.net |
Contenedor | Solo DeepSeek (colega) |
El contenedor sandboxed (ocode) no usa Ollama ni Gemma 4. Sus modelos ya estan configurados via DEEPSEEK_API_KEY en su .env.
Modelos Gemma 4 via Ollama (para el host OpenCode)
Ollama corre en contenedor expuesto en 127.0.0.1:11434 (solo localhost).
cp ollama/.env.example ollama/.env
mkdir -p /opt/ollama/data
docker compose --env-file ollama/.env -f ollama/docker-compose.yml up -d
Pull de modelos:
docker exec -it ollama ollama pull gemma4:e2b # modelo principal
docker exec -it ollama ollama pull gemma4:e4b # opcional si e2b no basta
Activar provider en el OpenCode del host:
sudo install -m 0644 opencode/opencode.json.example /home/felidae/.config/opencode/opencode.json
sudo systemctl restart opencode-web
Modelos recomendados para este VPS (8 vCPU, 22 GiB RAM, sin GPU):
| Modelo | RAM aprox | Uso |
|---|---|---|
gemma4:e2b |
~3-4 GiB | Modelo principal |
gemma4:e4b |
~5-6 GiB | Solo si e2b no basta |
gemma4:26b |
~16 GiB | No recomendable |
gemma4:31b |
~20 GiB | No recomendable |