SSD Nodes Learn Hosting plans →
Anleitungen Matt ConnorVon Matt Connor · Aktualisiert 2026-09-09

DSH-Weboberfläche auf dem VPS erreichen

DSH bindet an 127.0.0.1:3080. Die ausgegebene URL funktioniert nicht auf dem Laptop. Drei sichere Zugriffswege, darunter SSH-Tunnel, und eine riskante Methode.

Warum sich die DSH-Weboberfläche von Ihrem Laptop aus nicht öffnen lässt

Die DSH-Weboberfläche bindet an das Loopback-Interface. Daher funktioniert die von Ihrem Terminal ausgegebene URL nur auf dem Rechner, auf dem sie ausgegeben wurde. npx @deepseek-ai/dsh web meldet http://127.0.0.1:3080, und 127.0.0.1 bedeutet für jeden Rechner, der diese Adresse auswertet, „der Rechner, auf dem sie ausgewertet wird“. Ihr Laptop wertet die Adresse aus, prüft sein eigenes Loopback-Interface und findet dort keinen Prozess, der Verbindungen annimmt. Falls die Adresse selbst unklar ist, erklärt warum dsh überhaupt http://127.0.0.1:3080 ausgibt die Hintergründe ausführlicher. Ändern Sie nicht, an welches Interface DSH bindet. Richten Sie stattdessen einen authentifizierten Pfad von Ihrem Laptop zur Loopback-Adresse des VPS ein.

Der Loopback-Standard ist korrekt, und alle Methoden auf dieser Seite behalten ihn bei. Hinter Port 3080 läuft ein Agent, der Shell-Befehle auf Ihrem Server ausführt. Die Weboberfläche enthält keine Anmeldeseite. Das Loopback-Interface ist hier die einzige Zugriffskontrolle von DSH: Um den Socket zu erreichen, müssen Sie bereits eine Shell auf dem Server haben.

Woran DSH gebunden ist und wie Sie Ihre Konfiguration prüfen

Am 17. August 2026 geprüft: Die README von DeepSeek Harness sagt, dass npx @deepseek-ai/dsh web „die Weboberfläche startet, die standardmäßig unter http://127.0.0.1:3080 bereitgestellt wird“. Die CLI-Referenz im selben Repository dokumentiert --port <num> als Überschreibung mit dem Standardwert 3080 und --host <addr> als Überschreibung, die „0.0.0.0 absichtlich ablehnt“. DSH ist eine Entwicklervorschau. In der README wird in Großbuchstaben vor inkompatiblen Änderungen gewarnt. Bestätigen Sie beide Werte in Ihrer eigenen Installation, statt sich auf irgendeine Seite zu verlassen, auch nicht auf diese.

dsh --profile web --dump-config
ss -ltnp | grep 3080

--dump-config gibt den zusammengesetzten Konfigurationsbaum aus, ohne den Agenten zu starten. Dadurch sehen Sie den Host und den Port, die alle Patch-Ebenen überstehen. ss zeigt, worauf aktuell tatsächlich gelauscht wird. Eine funktionierende Zeile sieht so aus:

LISTEN 0  511  127.0.0.1:3080  0.0.0.0:*  users:(("node",pid=8123,fd=24))

Lesen Sie die Adresse vor dem Doppelpunkt und nichts weiter. 127.0.0.1:3080 ist nur an Loopback gebunden, was der gewünschte Zustand ist. 0.0.0.0:3080 bedeutet, dass alle Schnittstellen des Servers verwendet werden, einschließlich der öffentlichen Schnittstelle. Wenn ss überhaupt keine Zeile ausgibt, läuft DSH nicht. Kein Tunnel kann helfen, solange DSH nicht läuft. Wie Sie diesen Zustand erreichen, wird unter DeepSeek Harness auf einem VPS installieren und ausführen beschrieben.

Flags gelten nur für einen einzelnen Lauf. Damit ein Wert dauerhaft gilt, bearbeiten Sie stattdessen die Profil-Patch-Ebene. dsh --profile <name> startet das Profil unter $DSH_HOME/profiles/<name>. Die Ebenen werden in dieser Reihenfolge angewendet: Bundle-Patches, das eigene cordis.patch.yml des Profils, das $DSH_HOME/cordis.patch.yml auf Home-Ebene und anschließend ein beliebiges --patch-Overlay. Die Einstellungen für das Lauschen befinden sich unter dem @deepseek-ai/dsh-host-webserver-Plugin als host und port. Lesen Sie vor der Bearbeitung mit --dump-config Ihren eigenen zusammengesetzten Baum aus. Das Webprofil erstellt sich beim ersten Start aus einer mitgelieferten Vorlage, und die Entwicklervorschau ändert die Struktur dieser Vorlage weiterhin.

Das zweite Gate: die /api-Vertrauensgrenze

Pakete an Port 3080 zu senden, löst nur die Hälfte des Problems. DSH führt eine zweite Prüfung durch. Sie verursacht den verwirrenden Fehler, bei dem die Seite geladen wird, das Layout erscheint und anschließend nichts funktioniert.

Das @deepseek-ai/dsh-client-connection-Plugin enthält die Einstellung trustedHosts. Sie ist als „Authorities, die diese Bereitstellung über Loopback hinaus bedient: exaktes host:port oder portloses host, das jedem Port entspricht“ dokumentiert. Die Vertrauensgrenze lehnt jede /api-Anfrage ab, deren Host-Header weder Loopback enthält noch dort aufgeführt ist. Der Browser meldet die Ablehnung so:

transport failure for /api/host.describe: HTTP 403

Jeder Proxy vor DSH muss daher den Namen deklarieren, den der Browser verwendet. Die CLI akzeptiert --trusted-host <authority>. Die Option kann wiederholt werden:

dsh web --trusted-host dsh.example.com --trusted-host dsh.example.com:8443

Die Vertrauensgrenze vergleicht den Host-Header als einfachen String. Deshalb erscheinen oben beide Schreibweisen. dsh.example.com und dsh.example.com:8443 sind für diese Prüfung zwei verschiedene Authorities. Das gilt auch für localhost:3080 und 127.0.0.1:3080. Ein 403-Fehler, den Sie nicht erklären können, entsteht fast immer durch einen Unterschied zwischen der Schreibweise in der URL-Leiste und der Liste der vertrauenswürdigen Authorities.

Die Vertrauensgrenze prüft den Origin. Sie übernimmt keine Authentifizierung. Ein Browser darf den Host-Header nicht selbst setzen. Die Prüfung verhindert daher, dass eine Seite auf einer anderen Website Ihren Agent steuert. Jeder Client, der kein Browser ist, kann diesen Header frei setzen. Behandeln Sie trustedHosts als Kompatibilitätseinstellung für Proxys und niemals als Sicherheitskontrolle.

Option 1: lokales SSH-Forwarding

Verwenden Sie diese Option zuerst, weil sie am Server keinerlei Änderungen erfordert.

ssh -N -L 127.0.0.1:3080:127.0.0.1:3080 you@your-vps

-L öffnet auf Ihrem Laptop einen Listener und leitet jede Verbindung an 127.0.0.1:3080 weiter, wie sie auf dem VPS aufgelöst wird. -N bedeutet „keinen Remote-Befehl ausführen“. Die Sitzung transportiert daher nur das Forwarding und nichts anderes. Die lokale Seite als 127.0.0.1:3080 statt als bloßes 3080 zu schreiben, ist beabsichtigt: Dadurch wird der Listener auf dem Laptop an Loopback gebunden. So kann eine GatewayPorts-Einstellung in der SSH-Clientkonfiguration den Agent nicht unbemerkt im Netzwerk veröffentlichen, mit dem Sie gerade verbunden sind.

Öffnen Sie nun http://localhost:3080 in Ihrem Browser. Hier funktionieren zwei Dinge ohne weitere Konfiguration. Der Host-Header ist eine Loopback-Autorität, daher passiert die /api-Prüfung ohne zusätzliche Konfiguration. Außerdem behandeln Browser http://localhost als sicheren Kontext. Das ist wichtig, weil die DSH-Webanwendung beim Start crypto.randomUUID() aufruft. Browser stellen diese Funktion nur über HTTPS oder von einem Loopback-Ursprung aus bereit.

Fügen Sie -f hinzu, damit ssh sich selbst in den Hintergrund verschiebt, sobald das Forwarding aktiv ist:

ssh -f -N -L 127.0.0.1:3080:127.0.0.1:3080 you@your-vps

Der tatsächliche Nachteil: An einer öffentlichen Adresse wird nichts Neues geöffnet, und es ändern sich keine Firewall-Regeln. Damit ist dies die kleinstmögliche Erhöhung der Angriffsfläche. Ihre gesamte Zugriffskontrolle besteht aus Ihrer SSH-Konfiguration. Deshalb ist schlüsselbasiertes SSH mit deaktivierter Passwortanmeldung eine Voraussetzung und kein optionales Extra. Der Nachteil besteht darin, dass der Tunnel an eine einzelne Clientsitzung gebunden ist. Er endet, wenn der Laptop in den Ruhezustand wechselt. Sie müssen ihn manuell neu starten, und auf einem Smartphone steht er Ihnen nicht zur Verfügung.

Option 2: Tailscale serve auf dem VPS

Tailscale erstellt ein privates Netzwerk zwischen Ihren eigenen Geräten. Wenn Sie Tailscale auf dem VPS installieren, erhält dieser Rechner eine 100.x.y.z-Adresse, die nur Ihre Geräte erreichen können.

Der Beitritt zu diesem Netzwerk reicht nicht aus. Genau hier bleiben viele Anwender stecken. DSH lauscht nicht auf der 100.x.y.z-Adresse, weil der Dienst an Loopback gebunden ist. Ein Browser, der http://100.x.y.z:3080 aufruft, erhält eine Verbindungsablehnung, weil an diese Adresse kein Socket gebunden ist.

tailscale serve stellt die Verbindung zwischen beiden her. Der Dienst läuft auf dem VPS, akzeptiert Datenverkehr aus Ihrem privaten Netzwerk und leitet ihn an eine lokale Adresse weiter:

curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
sudo tailscale serve --bg --https=443 localhost:3080
tailscale serve status

tailscale serve status gibt die URL im Format https://<machine>.<tailnet>.ts.net/ aus. Starten Sie DSH mit diesem Namen als vertrauenswürdigem Namen. Andernfalls gibt /api wie oben beschrieben 403 zurück:

dsh web --trusted-host your-vps.your-tailnet.ts.net

Damit entfällt auch das Problem mit dem sicheren Kontext. Tailscale beendet echtes HTTPS mit einem Zertifikat, das für diesen Namen ausgestellt ist. Dadurch ist crypto.randomUUID() verfügbar, und die Benutzeroberfläche startet in einem Telefonbrowser. Nichts erreicht das öffentliche Internet, weil serve nur innerhalb Ihres privaten Netzwerks veröffentlicht.

Verwenden Sie hier nicht tailscale funnel. Dieser Befehl gehört zur selben Befehlsfamilie, ist aber für das öffentliche Internet bestimmt. Er würde einen Agenten mit Shell-Zugriff unter einem Hostnamen bereitstellen, den jeder auflösen kann. Lesen Sie wie serve den Datenverkehr innerhalb Ihres Tailnets hält, während funnel ihn veröffentlicht, bevor Sie einen der beiden Befehle eingeben. Die für ein Smartphone optimierte Variante dieser gesamten Einrichtung finden Sie unter einen selbst gehosteten Agenten vom Smartphone aus erreichen.

Der Nachteil ist eine zusätzliche Abhängigkeit. Jedes Gerät, das die Benutzeroberfläche benötigt, muss dem Netzwerk beitreten. Außerdem entscheidet ein Koordinationsserver, den Sie nicht selbst betreiben, welche Geräte daran teilnehmen. Wenn das nicht akzeptabel ist, verwendet ein selbst gehosteter Headscale-Koordinationsserver dasselbe Protokoll auf Hardware, die Ihnen gehört.

Option 3: ein authentifizierter TLS-Reverse-Proxy

Verwenden Sie diese Variante, wenn der Browser keinem privaten Netzwerk beitreten kann, beispielsweise auf einem Rechner, den Sie nicht administrieren. Sie veröffentlichen jetzt einen Hostnamen im Internet. Daher muss die Authentifizierung tatsächlich wirksam sein und vom Proxy bereitgestellt werden. DSH stellt keine Authentifizierung bereit.

TLS steht für Transport Layer Security, die Verschlüsselung hinter https://. Richten Sie nginx auf den Loopback-Port und schalten Sie ein Passwort davor. Der Block map gehört in den Kontext http. Legen Sie ihn daher in einer eigenen Datei unter /etc/nginx/conf.d/ ab:

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

Danach folgt die Site selbst:

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 Host              $host;
        proxy_set_header Upgrade           $http_upgrade;
        proxy_set_header Connection        $connection_upgrade;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 3600s;
        proxy_buffering    off;
    }
}

Erstellen Sie die Passwortdatei, testen Sie die Konfiguration und laden Sie sie neu:

sudo apt install -y apache2-utils
sudo htpasswd -c /etc/nginx/dsh.htpasswd you
sudo nginx -t && sudo systemctl reload nginx

nginx -t sollte syntax is ok und test is successful ausgeben. Wenn stattdessen ein Fehler ausgegeben wird, verwendet nginx weiterhin die alte Konfiguration. Daher ist noch nichts beschädigt. Starten Sie DSH anschließend mit dem öffentlichen Namen als vertrauenswürdigem Namen, weil proxy_set_header Host $host dsh.example.com weiterleitet und die Zugriffssperre die Weiterleitung andernfalls ablehnt:

dsh web --trusted-host dsh.example.com

Zwei Direktiven sind dabei entscheidend. Die Header Upgrade und Connection halten die langlebige Verbindung der Benutzeroberfläche offen. Ohne sie schließt nginx die Verbindung. Dadurch verbindet sich die Benutzeroberfläche in einer Schleife neu und zeigt veralteten Status an. proxy_read_timeout 3600s verhindert, dass nginx einen Agent-Lauf beendet, der länger als die standardmäßigen 60 Sekunden benötigt. Die Begründung für die übrigen Einstellungen finden Sie unter eine nginx-Reverse-Proxy-Konfiguration, Direktive für Direktive erklärt. Die Auswahl des Proxys wird unter nginx im Vergleich zu Caddy und Traefik erläutert.

Machen Sie sich klar, welchen Schutz Basic Authentication bietet. Sie hält zufällige Scanner ab und ist deutlich besser als ein offener Port. Sie verwendet jedoch nur ein gemeinsames Passwort vor einer Shell. Es gibt keinen zweiten Faktor und keine Möglichkeit, den Zugriff einer einzelnen Person zu entziehen. Jeder, der das Passwort kennt, kann Befehle unter dem Benutzer ausführen, unter dem DSH läuft. Wenn mehrere Personen Zugriff benötigen, schalten Sie stattdessen einen echten Identity Proxy davor. Lesen Sie außerdem die Sicherheitsregeln für den Betrieb eines Coding-Agenten auf einem VPS, bevor Sie den Zugriff weiter öffnen.

Was passiert, wenn Sie an 0.0.0.0 binden und den Port öffnen

Der naheliegende Weg wäre, den Dienst erneut zu binden und die Firewall zu öffnen. DSH verhindert den ersten Teil. --host <addr> weist 0.0.0.0 absichtlich zurück, und das Plugin @deepseek-ai/dsh-host-webserver dokumentiert host als Wert, der nur 127.0.0.1 oder 0.0.0.0 akzeptiert. Damit gibt es einen unterstützten Wert und einen zweiten, den die CLI ablehnt. Es gibt Community-Plugins, die diese Prüfung umgehen. Sie werden mit Warnungen ausgeliefert, und diese Warnungen sind berechtigt. Die Plugin-Schicht ist in umgekehrter Richtung deutlich nützlicher: Ausgabenlimits und Berechtigungsregeln für Tools schränken ein, was der Agent tun darf, statt den Bereich zu erweitern, auf dem er Verbindungen annimmt.

Wenn Sie die Bind-Adresse trotzdem erzwingen, geschieht Folgendes. Port 3080 antwortet auf Ihrer öffentlichen IP-Adresse. Es gibt keine Anmeldeseite. Die /api-Sperre prüft einen Host-Header, den jeder Client, der kein Browser ist, selbst setzt. Daher ändert es nichts, Ihre Adresse in trustedHosts einzutragen, wenn ein Angreifer über curl verfügt. Sie haben einen Agenten veröffentlicht, der Shell-Befehle mit Ihren Benutzerrechten ausführt, einschließlich der Zugangsdaten unter $DSH_HOME. Dort speichert DSH Profile und API-Schlüssel. Das ermöglicht Remote-Codeausführung auf Ihrem Server, einschließlich der damit verbundenen Kosten auf Ihrem Provider-Konto. Scanner durchsuchen kontinuierlich den gesamten Adressraum. Eine nicht veröffentlichte IP-Adresse ist daher keine Schutzmaßnahme. Jedes Geheimnis, das der Agent lesen kann, wird zusammen mit der Shell ausgegeben.

Alle oben beschriebenen Methoden verhindern, dass Sie dies tun müssen. Die SSH-Weiterleitung ist die richtige Standardlösung für eine Person auf einem Laptop. Verwenden Sie tailscale serve, wenn ein Telefon beteiligt ist oder Sie ein echtes Zertifikat benötigen. Den öffentlichen Reverse Proxy sollten Sie nur dann verwenden, wenn ein Browser, den Sie nicht verwalten, die Benutzeroberfläche erreichen muss. Davor muss eine echte Authentifizierung stehen.

FAQ

Warum wird http://127.0.0.1:3080 auf meinem Laptop nicht geöffnet?

Weil 127.0.0.1 für „das Gerät steht, das diese Adresse liest“. DSH gibt diese Adresse auf dem VPS aus, wo sie korrekt ist. Ihr Laptop liest dieselbe Zeichenfolge und greift auf sein eigenes Loopback-Interface zu, auf dem kein Dienst lauscht. Prüfen Sie die Serverseite auf dem VPS mit ss -ltnp | grep 3080. Eine Zeile mit 127.0.0.1:3080 bedeutet, dass DSH absichtlich an das Loopback-Interface gebunden ist. Sie benötigen einen Tunnel oder einen Proxy, keine andere Bind-Adresse.

Kann ich dsh web mit --host 0.0.0.0 ausführen?

Nein. Die am 17 August 2026 geprüfte CLI-Referenz des Repositorys dokumentiert --host <addr> als Override, das 0.0.0.0 absichtlich ablehnt. Der Grund ist, dass DSH Shell-Befehle ausführt und keine Anmeldeseite bereitstellt. Eine Bindung an alle Interfaces würde daher eine nicht authentifizierte Shell unter Ihrer öffentlichen IP-Adresse veröffentlichen. Community-Patches entfernen diese Prüfung. Wenn Sie einen solchen Patch anwenden, sind die Firewall und die Authentifizierung, die DSH nicht bereitstellt, Ihre Verantwortung.

Warum geben alle /api-Aufrufe hinter meinem Reverse Proxy HTTP 403 zurück?

Die Vertrauensprüfung /api lehnt jede Anfrage ab, deren Header Host weder eine Loopback-Adresse enthält noch in trustedHosts aufgeführt ist. Hinter einem Proxy enthält dieser Header Ihren öffentlichen Namen. Daher lehnt die Prüfung die Anfrage ab, und der Browser protokolliert transport failure for /api/host.describe: HTTP 403. Starten Sie DSH mit --trusted-host <your name> und übernehmen Sie die Schreibweise exakt. Das gilt auch für den Port, wenn Ihre URL einen enthält, da der Vergleich als literaler Zeichenfolgenvergleich erfolgt.

Warum wird die DSH-Oberfläche geladen, aber der Start über reines HTTP nie abgeschlossen?

Die Webanwendung ruft beim Start crypto.randomUUID() auf. Browser stellen diese Funktion nur in einem sicheren Kontext bereit: über HTTPS oder über einen Loopback-Ursprung wie http://localhost. Wird die Anwendung über reines HTTP von einer direkten IP-Adresse ausgeliefert, ist die Funktion nicht definiert. Die davon abhängigen Aufrufe lösen dadurch Fehler aus, und die Oberfläche wird nie vollständig aufgebaut. Die Bereitstellung über HTTPS mit tailscale serve oder über einen TLS-Reverse-Proxy behebt das Problem. Dasselbe gilt für den Zugriff über eine SSH-Weiterleitung auf http://localhost.

Welche Methode sollte ein einzelner Entwickler verwenden?

Die lokale SSH-Weiterleitung. Sie erfordert keine Änderungen am Server und an keinen Firewall-Regeln. Außerdem verwendet sie den SSH-Schlüssel, dem Sie bereits vertrauen. Führen Sie ssh -f -N -L 127.0.0.1:3080:127.0.0.1:3080 you@your-vps aus und öffnen Sie anschließend http://localhost:3080. Wechseln Sie zu tailscale serve, wenn Sie die Oberfläche auf einem Telefon verwenden möchten oder der Zugriff auch bestehen bleiben soll, wenn der Laptop in den Ruhezustand wechselt.