DeepSeek Harness: waarom 127.0.0.1:3080 niet werkt
De melding http://127.0.0.1:3080 verschijnt omdat de Web UI enkel op localhost bindt. Leer hoe u veilig verbinding maakt via een SSH tunnel in plaats van poort 3080 open te stellen.
Wat dsh web: http://127.0.0.1:3080 betekent
Wanneer u het DeepSeek Harness webprofiel op een VPS start, worden er twee regels weergegeven en wacht het programma vervolgens:
dsh web: http://127.0.0.1:3080
Ready.127.0.0.1 is het loopback-adres. Dit is het adres dat een machine gebruikt om met zichzelf te communiceren. Een socket die is gebonden aan 127.0.0.1 accepteert alleen verbindingen van processen op diezelfde machine, en nergens anders vandaan. Die regel vertelt u dus twee dingen tegelijk: waar de Web UI luistert en wie er toegang toe heeft. Alleen de machine waarop dsh draait.
Dat is de reden waarom de URL niet werkt wanneer u deze in de browser op uw laptop plakt. De 127.0.0.1 van uw laptop is uw laptop zelf. De harness luistert op de 127.0.0.1 van de VPS, wat een andere machine is met een eigen loopback-stack. Er is niets defect. U moet de verbinding overbruggen.
De officiële README vermeldt de standaardinstelling duidelijk: "Het commando start de Web UI, die standaard wordt geserveerd op http://127.0.0.1:3080." Het bind-adres is afkomstig van de webserver host-plugin, @deepseek-ai/dsh-host-webserver, waarvan de host-sleutel wordt gedocumenteerd als "Listen host; de twee ondersteunde waarden zijn loopback en all-interfaces". Loopback is wat u krijgt tenzij u dit wijzigt. Als poorten nieuw voor u zijn, behandelt hoe poorten werken op Linux het adres-plus-poortmodel waarop dit alles is gebaseerd.
Waarom de Web UI alleen aan localhost bindt
dsh is een agent-harness. Het browsertabblad fungeert als bedieningspaneel voor een proces dat shell-commando's uitvoert, bestanden in de door u gekozen werkmap leest en schrijft, en uw model API-key verbruikt. Iedereen die die pagina kan laden, kan dit alles doen als de gebruiker die dsh uitvoert.
Poort 3080 is dus geen dashboard met alleen-lezenrechten. Het laden van die pagina geeft de mogelijkheid om commando's op de server uit te voeren.
Open de Web UI en u komt direct in de sessielijst terecht. Er is geen inlogscherm, omdat de developer preview geen gebruikersaccounts en geen externe authenticatie bevat. Op loopback is dit consistent: het besturingssysteem fungeert als toegangscontrole en alleen lokale processen krijgen toegang. Bindt u dezelfde server aan 0.0.0.0 op een VPS met een publiek IP-adres, dan reageert diezelfde pagina op het gehele internet, zonder enige beveiliging ervoor. Geautomatiseerde scanners scannen continu op ongebruikelijke poorten, dus beschouw een gepubliceerde 3080 als gevonden.
Open poort 3080 niet in uw firewall en stel de webserverhostniet in op0.0.0.0op een publieke VPS. Die combinatie geeft de mogelijkheid tot commando-uitvoering op uw server aan degene die als eerste verbinding maakt.
Dezelfde redenering geldt voor elke agent-runtime die u op een server plaatst. Daarom begint het veilig draaien van een coding agent op een VPS met dezelfde regel: de controlepoort van de agent blijft privé en u gebruikt een vertrouwde methode om er toegang toe te krijgen.
Hoe open ik de dsh Web UI vanaf mijn laptop?
Er zijn drie betrouwbare methoden, en bij elk daarvan blijft de harness gebonden aan loopback.
- Een SSH-tunnel. Er luistert niets nieuws op de publieke interface en u beschikt al over de inloggegevens. Dit is de aanbevolen methode.
- Een privaat overlay-netwerk, zodat de UI bereikbaar is vanaf uw eigen apparaten en onzichtbaar blijft voor anderen.
- Een reverse proxy die TLS (transport layer security) termineert en om een wachtwoord vraagt voordat er verkeer wordt doorgestuurd.
Het verschil tussen deze methoden is de manier waarop uw browser naar loopback wordt geleid. Geen van deze methoden vereist dat de harness van loopback wordt gehaald.
Bereik het via een SSH-tunnel
Voer dit uit op uw laptop, niet op de VPS:
ssh -N -L 3080:127.0.0.1:3080 you@your-vpsLaat dit draaien en open vervolgens http://127.0.0.1:3080 in uw lokale browser. De Web UI wordt geladen.
Het argument -L bevat drie velden gescheiden door dubbele punten. Het eerste is de poort die op uw laptop wordt geopend. Het tweede en derde veld zijn het adres en de poort waarheen elke verbinding moet worden doorgestuurd. Het cruciale detail: 127.0.0.1 in het middelste veld wordt door de SSH-server op de VPS opgelost, nadat uw verkeer daar al is aangekomen. Dit betekent de loopback van de VPS, niet die van u. Dat is precies het adres dat dsh toonde, en daarom werkt de tunnel terwijl een directe browserverbinding dat niet doet.
-N vertelt SSH om geen extern commando uit te voeren, zodat u een forwarder krijgt en geen shell. Voor een achtergrondtunnel die luidruchtig faalt in plaats van stilzwijgend:
ssh -N -f -o ExitOnForwardFailure=yes -o ServerAliveInterval=30 -L 3080:127.0.0.1:3080 you@your-vps-f plaatst het proces op de achtergrond na authenticatie. ExitOnForwardFailure=yes is belangrijker dan het lijkt: zonder dit argument verbindt SSH succesvol, zelfs als de forward niet kon worden opgezet. U krijgt dan een werkende sessie en een dode tunnel zonder waarschuwing. ServerAliveInterval=30 stuurt elke 30 seconden een keepalive, zodat een inactieve tunnel NAT-timeouts (network address translation) op café- en hotelrouters overleeft.
Wat u zou moeten zien
Controleer op de VPS wat er daadwerkelijk luistert:
ss -ltnp | grep 3080Een gezond resultaat toont het loopback-adres:
LISTEN 0 511 127.0.0.1:3080 0.0.0.0:* users:(("node",pid=1042,fd=21))Als de kolom voor het lokale adres in plaats daarvan 0.0.0.0:3080 aangeeft, staat de Web UI op elke interface, inclusief de publieke. Stop het proces en corrigeer de bind voordat u iets anders doet. Als ss de socket toont maar het veld users: leeg laat, voer het dan uit met sudo, omdat de procesnaam voor een socket die eigendom is van een andere gebruiker anders verborgen blijft.
Wanneer de tunnel weigert te starten
SSH geeft dit weer en sluit af:
bind [127.0.0.1]:3080: Address already in use
channel_setup_fwd_listener_tcpip: cannot listen to port: 3080Dit betreft uw laptop, niet de server. Iets lokaal bezet poort 3080 al, vaak een eerdere tunnel die u bent vergeten. Kies in plaats daarvan een vrije lokale poort:
ssh -N -L 3081:127.0.0.1:3080 you@your-vpsAlleen het eerste veld is gewijzigd, dus u surft nu naar http://127.0.0.1:3081 terwijl de harness op 3080 blijft luisteren. De twee getallen hoeven nooit overeen te komen.
Als de tunnel wel opkomt maar de browser een geweigerde verbinding of een lege reactie rapporteert, is het verkeer naar de VPS gegaan en vond daar niets aan de andere kant. Ofwel dsh is afgesloten, of het proces is gebonden aan een andere poort. Controleer dit met ss -ltnp | grep 3080 op de server.
Nog één ding waar mensen hier tegenaan lopen. Een npx @deepseek-ai/dsh web op de voorgrond sterft wanneer de shell sluit, dus de harness stopt zodra u uitlogt. Start het binnen tmux of onder een systemd user service; dit is hetzelfde probleem als opgelost in een coding agent draaiende houden op een VPS. Terwijl u aan de SSH-kant werkt, is het de moeite waard om eerst SSH op uw VPS te beveiligen, omdat de tunnel uw SSH-login de enige toegangspoort tot de agent maakt.
Bereik het via een privaat overlay-netwerk
Een overlay-netwerk voorziet uw VPS en uw laptop van adressen op een privaat netwerk waar alleen uw apparaten lid van zijn. Tailscale is de gangbare keuze en het serve-commando past precies in dit scenario: tailscaled draait op de VPS en verbindt met localhost:3080 zelf, waardoor de harness op loopback blijft en u niets hoeft te wijzigen aan de configuratie van dsh.
tailscale serve --bg localhost:3080
tailscale serve statusDe UI is vervolgens bereikbaar via de naam van uw machine binnen uw tailnet, via HTTPS, zonder dat er een poort openstaat op de publieke interface. Hiervoor moeten HTTPS-certificaten zijn ingeschakeld voor uw tailnet, anders heeft serve geen certificaat om te presenteren. Om dit weer ongedaan te maken, herhaalt u het commando met off:
tailscale serve --https=443 offGebruik serve, nooit funnel. Funnel publiceert hetzelfde doel naar het publieke internet, waardoor u weer terug bent bij een niet-geauthenticeerde agent-runtime op een open poort. De twee commando's lijken bijna identiek en doen tegenovergestelde dingen, dus lees het verschil tussen Tailscale Serve en Funnel voordat u een van beide typt. Tailscale als privaat netwerk behandelt de installatie zelf.
Toegang via een reverse proxy met wachtwoordbeveiliging
Dit is de optie waarbij een poort daadwerkelijk wordt blootgesteld aan het internet. Authenticatie is hierbij de enige barrière tussen een buitenstaander en het uitvoeren van commando's op uw server. Kies voor deze methode wanneer meerdere personen de UI nodig hebben en een individuele tunnel voor iedereen onpraktisch is.
De harness blijft op 127.0.0.1:3080 draaien. nginx draait op dezelfde machine, waardoor deze loopback kan bereiken. De proxy luistert op poort 443 met een certificaat en een wachtwoordbestand.
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;
}
}Maak het wachtwoordbestand aan en herlaad de configuratie:
sudo apt install -y apache2-utils
sudo htpasswd -c /etc/nginx/dsh.htpasswd you
sudo nginx -t && sudo systemctl reload nginxnginx -t hoort syntax is ok te tonen, gevolgd door test is successful. Een herlaadactie met een foutief bestand mislukt en behoudt de actieve configuratie; lees daarom de foutmelding in plaats van blindelings te herstarten.
Drie van deze proxy-regels zijn geen decoratie. De headers Upgrade en Connection laten de WebSocket-handshake door; zonder deze headers laadt de pagina wel, maar vindt er geen update plaats. proxy_read_timeout 3600s vervangt de standaardwaarde van 60 seconden, die anders een langdurige agent-run halverwege afbreekt, waardoor de UI bevroren lijkt. proxy_buffering off verstuurt modeloutput naar de browser zodra deze binnenkomt, in plaats van te wachten tot de volledige respons is voltooid. Een nginx reverse proxy-configuratie, regel voor regel legt de rest uit, en kiezen tussen nginx, Caddy en Traefik behandelt hoe u hetzelfde bereikt met automatische certificaten.
Houd poort 3080 gesloten in de firewall, ongeacht welke proxy u kiest, zodat de enige toegangsweg via de geauthenticeerde proxy verloopt. Basisprincipes van ufw firewall behandelt de regels. Basisauthenticatie over TLS is een ondergrens, geen compleet beveiligingsmodel: wie het wachtwoord bezit, heeft toegang tot een shell op uw server. Geef de voorkeur aan de tunnel wanneer dat mogelijk is.
Hoe wijzig ik de poort waarop dsh web luistert?
--port hoort bij de webapplicatie, niet bij de launcher. De CLI-documentatie geeft het voorbeeld direct:
dsh --profile web --port 8080dsh web is een alias van --profile web, dus dsh web --port 8080 is hetzelfde commando. De launcher verwerkt alleen zijn eigen vlaggen en geeft alles wat daarna komt door aan het opgestarte profiel. Launcher-vlaggen staan daarom vooraan, en het eerste token dat de launcher niet herkent, start de argumenten van de applicatie. Plaats --port na het profiel, nooit ervoor.
Lees de URL die het commando afdrukt in plaats van er zomaar vanuit te gaan, omdat die regel het adres rapporteert waaraan de server daadwerkelijk is gebonden. Werk daarna het laatste veld van uw tunnel bij om overeen te komen:
ssh -N -L 3080:127.0.0.1:8080 you@your-vpsVoor een permanente wijziging staat de poort in de profielconfiguratie in plaats van op de commandoregel. De web en headless profielen initialiseren automatisch bij het eerste gebruik vanuit meegeleverde sjablonen, onder ~/.dsh. Om te zien wat er daadwerkelijk van kracht is nadat alle lagen zijn samengevoegd:
dsh --dump-configDe webserver-plugin stelt precies twee sleutels beschikbaar, host en port. Het instellen van port op 0 vraagt het besturingssysteem om een vrije poort, gedocumenteerd als "nul verzoekt om een door het OS toegewezen poort". Dat garandeert dat u nooit een conflict krijgt, en het is ongeschikt voor een tunnel, omdat het nummer bij elke herstart verandert.
Waarom faalt dsh met de melding address already in use?
Omdat een ander proces dat adres en die poort al bezet, weigert de kernel de tweede bind-opdracht. Node rapporteert dit als volgt:
Error: listen EADDRINUSE: address already in use 127.0.0.1:3080Zoek de houder van de poort op voordat u wijzigingen aanbrengt:
sudo ss -ltnp | grep 3080Het veld users:(("node",pid=1042,fd=21)) toont de naam van het proces en het bijbehorende PID. De gebruikelijke oorzaak is een eerdere dsh waarvan u dacht dat deze was gestopt, maar die vaak nog actief is in een losgekoppeld tmux-venster. Stop dat proces met kill 1042, of start de nieuwe instantie op een andere poort. Let op: 127.0.0.1:3080 en 0.0.0.0:3080 conflicteren ook met elkaar, omdat het binden aan alle interfaces automatisch ook de loopback-interface omvat.
Zet de versie vast, aangezien dit een developer preview is
De README is hierover duidelijk: DeepSeek Harness bevindt zich in een developer preview en ondergaat snelle iteraties, waarbij wijzigingen die de compatibiliteit verbreken onvermijdelijk zijn.
npx @deepseek-ai/dsh web verwijst bij elke uitvoering naar de laatst gepubliceerde versie. Een server die u een week niet heeft aangeraakt, kan bij de volgende start een andere CLI laden, inclusief andere flags. Zet de versie vast zodat een herstart geen upgrade is:
npx @deepseek-ai/dsh@0.1.0-rc.7 webSinds augustus 2026 is het gepubliceerde pakket versie 0.1.0-rc.7. Controleer wat een kale npx zou ophalen voordat u dit accepteert:
npm view @deepseek-ai/dsh versionFlags verplaatsen zich tussen de launcher en de webapplicatie in verschillende preview-releases. Als --port niet meer werkt zoals in deze handleiding beschreven, vraag de applicatie dan om de eigen lijst met flags in plaats van te gokken:
dsh --profile web --helpVoor de installatie zelf, de configuratie van de workspace en de model-key, zie DeepSeek Harness installeren op een VPS. Voor een kortere handleiding die alleen de toegangsstap behandelt, bespreekt de dsh Web UI bereiken op een VPS de tunnel zonder de achterliggende logica.
FAQ
Waarom kan ik http://127.0.0.1:3080 niet openen in de browser op mijn laptop?
Omdat 127.0.0.1 verwijst naar de machine waarop u typt. De DeepSeek Harness Web UI is gebonden aan het loopback-adres van de VPS, waardoor alleen processen op de VPS verbinding kunnen maken. Uw laptop heeft een eigen, afzonderlijk loopback-adres en daar luistert niets op poort 3080. Stuur de poort door via SSH met ssh -N -L 3080:127.0.0.1:3080 you@your-vps en laad vervolgens http://127.0.0.1:3080 lokaal. Het middelste veld van het -L-argument wordt aan de serverzijde opgelost, waardoor het naar de harness verwijst.
Is het veilig om de dsh Web UI aan 0.0.0.0 te binden op een publieke VPS?
Nee. De Web UI is het bedieningspaneel voor een agent die shell-commando's uitvoert en bestanden bewerkt als de gebruiker die dsh draait, en de developer preview bevat geen inlogscherm. Binden aan alle interfaces op een publiek IP-adres betekent dat iedereen die poort 3080 bereikt, commando's op uw server kan uitvoeren. Houd de binding op 127.0.0.1, houd 3080 gesloten in de firewall en gebruik een SSH-tunnel, een privaat overlay-netwerk of een reverse proxy die om een wachtwoord vraagt.
Hoe houd ik de dsh Web UI actief nadat ik mijn SSH-sessie heb afgesloten?
Een npx @deepseek-ai/dsh web op de voorgrond is een kindproces van uw inlog-shell en wordt beëindigd wanneer die shell sluit. Start het proces binnen een tmux-sessie en koppel los met Ctrl-b d, of draai het als een systemd user service met lingering ingeschakeld. De tunnel en de harness zijn onafhankelijk: u kunt de SSH-tunnel zo vaak verbreken en opnieuw opbouwen als u wilt zonder de draaiende harness te beïnvloeden, zolang de harness zelf een ouderproces heeft dat langer leeft dan uw inlogsessie.
Waarom bevriest de dsh Web UI halverwege een lange agent-taak achter nginx?
Omdat de standaard proxy_read_timeout van nginx 60 seconden is; de verbinding wordt gesloten als er een minuut lang geen data wordt verstuurd, wat bij een lange agent-stap snel gebeurt. Stel proxy_read_timeout 3600s; in binnen het location-blok. Voeg proxy_buffering off; toe zodat de output naar de browser wordt gestreamd zodra deze beschikbaar is, en geef de headers Upgrade en Connection door met proxy_http_version 1.1; zodat de WebSocket-handshake slaagt. Zonder deze headers laadt de pagina wel, maar ontvangt deze nooit updates.