dsh Web: Warum http://127.0.0.1:3080 erscheint
dsh zeigt http://127.0.0.1:3080, weil die Weboberfläche nur auf localhost lauscht. Erreichen Sie sie sicher per SSH-Tunnel und geben Sie Port 3080 nicht frei.
Bedeutung von dsh web: http://127.0.0.1:3080
Wenn Sie das DeepSeek Harness-Webprofil auf einem VPS starten, gibt es zwei Zeilen aus und wartet dann:
dsh web: http://127.0.0.1:3080
Ready.127.0.0.1 ist die Loopback-Adresse. Über diese Adresse kommuniziert ein Rechner mit sich selbst. Ein Socket, der an 127.0.0.1 gebunden ist, nimmt Verbindungen von Prozessen auf demselben Rechner an, und von keinem anderen. Diese Zeile zeigt Ihnen daher gleichzeitig zwei Dinge: Wo die Weboberfläche Verbindungen entgegennimmt und wer darauf zugreifen darf. Das ist ausschließlich der Rechner, auf dem dsh läuft.
Deshalb bewirkt die URL nichts, wenn Sie sie in den Browser auf Ihrem Laptop einfügen. 127.0.0.1 auf Ihrem Laptop bezeichnet Ihren Laptop. Das Harness nimmt Verbindungen auf 127.0.0.1 des VPS entgegen. Dabei handelt es sich um einen anderen Rechner mit einem eigenen Loopback-Stack. Es ist nichts beschädigt. Sie müssen die Verbindung über den Netzwerkpfad weiterleiten.
Die offizielle README nennt den Standardwert eindeutig: „Der Befehl startet die Weboberfläche, die standardmäßig unter http://127.0.0.1:3080 bereitgestellt wird.“ Die Bind-Adresse stammt vom Webserver-Host-Plugin @deepseek-ai/dsh-host-webserver. Dessen Schlüssel host ist als „Listen-Host; die beiden unterstützten Werte sind Loopback und alle Schnittstellen“ dokumentiert. Ohne Änderung wird Loopback verwendet. Wenn Ports für Sie neu sind, erklärt wie Ports unter Linux funktionieren das Modell aus Adresse und Port, auf dem dies alles beruht.
Warum die Weboberfläche nur an localhost gebunden ist
dsh ist ein Agent-Harness. Der Browser-Tab dient als Steueroberfläche für einen Prozess, der Shell-Befehle ausführt, Dateien im von Ihnen ausgewählten Arbeitsverzeichnis liest und schreibt und Ihren Model-API-Schlüssel verwendet. Jeder, der diese Seite laden kann, kann all das mit den Rechten des Benutzers tun, unter dem dsh ausgeführt wird.
Port 3080 ist daher kein schreibgeschütztes Dashboard. Wer diese Seite lädt, kann Befehle auf dem Server ausführen.
Wenn Sie die Weboberfläche öffnen, gelangen Sie direkt zur Sitzungsliste. Es gibt keine Anmeldeaufforderung, weil die Developer Preview keine Benutzerkonten und keine Remote-Authentifizierung bereitstellt. Auf dem Loopback-Interface ist das konsistent: Das Betriebssystem übernimmt die Zugriffskontrolle, und nur lokale Prozesse können eine Verbindung herstellen. Binden Sie denselben Server auf einem VPS mit öffentlicher IP an 0.0.0.0, antwortet diese Seite aus dem gesamten Internet, ohne vorgeschaltete Zugriffskontrolle. Automatisierte Scanner durchsuchen kontinuierlich auch ungewöhnliche Ports. Behandeln Sie einen veröffentlichten Port 3080 daher als gefunden.
Öffnen Sie Port 3080 nicht in Ihrer Firewall und setzen Siehostdes Webservers auf einem öffentlichen VPS nicht auf0.0.0.0. Diese Kombination ermöglicht jedem, der zuerst eine Verbindung herstellt, die Ausführung von Befehlen auf Ihrem Server.
Dieselbe Überlegung gilt für jede Agent-Laufzeit, die Sie auf einem Server einsetzen. Deshalb beginnt auch das sichere Ausführen eines Coding-Agenten auf einem VPS mit derselben Regel: Der Steuerport des Agenten bleibt privat, und ein vertrauenswürdiger Dienst stellt die Verbindung zu ihm her.
Wie öffne ich die dsh-Weboberfläche von meinem Laptop aus?
Es gibt drei sinnvolle Möglichkeiten. Bei allen bleibt der Harness an die Loopback-Schnittstelle gebunden.
- Ein SSH-Tunnel. Dabei lauscht nichts Neues an der öffentlichen Schnittstelle, und Sie verfügen bereits über die Zugangsdaten. Diese Methode sollten Sie verwenden.
- Ein privates Overlay-Netzwerk. Dadurch ist die Weboberfläche von Ihren eigenen Geräten aus erreichbar und für alle anderen unsichtbar.
- Ein Reverse Proxy, der TLS (Transport Layer Security) terminiert und ein Kennwort verlangt, bevor er eine Anfrage weiterleitet.
Der Unterschied besteht darin, was die Verbindung Ihres Browsers zur Loopback-Schnittstelle herstellt. Keine dieser Methoden sollte den Harness von der Loopback-Schnittstelle lösen.
Erreichen Sie ihn mit einem SSH-Tunnel
Führen Sie diesen Befehl auf Ihrem Laptop aus, nicht auf dem VPS:
ssh -N -L 3080:127.0.0.1:3080 you@your-vpsLassen Sie den Befehl laufen und öffnen Sie anschließend http://127.0.0.1:3080 in Ihrem lokalen Browser. Die Weboberfläche wird geladen.
Das Argument -L enthält drei durch Doppelpunkte getrennte Felder. Das erste Feld ist der Port, der auf Ihrem Laptop geöffnet wird. Das zweite und dritte Feld geben die Adresse und den Port an, an die jede Verbindung weitergeleitet wird. Entscheidend ist: 127.0.0.1 im mittleren Feld wird vom 127.0.0.1-SSH-Server auf dem VPS aufgelöst, nachdem Ihr Datenverkehr dort bereits angekommen ist. Gemeint ist die Loopback-Adresse des VPS, nicht die Ihres Laptops. Genau diese Adresse hat dsh ausgegeben. Deshalb funktioniert der Tunnel, während eine direkte Browserverbindung fehlschlägt.
-N weist SSH an, keinen Remote-Befehl auszuführen. Sie erhalten dadurch nur eine Weiterleitung und keine Shell. Für einen Hintergrundtunnel, der Fehler deutlich meldet, statt sie still zu ignorieren:
ssh -N -f -o ExitOnForwardFailure=yes -o ServerAliveInterval=30 -L 3080:127.0.0.1:3080 you@your-vps-f verschiebt den Prozess nach der Authentifizierung in den Hintergrund. ExitOnForwardFailure=yes ist wichtiger, als es zunächst scheint: Ohne diese Option stellt SSH auch dann erfolgreich eine Verbindung her, wenn die Weiterleitung nicht eingerichtet werden konnte. Sie erhalten dann eine funktionierende Sitzung, aber einen inaktiven Tunnel ohne Warnung. ServerAliveInterval=30 sendet alle 30 Sekunden ein Keepalive, damit ein inaktiver Tunnel Timeouts für NAT (Network Address Translation) auf Routern in Cafés und Hotels übersteht.
Was Sie sehen sollten
Prüfen Sie auf dem VPS, welcher Dienst tatsächlich lauscht:
ss -ltnp | grep 3080Ein korrektes Ergebnis nennt die Loopback-Adresse:
LISTEN 0 511 127.0.0.1:3080 0.0.0.0:* users:(("node",pid=1042,fd=21))Wenn in der Spalte für die lokale Adresse stattdessen 0.0.0.0:3080 steht, ist die Weboberfläche an alle Schnittstellen gebunden, einschließlich der öffentlichen Schnittstelle. Beenden Sie den Dienst und korrigieren Sie die Bind-Adresse, bevor Sie etwas anderes tun. Wenn ss den Socket ausgibt, das Feld users: jedoch leer bleibt, führen Sie den Befehl mit sudo aus. Andernfalls wird der Prozessname eines Sockets, der einem anderen Benutzer gehört, ausgeblendet.
Wenn der Tunnel nicht gestartet werden kann
SSH gibt diese Meldung aus und beendet sich:
bind [127.0.0.1]:3080: Address already in use
channel_setup_fwd_listener_tcpip: cannot listen to port: 3080Das betrifft Ihren Laptop, nicht den Server. Ein lokaler Prozess verwendet bereits Port 3080. Häufig handelt es sich um einen früheren Tunnel, den Sie vergessen haben. Wählen Sie stattdessen einen freien lokalen Port:
ssh -N -L 3081:127.0.0.1:3080 you@your-vpsNur das erste Feld wurde geändert. Sie öffnen nun http://127.0.0.1:3081 im Browser, während der Tunnel weiterhin auf Port 3080 lauscht. Die beiden Portnummern müssen nicht übereinstimmen.
Wenn der Tunnel startet, der Browser jedoch eine verweigerte Verbindung oder eine leere Antwort meldet, hat der Datenverkehr den VPS erreicht, dort aber am Ziel nichts gefunden. Entweder wurde dsh beendet oder der Dienst wurde an einen anderen Port gebunden. Prüfen Sie dies mit ss -ltnp | grep 3080 auf dem Server.
Ein weiterer Punkt führt hier häufig zu Problemen. Ein npx @deepseek-ai/dsh web im Vordergrund wird beendet, sobald die Shell geschlossen wird. Dadurch beendet der Harness den Prozess, sobald Sie sich abmelden. Starten Sie ihn innerhalb von tmux oder unter einem systemd-Benutzerdienst. Damit wird dasselbe Problem gelöst wie in einen Coding-Agent auf einem VPS weiterlaufen lassen. Während Sie die SSH-Seite bearbeiten, lohnt es sich, zuerst SSH auf Ihrem VPS abzusichern, weil der Tunnel Ihren SSH-Login zum einzigen Zugang zum Agenten macht.
Über ein privates Overlay-Netzwerk darauf zugreifen
Ein Overlay-Netzwerk weist Ihrem VPS und Ihrem Laptop Adressen in einem privaten Netzwerk zu, dem nur Ihre Geräte beitreten. Tailscale ist die gängige Wahl. Der Befehl serve passt genau zu diesem Fall: tailscaled wird auf dem VPS ausgeführt und verbindet localhost:3080 mit sich selbst. Dadurch bleibt der Harness an Loopback gebunden, und Sie müssen die Konfiguration von dsh nicht ändern.
tailscale serve --bg localhost:3080
tailscale serve statusDie Benutzeroberfläche ist anschließend über den Namen Ihres Computers in Ihrem Tailnet per HTTPS erreichbar, ohne dass ein Port auf der öffentlichen Schnittstelle geöffnet wird. Dafür müssen HTTPS-Zertifikate für Ihr Tailnet aktiviert sein. Andernfalls kann serve kein Zertifikat vorlegen. Um den Zugriff wieder zu deaktivieren, führen Sie den Befehl mit off erneut aus:
tailscale serve --https=443 offVerwenden Sie serve, niemals funnel. Funnel veröffentlicht dasselbe Ziel im öffentlichen Internet. Dadurch läuft der Agent wieder unauthentifiziert an einem offenen Port. Die beiden Befehle sehen fast identisch aus, bewirken aber das Gegenteil. Lesen Sie daher den Unterschied zwischen Tailscale Serve und Funnel, bevor Sie einen der beiden Befehle eingeben. Tailscale als privates Netzwerk beschreibt die Einrichtung selbst.
Erreichen Sie den Dienst über einen Reverse Proxy mit Passwortprüfung
Dies ist die Option, bei der tatsächlich ein Port ins Internet veröffentlicht wird. Die Authentifizierung ist damit die einzige Hürde zwischen einer fremden Person und der Befehlsausführung auf Ihrem Server. Wählen Sie diese Option, wenn mehrere Personen die Benutzeroberfläche benötigen und ein eigener Tunnel pro Person nicht praktikabel ist.
Der Harness bleibt auf 127.0.0.1:3080. nginx läuft auf demselben System, kann daher den Loopback erreichen und lauscht auf Port 443 mit einem Zertifikat und einer Passwortdatei.
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;
}
}Erstellen Sie die Passwortdatei und laden Sie die Konfiguration neu:
sudo apt install -y apache2-utils
sudo htpasswd -c /etc/nginx/dsh.htpasswd you
sudo nginx -t && sudo systemctl reload nginxnginx -t sollte syntax is ok gefolgt von test is successful ausgeben. Das Neuladen mit einer fehlerhaften Datei schlägt fehl und lässt die laufende Konfiguration unverändert. Lesen Sie daher die Fehlermeldung, statt den Dienst blind neu zu starten.
Drei dieser Proxy-Zeilen sind erforderlich. Die Header Upgrade und Connection ermöglichen den WebSocket-Handshake. Ohne sie wird die Seite geladen, aber nicht aktualisiert. proxy_read_timeout 3600s ersetzt den Standardwert von 60 Sekunden. Andernfalls wird eine lange Agent-Ausführung mitten in der Antwort abgebrochen, und die Benutzeroberfläche wirkt eingefroren. proxy_buffering off sendet die Modellausgabe beim Eintreffen an den Browser, statt sie bis zum Abschluss der Antwort zurückzuhalten. Eine nginx-Reverse-Proxy-Konfiguration, Zeile für Zeile erklärt die übrigen Einstellungen. Auswahl zwischen nginx, Caddy und Traefik beschreibt dieselbe Einrichtung mit automatischen Zertifikaten.
Lassen Sie Port 3080 unabhängig von der Wahl des Proxy an der Firewall geschlossen. Der einzige Zugangsweg soll über den authentifizierten Proxy führen. Grundlagen der ufw-Firewall beschreibt die erforderlichen Regeln. Basic Authentication über TLS ist nur eine Mindestmaßnahme und kein vollständiges Sicherheitsmodell: Wer dieses Passwort besitzt, hat eine Shell auf Ihrem Server. Verwenden Sie nach Möglichkeit den Tunnel.
Wie ändere ich den Port, auf dem dsh auf Webanfragen wartet?
--port gehört zur Webanwendung, nicht zum Launcher. Die CLI-Dokumentation enthält direkt das folgende Beispiel:
dsh --profile web --port 8080dsh web ist ein Alias für --profile web. Daher ist dsh web --port 8080 derselbe Befehl. Der Launcher wertet nur seine eigenen Flags aus und übergibt alles danach an das gestartete Profil. Die Flags des Launchers müssen daher zuerst kommen. Das erste Token, das der Launcher nicht erkennt, leitet die Argumente der Anwendung ein. Setzen Sie --port nach dem Profil, niemals davor.
Lesen Sie die URL, die der Befehl ausgibt, statt sie anzunehmen. Diese Zeile enthält die Adresse, an die der Server tatsächlich gebunden ist. Passen Sie anschließend das letzte Feld Ihres Tunnels entsprechend an:
ssh -N -L 3080:127.0.0.1:8080 you@your-vpsFür eine dauerhafte Änderung wird der Port in der Profilkonfiguration statt in der Befehlszeile festgelegt. Die Profile web und headless werden bei der ersten Verwendung automatisch anhand der mitgelieferten Vorlagen unter ~/.dsh initialisiert. So sehen Sie, welche Einstellungen nach dem Zusammenführen aller Ebenen tatsächlich wirksam sind:
dsh --dump-configDas Webserver-Plugin stellt genau zwei Schlüssel bereit: host und port. Wenn Sie port auf 0 setzen, fordert das Betriebssystem einen freien Port an. Dies ist mit „zero requests an OS-assigned port“ dokumentiert. Dadurch vermeiden Sie Portkonflikte, für einen Tunnel ist diese Einstellung jedoch ungeeignet, weil sich die Portnummer bei jedem Neustart ändert.
Warum schlägt dsh mit „address already in use“ fehl?
Weil ein anderer Prozess diese Adresse und diesen Port bereits verwendet. Der Kernel verweigert deshalb das zweite Binden. Node meldet den Fehler folgendermaßen:
Error: listen EADDRINUSE: address already in use 127.0.0.1:3080Ermitteln Sie den belegenden Prozess, bevor Sie etwas ändern:
sudo ss -ltnp | grep 3080Das Feld users:(("node",pid=1042,fd=21)) nennt den Prozess und seine PID. In der Regel handelt es sich um eine frühere dsh-Instanz, die Sie bereits beendet glaubten, die aber häufig noch in einem abgetrennten tmux-Fenster läuft. Beenden Sie diese mit kill 1042 oder starten Sie die neue Instanz an einem anderen Port. Beachten Sie, dass 127.0.0.1:3080 und 0.0.0.0:3080 ebenfalls miteinander kollidieren, weil das Binden an alle Schnittstellen die Loopback-Schnittstelle bereits einschließt.
Version festschreiben, da es sich um eine Entwicklervorschau handelt
Die README weist ausdrücklich darauf hin: DeepSeek Harness befindet sich in der Entwicklervorschau und wird schnell weiterentwickelt. Daher wird es zu inkompatiblen Änderungen kommen.
npx @deepseek-ai/dsh web löst bei jedem Aufruf die neueste veröffentlichte Version auf. Ein Server, den Sie eine Woche lang nicht angefasst haben, kann beim nächsten Start eine andere CLI mit anderen Flags ausführen. Schreiben Sie die Version fest, damit ein Neustart kein Upgrade ausführt:
npx @deepseek-ai/dsh@0.1.0-rc.7 webIm August 2026 ist das veröffentlichte Paket Version 0.1.0-rc.7. Prüfen Sie, welche Version ein Aufruf von npx ohne weitere Angaben installieren würde, bevor Sie ihn übernehmen:
npm view @deepseek-ai/dsh versionBei Preview-Releases werden Flags zwischen dem Launcher und der Webanwendung verschoben. Wenn --port nicht mehr wie in dieser Anleitung beschrieben funktioniert, fragen Sie die Anwendung nach ihrer eigenen Flag-Liste, statt die Optionen zu erraten:
dsh --profile web --helpInformationen zur Installation, zur Einrichtung des Workspace und zum Model-Key finden Sie unter DeepSeek Harness auf einem VPS installieren. Eine kürzere Anleitung nur für den Zugriffsschritt finden Sie unter Die dsh-Weboberfläche auf einem VPS erreichen. Dort wird der Tunnel ohne die Begründung beschrieben.
FAQ
Warum kann ich http://127.0.0.1:3080 im Browser meines Laptops nicht öffnen?
Weil 127.0.0.1 den Rechner bezeichnet, auf dem Sie den Befehl eingeben. Die DeepSeek Harness Web UI ist an die Loopback-Adresse des VPS gebunden. Daher können nur Prozesse auf dem VPS eine Verbindung herstellen. Ihr Laptop hat eine eigene, separate Loopback-Adresse. Dort lauscht kein Dienst auf Port 3080. Leiten Sie den Port mit ssh -N -L 3080:127.0.0.1:3080 you@your-vps über SSH weiter. Öffnen Sie anschließend lokal http://127.0.0.1:3080. Das mittlere Feld des Arguments -L wird serverseitig aufgelöst. Dadurch verweist es auf das Harness.
Ist es sicher, die dsh Web UI auf einem öffentlichen VPS an 0.0.0.0 zu binden?
Nein. Die Web UI ist die Steuerungsschnittstelle für einen Agenten, der Shell-Befehle ausführt und Dateien als der Benutzer bearbeitet, unter dem dsh läuft. Die Developer Preview bietet überhaupt keine Anmeldemaske. Wenn der Dienst an alle Schnittstellen einer öffentlichen IP-Adresse gebunden ist, kann jeder, der Port 3080 erreicht, Befehle auf Ihrem Server ausführen. Lassen Sie die Bind-Adresse auf 127.0.0.1. Halten Sie Port 3080 in der Firewall geschlossen. Verwenden Sie stattdessen einen SSH-Tunnel, ein privates Overlay-Netzwerk oder einen Reverse Proxy mit Passwortschutz.
Wie läuft die dsh Web UI weiter, nachdem ich meine SSH-Sitzung beendet habe?
Ein npx @deepseek-ai/dsh web im Vordergrund ist ein Kindprozess Ihrer Login-Shell. Daher wird es beendet, wenn diese Shell beendet wird. Starten Sie es innerhalb einer tmux-Sitzung und trennen Sie die Sitzung mit Ctrl-b d. Alternativ können Sie es als systemd-Benutzerdienst mit aktiviertem Lingering ausführen. Der Tunnel und das Harness sind unabhängig voneinander. Sie können den SSH-Tunnel beliebig oft trennen und neu aufbauen, ohne das laufende Harness zu beeinflussen. Voraussetzung ist, dass das Harness selbst einen übergeordneten Prozess hat, der länger als Ihre Login-Sitzung läuft.
Warum friert die dsh Web UI bei einem langen Agentenlauf hinter nginx nach einiger Zeit ein?
Weil nginx standardmäßig proxy_read_timeout auf 60 Sekunden setzt. Dadurch schließt nginx eine Verbindung, über die eine Minute lang keine Daten übertragen werden. Das kann bei einem langen Agentenschritt problemlos passieren. Setzen Sie proxy_read_timeout 3600s; im Block location. Fügen Sie proxy_buffering off; hinzu, damit die Ausgabe beim Eintreffen an den Browser übertragen wird. Übergeben Sie außerdem die Header Upgrade und Connection mit proxy_http_version 1.1;, damit der WebSocket-Handshake erfolgreich ist. Ohne diese Header wird die Seite geladen, empfängt aber keine Aktualisierungen.