Modelos autoalojados
Takuto Core puede manejar un servidor de modelos autoalojado y compatible con OpenAI — LM Studio, Ollama, vLLM y similares — a través del proveedor OpenCode. Esto mantiene el código fuente y los prompts enteramente en infraestructura que tú controlas. Esta página cubre el setup y los modos de fallo con los que nos topamos al conectar LM Studio con Docker Desktop, para que no tengas que volver a deducirlos.
Cada ajuste de abajo es editable desde Configuración → AI Settings → OpenCode en el dashboard. No hace falta editar
config.tomla mano.
Setup básico
-
Fija el proveedor en OpenCode en Configuración → AI Settings.
-
Fija el campo Model. El flag
-mde OpenCode espera<providerId>/<modelId>, y la configuración generada por Takuto Core siempre nombra al proveedorself_hosted, así que el valor debe verse así:self_hosted/<model-id-as-reported-by-the-server>Id de modelo reportado por el servidor Fija en Takuto qwen/qwen2.5-vl-7bself_hosted/qwen/qwen2.5-vl-7blmstudio-community/Llama-3.1-8B-Instruct-GGUFself_hosted/lmstudio-community/Llama-3.1-8B-Instruct-GGUF -
Fija la Base URL al endpoint compatible con OpenAI, incluido el
/v1final:http://host.docker.internal:1234/v1 -
Si tu servidor no necesita una API key real (LM Studio y Ollama normalmente no), marca Allow shared default token para que Takuto Core inyecte un bearer de marcador.
-
Fija Context limit / Output limit para que coincidan con tu modelo — los endpoints locales no pueden reportarlos, así que OpenCode depende de los valores que proporciones.
El lado del servidor de modelos
Haz que el servidor sea alcanzable desde los containers:
- LM Studio: activa Developer → Local Server → “Serve on Local Network”. Sin eso, LM
Studio se enlaza solo a
127.0.0.1y ningún container puede alcanzarlo. - Firewall de macOS: o apagado, o con el servidor de modelos explícitamente permitido.
Confirma que está enlazado a todas las interfaces, no solo a loopback:
lsof -nP -iTCP -sTCP:LISTEN | grep 1234
# Want: *:1234 (LISTEN) — bound to all interfaces
# If it shows 127.0.0.1:1234, "Serve on Local Network" is OFF.
El sidecar puente (workaround para gVisor)
Solo necesitas esto cuando el servidor de modelos corre en el Mac anfitrión y Docker Desktop usa el stack de red gVisor (el valor por defecto desde 4.34+). No lo necesitas para proveedores en la nube, ni cuando el servidor de modelos corre como un container dentro de la red de compose de Takuto Core — en ese caso apunta la Base URL al nombre del servicio (p. ej.
http://lm-studio:1234/v1) y sáltate el puente.
Con gVisor, el tráfico de los containers hacia IPs privadas en la LAN del Mac — incluido
host.docker.internal (que resuelve a 192.168.65.254 dentro del container) — puede agotar
el tiempo en silencio, mientras que las IPs públicas funcionan bien. Comprueba tu tipo de red:
ps ax | grep com.docker.virtualization | grep -o 'networkType [a-z]*'
# networkType gvisor ← affected
Confirma que es el problema de gVisor
Si el servidor se enlaza a *:1234, el firewall está apagado, internet público funciona
desde un container, pero tanto host.docker.internal:1234 como la IP de la LAN del Mac
agotan el tiempo desde dentro del container — es el stack de gVisor.
# Public internet works from a container:
docker exec <takuto-container> sh -c 'wget -q -O - -T 3 https://1.1.1.1 | head -3'
# host.docker.internal resolves but connections time out:
docker exec <takuto-container> sh -c 'curl -v -m 3 http://host.docker.internal:1234/v1/models 2>&1 | tail -5'
# * Connection timed out after 3001 milliseconds
Solución: el sidecar socat lm-bridge
Takuto Core incluye un pequeño container socat que se adjunta a ambas redes: la bridge
por defecto (que alcanza el host correctamente bajo gVisor) y la red de compose (para que los
workers anidados en DinD puedan enrutar hacia él). Levántalo con un solo flag — los targets de
make de abajo son el envoltorio de comodidad del repo del motor Takuto Core (la
vía de crea-tu-propio-container); por debajo, LM_BRIDGE=1
simplemente fusiona docker-compose.lm-bridge.yml en el stack de Compose:
make start BACKEND=postgres LM_BRIDGE=1
Eso arranca maestro-lm-bridge en la IP fijada 172.20.0.250, reenviando
TCP/1234 → host.docker.internal:${LM_HOST_PORT:-1234}. Luego fija la Base URL en AI
Settings a:
http://172.20.0.250:1234/v1
Para un puerto distinto del por defecto (el 11434 de Ollama, por ejemplo):
LM_HOST_PORT=11434 make start BACKEND=postgres LM_BRIDGE=1
Smoke test una vez que el puente está arriba
docker exec maestro-core-dind-1 docker run --rm --entrypoint /bin/bash \
maestro:latest -c \
'exec 3<>/dev/tcp/172.20.0.250/1234;
printf "GET /v1/models HTTP/1.0\r\nHost: x\r\n\r\n" >&3;
timeout 5 cat <&3 | head -5'
Un 200 OK seguido de JSON significa que la ruta del worker está sana.
Checklist para OpenCode error: unknown error
Cuando el dashboard muestra el críptico OpenCode error: unknown error, recorre estos en
orden — cada uno es un modo de fallo real:
- El campo Model empieza por
self_hosted/. - Allow shared default token está marcado (a menos que hayas guardado un bearer por
usuario). Cuando está desmarcado y no hay ningún bearer guardado, no se monta ningún
opencode.jsonen el worker y OpenCode sale justo después de su migración de base de datos del primer arranque. - La Base URL termina en
/v1. - El servidor de modelos tiene “Serve on Local Network” activo (
*:<port>, no127.0.0.1:<port>). - La red de Docker Desktop está sana — ejecuta el smoke test; si agota el tiempo, usa el
sidecar
LM_BRIDGEde arriba.
Si los cinco están en verde y la ejecución aún falla, ejecuta opencode run manualmente
dentro del container con --print-logs --log-level WARN para ver el stderr propio de
OpenCode en lugar del oculto “unknown error”.