50 lines
2.5 KiB
Markdown
50 lines
2.5 KiB
Markdown
# OpenCode Web UI
|
|
|
|
Este stack ejecuta OpenCode en un contenedor con aislamiento fuerte para exponerlo solo por HTTPS detras de Traefik + Authentik.
|
|
|
|
## Objetivo
|
|
|
|
- Dominio: `https://ocode.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 desde `opencode/.env.example`)
|
|
|
|
## Despliegue en contenedor
|
|
|
|
```bash
|
|
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
|
|
```
|
|
|
|
El router activo se define en `/opt/traefik/dynamic/opencode.yml` y aplica Authentik junto con la cabecera Basic necesaria para el backend.
|
|
|
|
## Endurecimiento aplicado
|
|
|
|
- `user: 1000:1000`
|
|
- `cap_drop: [ALL]`
|
|
- `security_opt: [no-new-privileges:true]`
|
|
- `read_only: true`
|
|
- `/tmp` en `tmpfs` con `exec`, 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.sock` ni montajes del host fuera de los paths definidos
|
|
|
|
## Authentik (acceso solo a esta app)
|
|
|
|
En Authentik, `ocode.sherlockhomeless.net` necesita su propio `Proxy Provider` publicado en el `authentik Embedded Outpost`.
|
|
|
|
Para aislar el acceso, crea un grupo exclusivo, por ejemplo `opencode-ocode-users`, y una `Policy Binding` que permita solo ese grupo. El contenedor usa los modelos configurados mediante `DEEPSEEK_API_KEY` en su `.env`.
|
|
|
|
## Claude Sonnet 5 mediante LiteLLM
|
|
|
|
OpenCode consume `claude-sonnet-5` desde el proveedor OpenAI-compatible de LiteLLM. La configuracion activa debe incluir el modelo con el identificador `litellm/claude-sonnet-5` y apuntar `options.baseURL` a `https://llm.sherlockhomeless.net/v1` (o a `http://litellm:4000/v1` si ambos servicios comparten la red Docker).
|
|
|
|
El fichero `opencode/opencode.json` contiene la configuracion local efectiva y esta ignorado por Git porque incluye la clave maestra de LiteLLM. OpenCode solo necesita esa clave; el OAuth de Claude se mantiene y renueva exclusivamente en LiteLLM, por lo que no se debe montar `.claude/.credentials.json` dentro de OpenCode.
|
|
|
|
OpenWebUI no requiere una entrada estatica equivalente: obtiene dinamicamente `claude-sonnet-5` de `/v1/models` usando su conexion OpenAI-compatible existente con LiteLLM.
|