Files
Portainer/opencode
Eduardo David Paredes Vara d771ea9dd5 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>
2026-05-25 05:49:44 +00:00
..

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

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: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).

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