feat(opencode): añadir stack del agente de código OpenCode

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>
This commit is contained in:
Eduardo David Paredes Vara
2026-05-25 05:49:44 +00:00
parent c484e502c2
commit d771ea9dd5
9 changed files with 267 additions and 0 deletions
+107
View File
@@ -0,0 +1,107 @@
# 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 desde `opencode/.env.example`)
- Middleware Traefik (inyecta `Authorization`): `/opt/traefik/dynamic/opencode-auth.yml`
- Config de legado host/systemd: `opencode/systemd/` y `opencode/traefik/opencode.yml`
## 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
```
Para SSO directo (sin segundo login de OpenCode), crea tambien este middleware dinamico en Traefik:
```yaml
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: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, cada dominio necesita su propio `Proxy Provider` publicado en el `authentik Embedded Outpost`:
1. Provider/app para `ocode.sherlockhomeless.net` (sandboxed).
2. Provider/app independiente para `opencode.sherlockhomeless.net` (clasico).
3. Ambos providers deben estar anadidos al `authentik Embedded Outpost`.
4. Para aislar el acceso sandboxed, crea un grupo exclusivo, por ejemplo `opencode-ocode-users`.
5. Crea una `Policy Binding` para la app sandboxed que permita solo ese grupo.
6. Crea el usuario del colega y anadelo solo a `opencode-ocode-users`.
7. 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).
```bash
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:
```bash
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:
```bash
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 |