Qué significa dsh web en http://127.0.0.1:3080
dsh web muestra http://127.0.0.1:3080 porque la interfaz sólo escucha en localhost. Acceda con un túnel SSH y evite exponer el puerto 3080.
Qué significa dsh web: http://127.0.0.1:3080
Cuando inicia el perfil web de DeepSeek Harness en un VPS, muestra dos líneas y después espera:
dsh web: http://127.0.0.1:3080
Ready.127.0.0.1 es la dirección de loopback. Es la dirección que usa una máquina para comunicarse consigo misma. Un socket enlazado a 127.0.0.1 acepta conexiones de procesos de esa misma máquina y de ninguna otra. Por tanto, esa línea indica dos cosas a la vez: dónde está escuchando la interfaz web y quién puede acceder a ella. Sólo puede acceder la máquina en la que se está ejecutando dsh.
Por eso la URL no hace nada cuando la pega en el navegador de su portátil. El 127.0.0.1 de su portátil es el propio portátil. Harness está escuchando en el 127.0.0.1 del VPS, que es otra máquina con otra pila de loopback. No hay ningún fallo. Debe transportar la conexión entre ambas máquinas.
El README oficial indica claramente el valor predeterminado: "El comando inicia la interfaz web, disponible en http://127.0.0.1:3080 de forma predeterminada". La dirección de enlace procede del complemento de host del servidor web, @deepseek-ai/dsh-host-webserver, cuya clave host está documentada como "Host de escucha; los dos valores admitidos son loopback y todas las interfaces". El valor predeterminado es loopback, salvo que lo cambie. Si los puertos son un concepto nuevo para usted, cómo funcionan los puertos en Linux explica el modelo de dirección más puerto en el que se basa todo esto.
Por qué Web UI sólo se enlaza a localhost
dsh es un entorno de ejecución para agentes. La pestaña del navegador es una interfaz de control para un proceso que ejecuta comandos de shell, lee y escribe archivos en el directorio del espacio de trabajo que haya elegido y consume la clave de API de su modelo. Cualquiera que pueda cargar esa página puede hacer todo eso con los permisos del usuario que ejecuta dsh.
Por tanto, el puerto 3080 no es un panel de sólo lectura. Cargar esa página permite ejecutar comandos en el servidor.
Abra Web UI y accederá directamente a la lista de sesiones. No aparece ninguna solicitud de inicio de sesión porque la vista previa para desarrolladores no incluye cuentas de usuario ni autenticación remota. En la interfaz de loopback esto es coherente: el sistema operativo controla el acceso y sólo pueden conectarse los procesos locales. Enlace el mismo servidor a 0.0.0.0 en un VPS con una IP pública y esa misma página responderá a todo Internet, sin ningún control delante. Los escáneres automatizados recorren continuamente los puertos poco habituales, así que considere descubierto cualquier 3080 publicado.
No abra el puerto 3080 en el firewall ni configurehostdel servidor web como0.0.0.0en un VPS público. Esa combinación permite ejecutar comandos en su servidor a quien se conecte primero.
El mismo razonamiento se aplica a cualquier entorno de ejecución de agentes que instale en un servidor. Por eso ejecutar un agente de programación de forma segura en un VPS parte de la misma regla: el puerto de control del agente permanece privado y algo de confianza le proporciona el acceso.
¿Cómo abro la interfaz web de dsh desde mi portátil?
Hay tres opciones válidas, y todas mantienen el harness enlazado a loopback.
- Un túnel SSH. No se abre ningún servicio nuevo en la interfaz pública y ya dispone de las credenciales. Esta es la opción que debe usar.
- Una red superpuesta privada, para que la interfaz sea accesible desde sus propios dispositivos e invisible para los demás.
- Un proxy inverso que termina TLS (seguridad de la capa de transporte) y exige una contraseña antes de reenviar cualquier solicitud.
La diferencia entre estas opciones es el mecanismo que conecta el navegador con loopback. Ninguna debe implicar mover el harness fuera de loopback.
Acceder mediante un túnel SSH
Ejecute esto en su portátil, no en el VPS:
ssh -N -L 3080:127.0.0.1:3080 you@your-vpsDéjelo en ejecución y abra http://127.0.0.1:3080 en el navegador local. La interfaz web se carga.
El argumento -L contiene tres campos separados por dos puntos. El primero es el puerto que se abrirá en el portátil. El segundo y el tercero son la dirección y el puerto a los que se reenviará cada conexión. El detalle importante es que 127.0.0.1, situado en el campo central, lo resuelve el servidor SSH del VPS después de que el tráfico ya haya llegado allí. Se refiere al loopback del VPS, no al suyo. Esa es exactamente la dirección que mostró dsh, por lo que el túnel funciona aunque una conexión directa desde el navegador no funcione.
-N indica a SSH que no ejecute ningún comando remoto, por lo que obtiene un reenviador y no un shell. Para ejecutar un túnel en segundo plano y recibir errores explícitos:
ssh -N -f -o ExitOnForwardFailure=yes -o ServerAliveInterval=30 -L 3080:127.0.0.1:3080 you@your-vps-f lo envía al segundo plano después de la autenticación. ExitOnForwardFailure=yes es más importante de lo que parece: sin esta opción, SSH se conecta correctamente aunque no pueda configurar el reenvío. Así obtiene una sesión activa y un túnel inoperativo sin ninguna advertencia. ServerAliveInterval=30 envía un keepalive cada 30 segundos para que el túnel inactivo sobreviva a los tiempos de espera de NAT (traducción de direcciones de red) de los routers de cafeterías y hoteles.
Qué debe comprobar
En el VPS, confirme qué proceso está escuchando realmente:
ss -ltnp | grep 3080Un resultado correcto muestra la dirección de loopback:
LISTEN 0 511 127.0.0.1:3080 0.0.0.0:* users:(("node",pid=1042,fd=21))Si la columna de dirección local muestra 0.0.0.0:3080 en su lugar, la interfaz web está disponible en todas las interfaces, incluida la pública. Deténgala y corrija la dirección de escucha antes de hacer cualquier otra cosa. Si ss muestra el socket pero deja vacío el campo users:, ejecútelo con sudo, porque de lo contrario se oculta el nombre del proceso cuando el socket pertenece a otro usuario.
Cuando el túnel no se inicia
SSH muestra esto y termina:
bind [127.0.0.1]:3080: Address already in use
channel_setup_fwd_listener_tcpip: cannot listen to port: 3080El problema está en su portátil, no en el servidor. Algo local ya está usando el puerto 3080, a menudo un túnel anterior que olvidó cerrar. Elija otro puerto local libre:
ssh -N -L 3081:127.0.0.1:3080 you@your-vpsSólo cambió el primer campo, por lo que ahora debe abrir http://127.0.0.1:3081, mientras el arnés sigue escuchando en 3080. Los dos números no tienen que coincidir.
Si el túnel se inicia, pero el navegador informa de una conexión rechazada o de una respuesta vacía, el tráfico llegó al VPS y no encontró nada en el extremo remoto. Puede que dsh haya terminado o que se haya enlazado a otro puerto. Compruébelo con ss -ltnp | grep 3080 en el servidor.
Hay otro problema frecuente. Un npx @deepseek-ai/dsh web en primer plano termina cuando se cierra su shell, por lo que el arnés se detiene en cuanto cierra la sesión. Inícielo dentro de tmux o mediante un servicio de usuario de systemd. Es el mismo problema que se resuelve en mantener un agente de programación en ejecución en un VPS. Mientras trabaja en la parte de SSH, conviene reforzar SSH en su VPS primero, porque el túnel convierte su inicio de sesión SSH en la única puerta de acceso al agente.
Acceda a través de una red overlay privada
Una red overlay proporciona a su VPS y a su portátil direcciones en una red privada a la que sólo se conectan sus dispositivos. Tailscale es la opción habitual, y su comando serve encaja exactamente en este caso: tailscaled se ejecuta en el VPS y se conecta al propio localhost:3080, por lo que el harness permanece en loopback y no cambia nada de la configuración de dsh.
tailscale serve --bg localhost:3080
tailscale serve statusLa interfaz estará disponible en el nombre de su equipo dentro de su tailnet, mediante HTTPS y sin ningún puerto abierto en la interfaz pública. Para ello, debe habilitar los certificados HTTPS para su tailnet; de lo contrario, serve no tendrá ningún certificado que presentar. Para desactivarlo, repita el comando con off:
tailscale serve --https=443 offUse serve, nunca funnel. Funnel publica el mismo destino en Internet, lo que vuelve a dejar el runtime del agente sin autenticación y en un puerto abierto. Los dos comandos son casi idénticos, pero tienen efectos opuestos. Lea la diferencia entre Tailscale Serve y Funnel antes de ejecutar cualquiera de ellos. Tailscale como red privada explica la configuración.
Acceder mediante un reverse proxy que comprueba una contraseña
Esta es la opción que realmente publica un puerto en Internet, por lo que la autenticación es lo único que separa a un desconocido de la ejecución de comandos en el servidor. Elíjala cuando varias personas necesiten la interfaz y no sea práctico usar un túnel independiente para cada una.
El harness permanece en 127.0.0.1:3080. nginx se ejecuta en el mismo equipo, por lo que puede acceder a loopback, y escucha en 443 con un certificado y un archivo de contraseñas.
server {
listen 443 ssl;
server_name dsh.example.com;
ssl_certificate /etc/letsencrypt/live/dsh.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/dsh.example.com/privkey.pem;
auth_basic "dsh";
auth_basic_user_file /etc/nginx/dsh.htpasswd;
location / {
proxy_pass http://127.0.0.1:3080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 3600s;
proxy_buffering off;
}
}Cree el archivo de contraseñas y recargue la configuración:
sudo apt install -y apache2-utils
sudo htpasswd -c /etc/nginx/dsh.htpasswd you
sudo nginx -t && sudo systemctl reload nginxnginx -t debería mostrar syntax is ok seguido de test is successful. Una recarga con un archivo incorrecto falla y mantiene activa la configuración actual, por lo que debe leer el error en lugar de reiniciar a ciegas.
Tres de esas líneas del proxy no son decorativas. Las cabeceras Upgrade y Connection permiten completar el handshake de WebSocket. Sin ellas, la página se carga, pero nunca se actualiza. proxy_read_timeout 3600s reemplaza el valor predeterminado de 60 segundos. De lo contrario, interrumpe una ejecución larga del agente a mitad de la respuesta y la interfaz parece bloqueada. proxy_buffering off envía la salida del modelo al navegador a medida que llega, en lugar de retenerla hasta que termine la respuesta. Configuración de un reverse proxy de nginx, línea por línea explica el resto, y Cómo elegir entre nginx, Caddy y Traefik explica cómo hacer lo mismo con certificados automáticos.
Mantenga 3080 cerrado en el firewall independientemente del proxy que elija, para que el único acceso sea mediante el proxy autenticado. Conceptos básicos del firewall ufw explica las reglas. La autenticación básica sobre TLS es un nivel mínimo, no un modelo de seguridad completo: quien tenga esa contraseña tendrá acceso a un shell en el servidor. Prefiera el túnel siempre que sea posible.
¿Cómo cambio el puerto en el que escucha la interfaz web de dsh?
--port pertenece a la aplicación web, no al launcher. La documentación de CLI muestra directamente el ejemplo:
dsh --profile web --port 8080dsh web es un alias de --profile web, por lo que dsh web --port 8080 es el mismo comando. El launcher analiza sólo sus propias flags y entrega todo lo que aparece después al perfil iniciado. Por tanto, las flags del launcher deben ir primero, y el primer token que el launcher no reconoce inicia los argumentos de la aplicación. Coloque --port después del perfil, nunca antes.
Lea la URL que imprime el comando en lugar de darla por supuesta, porque esa línea indica la dirección a la que el servidor se ha asociado realmente. Después, actualice el último campo del túnel para que coincida:
ssh -N -L 3080:127.0.0.1:8080 you@your-vpsPara aplicar un cambio permanente, el puerto se configura en el perfil, no en la línea de comandos. Los perfiles web y headless se inicializan automáticamente en el primer uso a partir de las plantillas incluidas, en ~/.dsh. Para comprobar qué configuración está activa después de combinar todas las capas:
dsh --dump-configEl plugin del webserver expone exactamente dos claves: host y port. Establecer port en 0 solicita al sistema operativo un puerto libre; la documentación indica que «zero requests an OS-assigned port». Esto evita los conflictos de puerto, pero no es adecuado para un túnel porque el número cambia en cada reinicio.
¿Por qué dsh falla con «address already in use»?
Otro proceso ya tiene esa dirección y ese puerto, por lo que el kernel rechaza el segundo bind. Node lo muestra así:
Error: listen EADDRINUSE: address already in use 127.0.0.1:3080Identifique qué proceso lo tiene antes de cambiar nada:
sudo ss -ltnp | grep 3080El campo users:(("node",pid=1042,fd=21)) indica el proceso y su PID. Lo habitual es que se trate de un dsh anterior que creía detenido y que a menudo sigue activo en una ventana tmux desconectada. Deténgalo con kill 1042 o inicie la nueva instancia en otro puerto. Tenga en cuenta que 127.0.0.1:3080 y 0.0.0.0:3080 también entran en conflicto entre sí, porque enlazar todas las interfaces ya incluye loopback.
Fija la versión porque se trata de una versión preliminar para desarrolladores
El README lo indica claramente: DeepSeek Harness está en versión preliminar para desarrolladores, evoluciona rápidamente y habrá cambios que rompan la compatibilidad.
npx @deepseek-ai/dsh web se resuelve siempre en la versión publicada más reciente cada vez que se ejecuta. Un servidor que no se ha tocado durante una semana puede iniciar una CLI diferente en el siguiente arranque, con flags distintos. Fija la versión para que un reinicio no se convierta en una actualización:
npx @deepseek-ai/dsh@0.1.0-rc.7 webEn agosto de 2026, el paquete publicado es la versión 0.1.0-rc.7. Comprueba qué instalaría un npx sin versión fijada antes de aceptarlo:
npm view @deepseek-ai/dsh versionLos flags cambian entre el launcher y la aplicación web en las distintas versiones preliminares. Si --port deja de comportarse como se describe en esta guía, solicita a la aplicación su propia lista de flags en lugar de adivinar:
dsh --profile web --helpPara la instalación, la configuración del workspace y la clave del modelo, consulta instalar DeepSeek Harness en un VPS. Para una guía más breve centrada sólo en el acceso, acceder a la interfaz web de dsh en un VPS explica el túnel sin el razonamiento.
FAQ
¿Por qué no puedo abrir http://127.0.0.1:3080 en el navegador de mi laptop?
Porque 127.0.0.1 hace referencia al equipo desde el que escribe. La interfaz web de DeepSeek Harness está vinculada a la dirección de loopback del VPS, por lo que sólo los procesos del VPS pueden conectarse a ella. Su laptop tiene su propio loopback independiente y no hay ningún proceso escuchando en el puerto 3080. Reenvíe el puerto mediante SSH con ssh -N -L 3080:127.0.0.1:3080 you@your-vps y, después, cargue http://127.0.0.1:3080 de forma local. El campo intermedio del argumento -L se resuelve en el servidor, por lo que apunta al harness.
¿Es seguro vincular la interfaz web de dsh a 0.0.0.0 en un VPS público?
No. La interfaz web es la superficie de control de un agente que ejecuta comandos de shell y edita archivos con el usuario que ejecuta dsh, y la vista previa para desarrolladores no muestra ninguna pantalla de inicio de sesión. Vincularla a todas las interfaces de una IP pública permite que cualquiera que llegue al puerto 3080 ejecute comandos en el servidor. Mantenga el enlace en 127.0.0.1, mantenga el puerto 3080 cerrado en el firewall y use un túnel SSH, una red overlay privada o un proxy inverso que requiera una contraseña.
¿Cómo mantengo la interfaz web de dsh en ejecución después de cerrar la sesión SSH?
Un npx @deepseek-ai/dsh web en primer plano es un proceso hijo del shell de inicio de sesión, por lo que termina cuando ese shell sale. Inícielo dentro de una sesión de tmux y sepárelo con Ctrl-b d, o ejecútelo como un servicio de usuario de systemd con el modo lingering habilitado. El túnel y el harness son independientes: puede cerrar y volver a crear el túnel SSH tantas veces como quiera sin afectar al harness en ejecución, siempre que el propio harness tenga un proceso padre que sobreviva a su inicio de sesión.
¿Por qué la interfaz web de dsh se congela a mitad de una ejecución larga del agente detrás de nginx?
Porque el valor predeterminado de proxy_read_timeout en nginx es de 60 segundos. Por tanto, cierra una conexión que no produce datos durante un minuto, algo habitual durante un paso largo del agente. Configure proxy_read_timeout 3600s; en el bloque location. Añada proxy_buffering off; para que la salida se transmita al navegador a medida que llega y envíe las cabeceras Upgrade y Connection con proxy_http_version 1.1; para que el handshake de WebSocket se complete correctamente. Sin esas cabeceras, la página se carga, pero nunca recibe actualizaciones.