fix(opencode): retire legacy host route

This commit is contained in:
Eduardo David Paredes Vara
2026-07-25 11:22:13 +00:00
parent aaf50e5af7
commit 10d2a301e0
8 changed files with 21 additions and 164 deletions
+3 -57
View File
@@ -4,8 +4,7 @@ Este stack ejecuta OpenCode en un contenedor con aislamiento fuerte para exponer
## Objetivo
- Dominio sandboxed: `https://ocode.sherlockhomeless.net`
- Dominio clasico host/systemd: `https://opencode.sherlockhomeless.net`
- Dominio: `https://ocode.sherlockhomeless.net`
- Acceso: solo usuarios autorizados en Authentik
- Aislamiento: sin privilegios, filesystem raiz de solo lectura y workspace dedicado
@@ -14,7 +13,6 @@ Este stack ejecuta OpenCode en un contenedor con aislamiento fuerte para exponer
- 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
@@ -50,58 +48,6 @@ El router sandboxed usa la cadena `ths-authentik@docker,opencode-inject-auth@fil
## Authentik (acceso solo a esta app)
En Authentik, cada dominio necesita su propio `Proxy Provider` publicado en el `authentik Embedded Outpost`:
En Authentik, `ocode.sherlockhomeless.net` 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 |
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`.
+8 -7
View File
@@ -3,7 +3,7 @@ services:
build:
context: .
dockerfile: Dockerfile
image: local/opencode-sandbox:latest
image: local/opencode-sandbox:pinned-20260528
container_name: opencode
restart: unless-stopped
stop_grace_period: 30s
@@ -29,14 +29,15 @@ services:
networks:
- proxy
labels:
prune.protect: "true"
traefik.enable: "true"
traefik.docker.network: "${TRAEFIK_DOCKER_NETWORK}"
traefik.http.routers.ocode.rule: "Host(`${OPENCODE_DOMAIN}`)"
traefik.http.routers.ocode.entrypoints: "${TRAEFIK_ENTRYPOINT_SECURE}"
traefik.http.routers.ocode.tls: "true"
traefik.http.routers.ocode.tls.certresolver: "${TRAEFIK_CERTRESOLVER}"
traefik.http.routers.ocode.middlewares: "crowdsec-bouncer@file,${TRAEFIK_AUTH_CHAIN}"
traefik.http.services.ocode.loadbalancer.server.port: "4096"
traefik.http.routers.opencode.rule: "Host(`${OPENCODE_DOMAIN}`)"
traefik.http.routers.opencode.entrypoints: "${TRAEFIK_ENTRYPOINT_SECURE}"
traefik.http.routers.opencode.tls: "true"
traefik.http.routers.opencode.tls.certresolver: "${TRAEFIK_CERTRESOLVER}"
traefik.http.routers.opencode.middlewares: "crowdsec-bouncer@file,${TRAEFIK_AUTH_CHAIN}"
traefik.http.services.opencode.loadbalancer.server.port: "4096"
networks:
proxy:
-4
View File
@@ -1,4 +0,0 @@
OPENCODE_SERVER_USERNAME=opencode
OPENCODE_SERVER_PASSWORD=change-me
OPENCODE_DISABLE_AUTOUPDATE=true
-29
View File
@@ -1,29 +0,0 @@
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"ollama-vps": {
"npm": "@ai-sdk/openai-compatible",
"name": "Ollama VPS",
"options": {
"baseURL": "http://localhost:11434/v1",
"apiKey": "ollama"
},
"models": {
"gemma4:e2b": {
"name": "Gemma 4 E2B VPS",
"limit": {
"context": 16384,
"output": 2048
}
},
"gemma4:e4b": {
"name": "Gemma 4 E4B VPS",
"limit": {
"context": 16384,
"output": 2048
}
}
}
}
}
}
-24
View File
@@ -1,24 +0,0 @@
[Unit]
Description=OpenCode Web UI
Documentation=https://opencode.ai/docs/web/
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=felidae
Group=felidae
WorkingDirectory=/home/eduardo/Portainer_repo
EnvironmentFile=/etc/opencode-web.env
Environment=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Environment=HOME=/home/felidae
ExecStart=/usr/local/bin/opencode-host web --hostname 10.0.0.1 --port 4096 --print-logs
Restart=always
RestartSec=5
# OpenCode necesita operar sobre repos y herramientas del host; se mantiene sin
# sandboxing restrictivo de systemd a proposito.
NoNewPrivileges=false
[Install]
WantedBy=multi-user.target
-27
View File
@@ -1,27 +0,0 @@
http:
routers:
opencode:
rule: Host(`opencode.sherlockhomeless.net`)
entryPoints:
- websecure
tls:
certResolver: letsencrypt
middlewares:
- crowdsec-bouncer@file
- ths-authentik@docker
- opencode-basic-auth
service: opencode
middlewares:
opencode-basic-auth:
headers:
customRequestHeaders:
# En el host desplegado se genera desde /etc/opencode-web.env.
# No versionar el secreto real en el repo.
Authorization: "Basic <base64(usuario:password-opencode)>"
services:
opencode:
loadBalancer:
servers:
- url: http://host.docker.internal:4096