diff --git a/memos/docker-compose.yml b/memos/docker-compose.yml index 52241c5..55f5139 100644 --- a/memos/docker-compose.yml +++ b/memos/docker-compose.yml @@ -3,6 +3,8 @@ services: image: postgres:17-alpine container_name: memos-db restart: unless-stopped + labels: + prune.protect: "true" environment: TZ: ${TZ} POSTGRES_DB: ${MEMOS_DB_NAME} @@ -21,9 +23,10 @@ services: memos: image: neosmemo/memos:0.27.1 - pull_policy: always container_name: memos restart: unless-stopped + labels: + prune.protect: "true" depends_on: memos-db: condition: service_healthy @@ -55,12 +58,8 @@ services: - memos_internal - proxy labels: - traefik.enable: "true" - traefik.docker.network: "${TRAEFIK_DOCKER_NETWORK}" - traefik.http.routers.memos.rule: "Host(`${MEMOS_DOMAIN}`)" - traefik.http.routers.memos.entrypoints: "${TRAEFIK_ENTRYPOINT_SECURE}" - traefik.http.routers.memos.tls.certresolver: "${TRAEFIK_CERTRESOLVER}" - traefik.http.services.memos.loadbalancer.server.port: "8080" + prune.protect: "true" + traefik.enable: "false" networks: memos_internal: diff --git a/onetimesecret/docker-compose.yml b/onetimesecret/docker-compose.yml index 6c6cacc..309f437 100644 --- a/onetimesecret/docker-compose.yml +++ b/onetimesecret/docker-compose.yml @@ -1,7 +1,6 @@ services: ots: image: ${OTS_IMAGE} - pull_policy: always container_name: onetimesecret restart: unless-stopped healthcheck: @@ -34,19 +33,13 @@ services: networks: - proxy labels: + prune.protect: "true" traefik.enable: "true" traefik.docker.network: "${TRAEFIK_DOCKER_NETWORK}" - traefik.http.routers.onetimesecret.rule: "Host(`${OTS_DOMAIN}`)" - traefik.http.routers.onetimesecret.entrypoints: "${TRAEFIK_ENTRYPOINT_SECURE}" - traefik.http.routers.onetimesecret.tls: "true" - traefik.http.routers.onetimesecret.tls.certresolver: "${TRAEFIK_CERTRESOLVER}" - traefik.http.routers.onetimesecret.middlewares: "crowdsec-bouncer@file" - traefik.http.routers.onetimesecret.service: "ots-svc" - traefik.http.services.ots-svc.loadbalancer.server.port: "3000" homepage.group: "Automatizacion y desarrollo" homepage.name: "OneTimeSecret" - homepage.icon: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/key.svg" + homepage.icon: "https://onetimesecret.com/etc/img/onetime-logo-md.png" homepage.href: "https://${OTS_DOMAIN}/" homepage.description: "Compartir secretos de un solo uso" homepage.siteMonitor: "https://${OTS_DOMAIN}/" @@ -55,6 +48,8 @@ services: image: ${OTS_REDIS_IMAGE} container_name: onetimesecret-redis restart: unless-stopped + labels: + prune.protect: "true" volumes: - ${OTS_REDIS_PATH}:/data:Z networks: diff --git a/opencode/README.md b/opencode/README.md index d31d9e4..346a90b 100644 --- a/opencode/README.md +++ b/opencode/README.md @@ -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`. diff --git a/opencode/docker-compose.yml b/opencode/docker-compose.yml index 26869ed..1929deb 100644 --- a/opencode/docker-compose.yml +++ b/opencode/docker-compose.yml @@ -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: diff --git a/opencode/opencode-web.env.example b/opencode/opencode-web.env.example deleted file mode 100644 index ce7a719..0000000 --- a/opencode/opencode-web.env.example +++ /dev/null @@ -1,4 +0,0 @@ -OPENCODE_SERVER_USERNAME=opencode -OPENCODE_SERVER_PASSWORD=change-me -OPENCODE_DISABLE_AUTOUPDATE=true - diff --git a/opencode/opencode.json.example b/opencode/opencode.json.example deleted file mode 100644 index fb55c68..0000000 --- a/opencode/opencode.json.example +++ /dev/null @@ -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 - } - } - } - } - } -} diff --git a/opencode/systemd/opencode-web.service b/opencode/systemd/opencode-web.service deleted file mode 100644 index c702a96..0000000 --- a/opencode/systemd/opencode-web.service +++ /dev/null @@ -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 diff --git a/opencode/traefik/opencode.yml b/opencode/traefik/opencode.yml deleted file mode 100644 index 58be489..0000000 --- a/opencode/traefik/opencode.yml +++ /dev/null @@ -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 " - - services: - opencode: - loadBalancer: - servers: - - url: http://host.docker.internal:4096