SSD Nodes Learn 🎉 VPS от $5.50/мес
Руководства Matt ConnorАвтор: Matt Connor · Обновлено 2026-08-21

Почему DeepSeek Harness выводит http://127.0.0.1:3080

DeepSeek Harness по умолчанию привязывает веб-интерфейс к адресу 127.0.0.1. Это означает, что доступ к панели возможен только через SSH-туннель. Публикация порта 3080 небезопасна.

Что означает dsh web: http://127.0.0.1:3080

Когда вы запускаете веб-профиль DeepSeek Harness на VPS, он выводит две строки и переходит в режим ожидания:

dsh web: http://127.0.0.1:3080
Ready.

127.0.0.1 — это адрес обратной петли (loopback). Этот адрес машина использует для связи с самой собой. Сокет, привязанный к 127.0.0.1, принимает соединения только от процессов на этой же машине и ниоткуда больше. Таким образом, эта строка сообщает вам две вещи одновременно: где прослушивается веб-интерфейс и кому разрешено к нему обращаться. Только той машине, на которой запущен dsh.

Именно поэтому URL не работает, когда вы вставляете его в браузер на своем ноутбуке. 127.0.0.1 вашего ноутбука — это сам ноутбук. Harness прослушивает 127.0.0.1 на VPS, а это другая машина с другим стеком loopback. Ничего не сломано. Вам нужно перенаправить соединение.

В официальном README значение по умолчанию указано прямо: "Команда запускает веб-интерфейс, который по умолчанию доступен по адресу http://127.0.0.1:3080". Адрес привязки берется из плагина веб-сервера @deepseek-ai/dsh-host-webserver, чей ключ host описан как "Хост для прослушивания; поддерживаются два значения: loopback и all-interfaces". Loopback используется по умолчанию, если вы не измените это значение. Если работа с портами для вас в новинку, в статье как работают порты в Linux описана модель «адрес плюс порт», на которой всё это базируется.

Почему веб-интерфейс привязывается только к localhost

dsh — это среда выполнения агента. Вкладка браузера служит панелью управления для процесса, который выполняет shell-команды, читает и записывает файлы в выбранной рабочей директории, а также расходует ваш API-ключ модели. Любой, кто может открыть эту страницу, получает все эти возможности от имени пользователя, под которым запущен dsh.

Таким образом, порт 3080 — это не просто панель мониторинга для чтения. Загрузка этой страницы дает возможность выполнения команд на сервере.

При открытии веб-интерфейса вы сразу попадаете в список сессий. Запроса на вход нет, так как в developer preview не реализованы учетные записи пользователей и удаленная аутентификация. При работе через loopback это безопасно: операционная система выступает в роли контроля доступа, и доступ получают только локальные процессы. Если привязать этот же сервер к 0.0.0.0 на VPS с публичным IP, та же самая страница станет доступна всему интернету без какой-либо защиты. Автоматизированные сканеры постоянно проверяют редкие порты, поэтому считайте, что опубликованный порт 3080 будет обнаружен немедленно.

Не открывайте порт 3080 в вашем брандмауэре и не устанавливайте для веб-сервера host значение 0.0.0.0 на публичном VPS. Такая комбинация передает права на выполнение команд на вашем сервере любому, кто подключится первым.

Те же рассуждения применимы к любой среде выполнения агентов, которую вы размещаете на сервере. Именно поэтому руководство по безопасному запуску агента для программирования на VPS начинается с того же правила: управляющий порт агента должен оставаться приватным, а доступ к нему должен осуществляться через доверенный промежуточный узел.

Как открыть веб-интерфейс dsh с моего ноутбука?

Существует три надежных способа, и каждый из них оставляет harness привязанным к loopback.

  • SSH-туннель. Никакие новые службы не прослушивают публичный интерфейс, а учетные данные у вас уже есть. Это рекомендуемый вариант.
  • Частная оверлейная сеть, благодаря которой интерфейс доступен с ваших устройств и невидим для всех остальных.
  • Reverse proxy, который выполняет TLS (transport layer security) termination и запрашивает пароль перед пересылкой любого запроса.

Разница между ними заключается в способе доставки трафика из вашего браузера на loopback. Ни один из этих методов не требует переноса harness с loopback.

Доступ через SSH-туннель

Выполните эту команду на своем ноутбуке, а не на VPS:

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

Оставьте процесс запущенным, затем откройте http://127.0.0.1:3080 в локальном браузере. Веб-интерфейс загрузится.

Аргумент -L содержит три поля, разделенных двоеточиями. Первое — порт, который будет открыт на вашем ноутбуке. Второе и третье — адрес и порт, на которые перенаправляется каждое соединение. Важная деталь: 127.0.0.1 в среднем поле разрешается SSH-сервером на VPS уже после того, как трафик туда поступил. Это означает loopback-интерфейс VPS, а не вашего компьютера. Именно этот адрес выводит dsh, поэтому туннель работает, а прямое подключение из браузера — нет.

-N указывает SSH не выполнять удаленную команду, поэтому вы получаете только перенаправление портов без интерактивной оболочки. Для фонового туннеля, который сообщает об ошибках, а не молчит:

ssh -N -f -o ExitOnForwardFailure=yes -o ServerAliveInterval=30 -L 3080:127.0.0.1:3080 you@your-vps

-f переводит процесс в фоновый режим после аутентификации. ExitOnForwardFailure=yes важнее, чем кажется: без этого флага SSH успешно установит соединение, даже если перенаправление настроить не удалось. В результате вы получите рабочую сессию и неработающий туннель без каких-либо предупреждений. ServerAliveInterval=30 отправляет keepalive-пакеты каждые 30 секунд, чтобы простаивающий туннель не разрывался из-за таймаутов NAT (network address translation) в сетях кафе или отелей.

Что вы должны увидеть

На VPS проверьте, какой именно адрес прослушивается:

ss -ltnp | grep 3080

Корректный результат указывает на loopback-адрес:

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

Если в столбце локального адреса указано 0.0.0.0:3080, значит, веб-интерфейс доступен на всех интерфейсах, включая публичный. Остановите его и исправьте привязку (bind), прежде чем продолжать. Если ss показывает сокет, но поле users: пустое, запустите команду с sudo, так как в противном случае имя процесса для сокета, принадлежащего другому пользователю, будет скрыто.

Если туннель не запускается

SSH выводит следующее сообщение и завершает работу:

bind [127.0.0.1]:3080: Address already in use
channel_setup_fwd_listener_tcpip: cannot listen to port: 3080

Проблема на стороне вашего ноутбука, а не сервера. Какой-то локальный процесс уже занял порт 3080, часто это забытый ранее запущенный туннель. Выберите другой свободный локальный порт:

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

Изменилось только первое поле, поэтому теперь переходите по адресу http://127.0.0.1:3081, в то время как сервис продолжает слушать порт 3080. Эти два числа не обязаны совпадать.

Если туннель поднялся, но браузер сообщает об отказе в соединении или пустом ответе, значит, трафик дошел до VPS, но на той стороне ничего не обнаружено. Либо процесс dsh завершился, либо он привязался к другому порту. Проверьте это с помощью ss -ltnp | grep 3080 на сервере.

Есть еще один нюанс. Фоновый процесс npx @deepseek-ai/dsh web завершается при закрытии оболочки, поэтому туннель остановится, как только вы выйдете из системы. Запускайте его внутри tmux или как пользовательский systemd-сервис — это та же задача, что описана в поддержании работы агента на VPS. Пока вы занимаетесь настройкой SSH, стоит сначала выполнить укрепление безопасности SSH на VPS, так как туннель делает ваш SSH-логин единственной точкой входа к агенту.

Доступ через частную оверлейную сеть

Оверлейная сеть предоставляет вашему VPS и ноутбуку адреса в частной сети, к которой подключаются только ваши устройства. Tailscale является популярным выбором, и его команда serve идеально подходит для этого случая: tailscaled запускается на VPS и подключается к localhost:3080, поэтому обвязка остается на loopback, и вам не нужно менять настройки dsh.

tailscale serve --bg localhost:3080
tailscale serve status

Интерфейс становится доступен по имени вашей машины внутри tailnet по протоколу HTTPS, при этом порты на публичном интерфейсе остаются закрытыми. Для этого в вашем tailnet должны быть включены HTTPS-сертификаты, иначе serve не сможет предоставить сертификат. Чтобы отключить доступ, повторите команду с off:

tailscale serve --https=443 off

Используйте serve, никогда не используйте funnel. Funnel публикует ту же цель в публичный интернет, что возвращает вас к неаутентифицированной среде выполнения агента на открытом порту. Эти две команды выглядят почти одинаково, но выполняют противоположные действия, поэтому ознакомьтесь с разницей между Tailscale Serve и Funnel перед вводом любой из них. В Tailscale как частная сеть описана настройка самой сети.

Доступ через обратный прокси с проверкой пароля

Это вариант, который действительно открывает порт в интернет, поэтому аутентификация — единственное препятствие между посторонним лицом и выполнением команд на вашем сервере. Выбирайте его, когда доступ к интерфейсу нужен нескольким пользователям, а создание отдельного туннеля для каждого нецелесообразно.

Harness остается на 127.0.0.1:3080. nginx работает на том же узле, поэтому он может обращаться к loopback и слушает порт 443 с использованием сертификата и файла паролей.

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;
    }
}

Создайте файл паролей и перезагрузите конфигурацию:

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

nginx -t должен вывести syntax is ok, а затем test is successful. Перезагрузка с поврежденным файлом завершится ошибкой и сохранит текущую конфигурацию, поэтому читайте текст ошибки, а не перезапускайте сервис вслепую.

Три из этих строк прокси-сервера не являются декоративными. Заголовки Upgrade и Connection пропускают рукопожатие WebSocket, без них страница загружается, но не обновляется. proxy_read_timeout 3600s заменяет стандартное значение в 60 секунд, которое иначе прервет выполнение долгого агента в середине ответа и оставит интерфейс в «зависшем» состоянии. proxy_buffering off отправляет вывод модели в браузер по мере поступления, вместо того чтобы удерживать его до завершения ответа. Построчный разбор конфигурации обратного прокси nginx объясняет остальное, а выбор между nginx, Caddy и Traefik описывает реализацию того же решения с автоматическими сертификатами.

Держите порт 3080 закрытым в брандмауэре независимо от того, какой прокси вы выберете, чтобы единственный путь внутрь проходил через аутентифицированный прокси. Основы работы с брандмауэром ufw описывает правила настройки. Базовая аутентификация поверх TLS — это минимальный уровень, а не законченная модель безопасности: тот, кто владеет этим паролем, владеет оболочкой (shell) на вашем сервере. По возможности отдавайте предпочтение туннелям.

Как изменить порт, на котором прослушивает запросы dsh web?

--port относится к веб-приложению, а не к лаунчеру. В документации CLI приведен прямой пример:

dsh --profile web --port 8080

dsh web является псевдонимом --profile web, поэтому dsh web --port 8080 — это та же самая команда. Лаунчер анализирует только свои собственные флаги, а всё, что идет после них, передает загружаемому профилю. Поэтому флаги лаунчера должны стоять первыми, а первый токен, который лаунчер не распознает, начинает аргументы приложения. Размещайте --port после профиля, но никогда не перед ним.

Считывайте URL, который выводит команда, вместо того чтобы предполагать его, так как эта строка сообщает адрес, к которому сервер фактически привязался. Затем обновите последнее поле вашего туннеля, чтобы оно соответствовало:

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

Для постоянного изменения порт указывается в конфигурации профиля, а не в командной строке. Профили web и headless автоматически инициализируются при первом использовании из поставляемых шаблонов, расположенных в ~/.dsh. Чтобы увидеть, что именно действует после объединения всех уровней конфигурации:

dsh --dump-config

Плагин веб-сервера предоставляет ровно два ключа: host и port. Установка port в значение 0 запрашивает у операционной системы свободный порт; это задокументировано как «ноль запрашивает порт, назначенный ОС». Это гарантирует отсутствие конфликтов, но плохо подходит для туннеля, так как номер порта меняется при каждом перезапуске.

Почему dsh завершается с ошибкой address already in use?

Это происходит потому, что другой процесс уже занял этот адрес и порт, поэтому ядро отклоняет повторный вызов bind. Node сообщает об этом следующим образом:

Error: listen EADDRINUSE: address already in use 127.0.0.1:3080

Прежде чем вносить изменения, найдите процесс, удерживающий порт:

sudo ss -ltnp | grep 3080

Поле users:(("node",pid=1042,fd=21)) указывает имя процесса и его PID. Чаще всего причиной является предыдущий экземпляр dsh, который, как вы полагали, был остановлен, но всё ещё работает в отсоединённом окне tmux. Остановите этот процесс с помощью kill 1042 или запустите новый экземпляр на другом порту. Учтите, что 127.0.0.1:3080 и 0.0.0.0:3080 также конфликтуют друг с другом, так как привязка ко всем интерфейсам уже включает в себя loopback.

Закрепите версию, так как это предварительная версия для разработчиков

В README прямо сказано: DeepSeek Harness находится на стадии предварительной версии для разработчиков и быстро развивается, поэтому возможны изменения, нарушающие обратную совместимость.

npx @deepseek-ai/dsh web при каждом запуске обращается к самой новой опубликованной версии. Сервер, к которому вы не обращались неделю, при следующем запуске может запустить другой CLI с другими флагами. Закрепите версию, чтобы перезапуск не приводил к обновлению:

npx @deepseek-ai/dsh@0.1.0-rc.7 web

По состоянию на август 2026 года опубликованный пакет имеет версию 0.1.0-rc.7. Проверьте, что именно загрузит обычный npx, прежде чем подтверждать действие:

npm view @deepseek-ai/dsh version

В предварительных выпусках флаги перемещаются между загрузчиком и веб-приложением. Если --port перестает вести себя так, как описано в этом руководстве, запросите у самого приложения список его флагов, вместо того чтобы угадывать:

dsh --profile web --help

Информацию об установке, настройке рабочей области и ключе модели см. в разделе установка DeepSeek Harness на VPS. Более краткое руководство, посвященное только этапу доступа, подключение к веб-интерфейсу dsh на VPS, описывает создание туннеля без пояснений логики работы.

FAQ

Почему я не могу открыть http://127.0.0.1:3080 в браузере на своем ноутбуке?

Потому что 127.0.0.1 означает машину, за которой вы работаете. Веб-интерфейс DeepSeek Harness привязан к loopback-адресу VPS, поэтому к нему могут подключаться только процессы внутри самого VPS. У вашего ноутбука собственный loopback, и на нем никто не слушает порт 3080. Перенаправьте порт через SSH с помощью ssh -N -L 3080:127.0.0.1:3080 you@your-vps, а затем откройте http://127.0.0.1:3080 локально. Среднее поле аргумента -L разрешается на стороне сервера, именно поэтому оно указывает на harness.

Безопасно ли привязывать веб-интерфейс dsh к 0.0.0.0 на публичном VPS?

Нет. Веб-интерфейс — это панель управления агентом, который выполняет shell-команды и редактирует файлы от имени пользователя, запустившего dsh, а предварительная версия для разработчиков не имеет экрана авторизации. Привязка ко всем интерфейсам на публичном IP означает, что любой, кто обратится к порту 3080, получит возможность выполнять команды на вашем сервере. Оставьте привязку на 127.0.0.1, держите порт 3080 закрытым в файрволе и используйте SSH-туннель, частную оверлейную сеть или reverse proxy с обязательной аутентификацией.

Как оставить веб-интерфейс dsh запущенным после закрытия SSH-сессии?

Процесс npx @deepseek-ai/dsh web, запущенный в foreground, является дочерним для вашей оболочки входа, поэтому он завершается при выходе из нее. Запустите его внутри сессии tmux и отсоединитесь с помощью Ctrl-b d, либо запустите его как systemd user service с включенным lingering. Туннель и harness независимы: вы можете разрывать и восстанавливать SSH-туннель сколько угодно раз, не затрагивая работающий harness, если у последнего есть родительский процесс, который продолжает работать после завершения вашей сессии.

Почему веб-интерфейс dsh зависает во время долгого выполнения агента при работе через nginx?

Потому что значение proxy_read_timeout по умолчанию в nginx составляет 60 секунд, поэтому он закрывает соединение, если в течение минуты не передаются данные, что часто случается при длительных шагах агента. Установите proxy_read_timeout 3600s; в блоке location. Добавьте proxy_buffering off;, чтобы вывод передавался в браузер по мере поступления, и передайте заголовки Upgrade и Connection с помощью proxy_http_version 1.1;, чтобы рукопожатие WebSocket завершилось успешно. Без этих заголовков страница загружается, но обновления не приходят.