Instalar DeepSeek Harness en un VPS sin exponerlo
Instala DeepSeek Harness en un VPS Linux, fija la version de npm, revisa que todo sea un plugin y accede a la interfaz web del puerto 3080 mediante un tunel SSH.
Qué es DeepSeek Harness
DeepSeek Harness (dsh) es un runtime de agentes de Node.js que puede ejecutar en un VPS (servidor privado virtual). La forma segura de ejecutarlo es vincularlo a 127.0.0.1 y acceder desde el navegador mediante un túnel SSH (secure shell). Proporciona una interfaz web (interfaz de usuario) en el puerto 3080 en lugar de ejecutarse en una terminal. Este servidor web no solicita ninguna contraseña propia. Por tanto, publicar el puerto 3080 entrega a cualquiera que lo encuentre un agente que puede leer sus archivos y ejecutar comandos con su usuario de Linux.
DeepSeek lo publicó el 13 de agosto de 2026 con licencia MIT, como el paquete npm @deepseek-ai/dsh. El proyecto se describe como una vista previa para desarrolladores e indica que se esperan cambios incompatibles. Todos los números de versión que aparecen a continuación corresponden a una instantánea de agosto de 2026. Compruebe el repositorio antes de copiar cualquiera de estos elementos en un sistema importante.
Un principio recorre todo el diseño: todo es un plugin. El adaptador del modelo, el registro de herramientas, el registro de sesiones, el sandbox, el planificador y el propio bucle del agente son plugins cargados en un contexto compartido. Cualquiera de ellos puede sustituirse. No existe un núcleo privilegiado que los plugins sólo complementen. Esto hace que merezca la pena probar el harness y también es el origen del único riesgo real.
Un arnés no es un modelo
El arnés ejecuta el ciclo del agente. El razonamiento ocurre en un modelo independiente, por lo que nada funciona hasta que se proporciona una clave de API (interfaz de programación de aplicaciones) o la dirección de un endpoint de modelo alojado por usted.
Esto se configura en la interfaz de usuario, en Settings y después en Models. El catálogo incluye tarjetas preparadas para los principales proveedores de API (DeepSeek, OpenAI, Anthropic), donde se pega una clave. La opción "Add a custom provider" es la más interesante: requiere un ID de proveedor, un nombre visible, una URL base, un protocolo de API y una credencial. Usa el protocolo compatible con OpenAI, por lo que funciona con cualquier gateway o servidor local que implemente ese protocolo. Los proveedores personalizados también pueden consultar el endpoint compatible con OpenAI GET /models para completar automáticamente la lista de modelos.
Así se apunta el arnés a un modelo del mismo VPS. Ollama expone una API compatible con OpenAI en http://127.0.0.1:11434/v1/ y requiere que el campo de clave de API contenga cualquier cadena, ollama por convención, porque el campo es obligatorio y después se ignora. La cuestión más difícil es si un modelo suficientemente pequeño para ejecutarse en su VPS puede controlar un agente con resultados adecuados. La diferencia entre Ollama y vLLM como servidores de modelos locales determina cuánta RAM consumirá la respuesta.
Las claves introducidas en la interfaz de usuario son de solo escritura. El arnés las almacena en $DSH_HOME/.credentials.yaml y conserva únicamente una referencia a la credencial en settings.yaml. $DSH_HOME tiene ~/.dsh de forma predeterminada. Trate ese archivo como un archivo de contraseñas, porque lo es: cualquiera que pueda leerlo puede gastar su presupuesto de API.
Lo que necesita antes de instalar
- un VPS con Ubuntu 24.04 u otro Linux actual, con acceso SSH
- Node.js 22.19 o una versión posterior de la línea 22.x, o Node.js 24 o posterior, que son las versiones con las que el proyecto compila y ejecuta sus pruebas
- una cuenta de usuario normal, no
root, porque el agente ejecuta comandos de shell como el usuario que inició el proceso pnpmen el PATH si planea instalar plugins, ya que el comando de plugins lo ejecuta mediante un shell- el puerto 3080 cerrado en el firewall y en el firewall de red independiente del proveedor
El paquete nodejs de Ubuntu es más antiguo de lo que necesita el arnés de pruebas, por lo que debe instalar Node desde NodeSource o nvm en lugar de recurrir a apt install nodejs. Si el VPS es nuevo, merece la pena reforzar SSH antes de cualquier otra tarea durante diez minutos, porque el túnel del que está a punto de depender sólo es tan seguro como el servidor SSH que lo respalda.
Instale DeepSeek Harness en un VPS con una versión fijada
node --version
npx @deepseek-ai/dsh@0.1.0-rc.6 webnpx descarga el paquete y ejecuta su binario dsh. web es un alias de --profile web, que inicia la aplicación web, y el proceso muestra la dirección en la que está escuchando. El valor predeterminado es http://127.0.0.1:3080.
Fije la versión. npx @deepseek-ai/dsh web resuelve el destino actual de la etiqueta latest cada vez que se ejecuta, y el proyecto ya ha publicado varias versiones candidatas y advierte que habrá cambios incompatibles. 0.1.0-rc.6 es el destino al que apuntaba latest el 13 de agosto de 2026. Una versión fijada garantiza que el servidor configurado hoy se comporte igual el próximo mes. Así, la actualización pasa a ser una decisión explícita y no un cambio inesperado.
Para el uso diario, instálelo una vez en lugar de volver a resolver la versión en cada inicio.
npm install -g @deepseek-ai/dsh@0.1.0-rc.6
dsh --profile web --helpConviene ejecutar esa segunda línea porque el lanzador y la aplicación web tienen conjuntos de opciones independientes. dsh --help muestra las opciones propias del lanzador. dsh --profile web --help muestra las opciones que acepta la aplicación web. Ahí se encuentran --port, --host y --trusted-host, que se puede repetir.
Ahora confirme en qué dirección está escuchando.
ss -tlnp | grep 3080La columna de dirección local debe mostrar 127.0.0.1:3080. Si muestra 0.0.0.0:3080, la interfaz está accesible desde Internet. Detenga el proceso antes de hacer cualquier otra cosa.
Por qué nunca debe publicar el puerto 3080
El servidor web no tiene una capa de autenticación. Su configuración expone un host de escucha y un puerto de escucha. Esa es toda la superficie. El control de acceso para despliegues que no usan loopback se configura por separado mediante un ajuste de host de confianza. No es una pantalla de inicio de sesión.
Ahora tenga en cuenta lo que hay detrás de ese puerto. El agente edita archivos del workspace y ejecuta comandos de shell. Además, las credenciales del proveedor están almacenadas en disco junto al agente. Por tanto, un puerto 3080 abierto equivale a un shell remoto con una interfaz de chat, que se ejecuta con el usuario que lo inició y tiene asociada su clave de API. No hace falta ningún exploit. Basta con conocer el número de puerto. Los escáneres encuentran los puertos a las pocas horas de que un host se conecte.
La CLI (interfaz de línea de comandos) confirma este comportamiento. Desde 0.1.0-rc.6, no admite deliberadamente --host 0.0.0.0 y termina con un error de uso en lugar de iniciarse. Este rechazo es una función de seguridad. No busque un parche para eliminarlo.
Hay otros dos despliegues razonables cuando un túnel no resulta adecuado. Coloque el equipo en una red superpuesta privada para que tenga una dirección a la que sólo puedan enrutar sus propios dispositivos. Esto es lo que proporciona un servidor de control Headscale autohospedado. Otra opción es situar delante un reverse proxy que autentique la petición antes de que llegue al puerto 3080, por ejemplo un servidor de inicio de sesión único Authentik que realice autenticación delegada. Un reverse proxy sin autenticación delante no es un control de seguridad. Es una URL más larga.
Acceder a la interfaz web mediante un túnel SSH
Ejecute esto en su portátil, no en el servidor.
ssh -N -L 3080:127.0.0.1:3080 you@your-server-L abre el puerto 3080 en su portátil y reenvía todo lo que se conecte a él a través de la sesión SSH cifrada. La parte 127.0.0.1:3080 se resuelve en el servidor, por lo que la conexión llega al harness desde loopback, exactamente como si estuviera delante de la máquina. -N indica que no se debe iniciar un shell remoto, porque sólo necesita el reenvío.
A continuación, abra http://127.0.0.1:3080 en el navegador local. Si el puerto 3080 ya está ocupado en su portátil, cambie el número de la izquierda: ssh -N -L 3180:127.0.0.1:3080 you@your-server, y después abra http://127.0.0.1:3180. El número de la izquierda es local y el de la derecha pertenece al servidor, por lo que sólo debe cambiar el de la izquierda.
Guárdelo en ~/.ssh/config y deje de escribirlo manualmente.
Host dsh
HostName 203.0.113.10
User deploy
IdentityFile ~/.ssh/id_ed25519
LocalForward 3080 127.0.0.1:3080Después, ssh -N dsh inicia el túnel. Si el navegador indica que se rechazó la conexión, normalmente significa que el túnel está activo, pero no hay nada escuchando en el extremo remoto, porque SSH reenvía el puerto tanto si el harness está ejecutándose como si no. Compruebe el servidor con el comando ss anterior.
Mantenga el harness en ejecución después de cerrar la sesión
Un comando npx termina junto con su shell. Un servicio de usuario de systemd permanece activo y vuelve a iniciar el harness después de un fallo o un reinicio.
loginctl enable-linger $USER
mkdir -p ~/.config/systemd/user
command -v dshenable-linger es importante porque los servicios de usuario normalmente se detienen cuando finaliza la última sesión. Sin esta opción, el harness termina en cuanto cierra el túnel. Tome la ruta absoluta que muestra command -v dsh e introdúzcala en la unidad, porque systemd no busca en el PATH que construye el shell de inicio de sesión.
[Unit]
Description=DeepSeek Harness web UI
After=network-online.target
[Service]
Type=simple
WorkingDirectory=%h/projects/site
ExecStart=/usr/local/bin/dsh web
Restart=on-failure
RestartSec=5
[Install]
WantedBy=default.targetWorkingDirectory no es un detalle estético. El proceso dsh usa el directorio desde el que se inicia como ubicación predeterminada del sistema de archivos. Por eso, si el servicio se inicia en el directorio incorrecto, el agente obtiene un espacio de trabajo predeterminado incorrecto. Aun así, puede seleccionar el espacio de trabajo en la interfaz.
systemctl --user daemon-reload
systemctl --user enable --now dsh
systemctl --user status dshUna unidad que no se inicia casi siempre tiene una ruta ExecStart incorrecta o una versión de Node que el binario rechaza. journalctl --user -u dsh -n 50 indica cuál de las dos causas se aplica. El mismo patrón sirve para mantener cualquier agente de programación activo en un VPS, y los modos de fallo son idénticos.
Qué puede hacer un plugin
Un plugin es un módulo que aporta servicios, eventos tipados y efectos reversibles a un contexto compartido. Conviene revisar con atención los puntos de extensión:
- registrar un proveedor de modelos en
ctx.llm - añadir herramientas orientadas al modelo en
ctx.tools - proporcionar el backend de shell detrás de
ctx.shell - proporcionar acceso al sistema de archivos o aplicar políticas detrás de
ctx.fs - registrar comandos para usuarios en
ctx.commands - ejecutar tareas en segundo plano mediante
ctx.jobs - envolver los procesos iniciados con un backend
ctx.sandbox - interceptar solicitudes y llamadas a herramientas mediante los eventos
agent/*ytools/* - ampliar el estado persistente de la sesión
- controlar la interfaz de usuario mediante
ctx.agents
Lea esa lista como lo haría un atacante. Un plugin puede proporcionar la capa del sistema de archivos y la capa de shell, y puede situarse entre el modelo y cada llamada a herramienta que realice. Ningún cuadro de diálogo de permisos se interpone entre un plugin y esos puntos de extensión, porque un plugin es código Node normal que se carga en el mismo proceso que todo lo demás. Instalar un plugin equivale a ejecutar código de un tercero con los permisos de su agente, y los permisos del agente son los permisos de su usuario de Unix.
Esta es la misma decisión de confianza que toma al conectar un servidor MCP a un agente en un VPS, donde MCP significa protocolo de contexto del modelo. Por eso ejecutar un agente de programación de forma segura en un VPS empieza por la cuenta con la que se ejecuta, no por el modelo. También explica por qué los ataques a la cadena de suministro de npm afectan tanto a los servidores: la instalación es la intrusión y no aparece ninguna solicitud de confirmación.
De dónde proceden los plugins
Los plugins se almacenan en perfiles. Un perfil es una composición con nombre almacenada en $DSH_HOME, que de forma predeterminada es ~/.dsh, y cada directorio de perfil contiene los plugins externos que instala. La CLI los administra reenviando los argumentos directamente a pnpm, y usa el directorio del perfil como directorio de trabajo.
dsh plugin --profile web add github:deepseek-harness/turtle-ui
dsh plugin --profile web remove turtle-uiComo los argumentos llegan a pnpm sin cambios, add, remove, update y why funcionan igual que en cualquier proyecto de pnpm, y un plugin puede ser un paquete npm o una referencia de GitHub. pnpm debe estar disponible primero en PATH. En Node 22 y versiones posteriores, corepack enable pnpm lo coloca allí.
El descubrimiento se realiza mediante un tema de GitHub. Los autores de plugins añaden el tema dsh-plugin a su repositorio, y consultar ese tema es la forma de encontrar los plugins disponibles. Un tema es una etiqueta que el autor aplica a su propio repositorio. Nadie lo revisa ni lo firma, y la página del tema se ordena por estrellas, que miden la popularidad, no la seguridad.
Cuatro hábitos permiten mantener esto bajo control. Lea el código fuente antes de instalar, porque la mayoría de los plugins son lo bastante pequeños como para leerlos en diez minutos. Fije la versión o el commit exactos en lugar de seguir una rama. Ejecute el harness con un usuario que no sea propietario de ningún otro recurso, en un VPS que esté dispuesto a reconstruir. Asigne al agente su propia clave de API con su propio límite de gasto, separado de la clave que usan los servicios de producción.
Si prefiere comparar los diseños antes de decidirse por uno, el harness multiagente de Omnigent resuelve el mismo problema con una estructura diferente, y las diferencias resultan evidentes cuando se incorporan plugins.
Qué falla primero
Node es demasiado antiguo. El proyecto requiere Node 22.19 y versiones posteriores de la línea 22.x, o Node 24 y posteriores, y su CI prueba esas versiones. Un entorno de ejecución más antiguo falla al iniciar porque el código usa sintaxis y API que no admite. Ejecute node --version antes de cualquier otra cosa.
El puerto 3080 ya está en uso. Puede tratarse de un segundo arnés, un proceso antiguo o una aplicación no relacionada que también usa 3080. Encuéntrelo con ss -tlnp | grep 3080. Después, deténgalo o inicie el arnés en otro puerto con dsh web --port 3180. --port pertenece a la aplicación web, por lo que debe ejecutarse después de web.
El navegador no puede conectarse a través del túnel. Confirme que accedió a 127.0.0.1 y no a la dirección pública del servidor, porque el puerto reenviado sólo existe en su portátil. Después, confirme que el arnés está escuchando en el servidor, ya que SSH configura el reenvío aunque no haya ningún proceso que responda en el extremo remoto.
dsh plugin falla inmediatamente. El comando es un contenedor de pnpm, por lo que la ausencia del binario pnpm lo detiene antes de iniciar cualquier trabajo de los complementos.
El agente no puede ver su proyecto. El espacio de trabajo usa de forma predeterminada el directorio en el que se inició el proceso. Por tanto, una unidad cuyo WorkingDirectory sea su directorio personal proporciona al agente ese directorio. Seleccione el espacio de trabajo en la interfaz o corrija la unidad y vuelva a cargarla.
FAQ
¿Es seguro exponer la interfaz web de DeepSeek Harness en el puerto 3080?
No. El servidor web no tiene autenticación propia y el agente que se ejecuta detrás edita archivos y ejecuta comandos de shell con la cuenta del usuario que inició el proceso. La clave de API del proveedor también se almacena en el mismo disco. Mantenga el listener en 127.0.0.1 y acceda a él mediante un túnel SSH. También puede usar una red superpuesta privada o un reverse proxy que autentique cada petición antes de que llegue al puerto. A partir de la versión 0.1.0-rc.6, la CLI rechaza --host 0.0.0.0 y termina con un error de uso. Esto muestra la opinión de los autores sobre esa configuración.
¿Necesito una clave de API de DeepSeek o puedo usar un modelo local?
Cualquiera de las dos opciones funciona porque el harness es un entorno de ejecución, no un modelo. En Settings y después en Models, puede pegar una clave en la tarjeta de un proveedor del catálogo. También puede elegir "Add a custom provider" y proporcionarle una URL base que use el protocolo compatible con OpenAI. Un servidor local de Ollama responde en http://127.0.0.1:11434/v1/ y acepta cualquier cadena en el campo de clave de API. Las claves se guardan en $DSH_HOME/.credentials.yaml, cuyo valor predeterminado es ~/.dsh/.credentials.yaml.
¿Qué permisos obtiene realmente un plugin de DeepSeek Harness al instalarlo?
Obtiene los permisos de la cuenta que ejecuta el harness. Un plugin es código Node cargado en el mismo proceso. Sus puntos de extensión incluyen el backend de shell, la capa del sistema de archivos, el registro de herramientas y los eventos que envuelven cada llamada a una herramienta. Ningún mecanismo aísla un plugin de esos puntos de integración, salvo que el propio plugin proporcione el aislamiento. Lea el código fuente antes de instalarlo y ejecute el harness con un usuario que no sea propietario de ningún recurso importante.
¿Qué versión debo instalar y seguirá funcionando?
Instale una versión exacta, por ejemplo npx @deepseek-ai/dsh@0.1.0-rc.6 web. Esa era la versión a la que apuntaba la etiqueta latest el 13 de agosto de 2026. El proyecto se define como una versión preliminar para desarrolladores y advierte que se esperan cambios incompatibles. Por tanto, un comando sin versión fijada puede comportarse de forma distinta de un día para otro. Compruebe el repositorio antes de actualizar y espere cambios en las claves de configuración y las interfaces de los plugins mientras la versión siga comenzando por 0.