Jak uruchomić dsh jako usługę systemd na VPS
Skonfiguruj dsh jako usługę systemd, aby zapewnić ciągłe działanie procesu po zamknięciu sesji SSH. Poradnik zawiera instrukcję tworzenia użytkownika, polityki Restart oraz logi.
Uruchamianie dsh w trybie bezgłowym na serwerze VPS, poza terminalem
Uruchomienie dsh w trybie bezgłowym na serwerze VPS wymaga utworzenia pliku jednostki systemd oraz dedykowanego użytkownika, który będzie właścicielem procesu. dsh to narzędzie wiersza poleceń służące do uruchamiania DeepSeek Harness, środowiska uruchomieniowego agentów DeepSeek, opublikowanego na licencji MIT w wersji developer preview w sierpniu 2026 roku. Szybki start zaleca wpisanie npx @deepseek-ai/dsh web, co jest poprawne, jednak proces ten kończy się w momencie zamknięcia sesji SSH (secure shell).
Plik jednostki rozwiązuje cztery problemy jednocześnie. Usługa uruchamia się automatycznie po restarcie systemu. Jej wyjście trafia do dziennika systemowego zamiast przewijać się w terminalu. Proces działa na koncie innym niż root. Ponadto uruchamiana jest konkretna, wybrana wersja oprogramowania, co w tym przypadku ma szczególne znaczenie, gdyż autorzy oprogramowania wyraźnie zaznaczają:
DeepSeek Harness znajduje się obecnie w fazie developer preview i jest intensywnie rozwijany. NALEŻY SPODZIEWAĆ SIĘ ZMIAN NIEKOMPATYBILNYCH WSTECZNIE.
Niniejszy przewodnik zakłada, że dsh działa już poprawnie przy ręcznym uruchomieniu. Jeśli tak nie jest, należy rozpocząć od instalacji DeepSeek Harness na serwerze VPS i powrócić, gdy npx @deepseek-ai/dsh web zacznie poprawnie wyświetlać stronę.
Najpierw Node, ponieważ npm nie wyświetli ostrzeżenia
node -vDomyślny pakiet w Ubuntu 24.04 zawiera Node 18 (wersja 18.19.1 na sierpień 2026), co jest wersją przestarzałą jak na pakiet wydany w tym roku. @deepseek-ai/dsh nie publikuje pola engines, więc npm nie wyświetla ostrzeżenia EBADENGINE, gdy wersja Node jest zbyt stara. Błąd pojawia się dopiero w czasie wykonywania jako błąd składni lub brak wbudowanej funkcji, co jest znacznie trudniejsze do zdiagnozowania. Należy zainstalować aktualne wydanie o długoterminowym wsparciu (LTS) z repozytorium NodeSource:
curl -fsSL https://deb.nodesource.com/setup_22.x -o /tmp/nodesource_setup.sh
less /tmp/nodesource_setup.sh
sudo -E bash /tmp/nodesource_setup.sh
sudo apt install -y nodejs
node -vnode -v powinno teraz wyświetlić wersję v22. Linia less znajduje się tam, ponieważ przesyłanie zdalnego skryptu bezpośrednio do bash uruchamia kod, którego użytkownik nigdy nie przeczytał.
Weryfikacja działania przed utworzeniem jednostki
npx @deepseek-ai/dsh@0.1.0-rc.7 webPozostaw ten proces uruchomiony. Z drugiej sesji SSH wykonaj:
curl -fsS http://127.0.0.1:3080/ -o /dev/null && echo upup oznacza, że profil web nasłuchuje na interfejsie loopback, co jest domyślnym zachowaniem. curl: (7) Failed to connect to 127.0.0.1 port 3080: Connection refused oznacza, że usługa nie działa, a pierwszy terminal wskazuje przyczynę. Zatrzymaj ręczne uruchomienie za pomocą Ctrl+C przed przejściem dalej: jednostka próbująca powiązać port zajęty przez inny proces zakończy się błędem Error: listen EADDRINUSE: address already in use 127.0.0.1:3080.
0.1.0-rc.7 to wersja opublikowana 18 sierpnia 2026. Sprawdź aktualną wersję za pomocą npm view @deepseek-ai/dsh version, a następnie przypnij wybraną wersję do uruchomienia.
Instalacja przypiętej wersji globalnie
npx jest niewłaściwym narzędziem wewnątrz pliku jednostki. Rozwiązuje ono wersję pakietu w momencie uruchomienia procesu, więc restart wykonany za trzy miesiące może zainicjować inną kompilację agenta w fazie podglądu bez żadnej zmiany po stronie użytkownika. Wymaga to również dostępności rejestru npm podczas rozruchu, co sprawia, że działająca maszyna staje się niedziałającą jednostką w dniu, w którym rejestr działa wolno. Należy zainstalować pakiet jednorazowo, w wersji, którą zapisano:
sudo npm install -g @deepseek-ai/dsh@0.1.0-rc.7
command -v dsh
npm ls -g --depth=0 @deepseek-ai/dshcommand -v dsh wyświetla /usr/bin/dsh, gdy npm pochodzi z NodeSource, oraz /usr/local/bin/dsh, gdy pochodzi z pakietów systemowych Ubuntu. W pliku jednostki należy użyć ścieżki, która została faktycznie wyświetlona. npm ls -g drukuje dokładną wersję, co jest informacją niezbędną za sześć tygodni, gdy zachowanie oprogramowania ulegnie zmianie, a użytkownik nie będzie pamiętał, co zostało zainstalowane.
Użytkownik będący właścicielem usługi i niczego więcej
Agent wykonuje polecenia powłoki. Na tym polega jego zadanie. Uruchamianie go jako root sprawia, że każde wywołanie narzędzia staje się wywołaniem z uprawnieniami roota, dlatego należy utworzyć dla niego osobne konto bez powłoki logowania.
sudo useradd --system --create-home --home-dir /var/lib/dsh --shell /usr/sbin/nologin dsh
sudo install -d -o dsh -g dsh -m 750 /var/lib/dsh/harness /var/lib/dsh/workspace
id dsh/var/lib/dsh/harness staje się DSH_HOME, katalogiem, w którym dsh przechowuje profile. Profil to nazwany stos pakietów wtyczek z własną warstwą poprawek na wierzchu, a profile web oraz headless budują się same z dostarczonych szablonów przy pierwszym uruchomieniu. To pierwsze uruchomienie zapisuje pliki i może pobierać pakiety, więc należy wykonać je ręcznie, aby móc monitorować proces.
sudo -u dsh env HOME=/var/lib/dsh DSH_HOME=/var/lib/dsh/harness /usr/bin/dsh --profile webZmienną HOME należy ustawić jawnie, zamiast polegać na tym, jak traktuje ją sudo, ponieważ to, czy sudo nadpisuje HOME dla polecenia bez logowania, zależy od ustawienia set_home w /etc/sudoers. Błędna konfiguracja spowoduje, że przy pierwszym uruchomieniu katalogi pamięci podręcznej zostaną zapisane w Twoim katalogu domowym jako własność dsh, przez co usługa później nie odnajdzie własnego stanu. Proces należy zatrzymać za pomocą Ctrl+C, gdy sprawdzenie curl zwróci up.
Plik jednostki
Wpisz /etc/systemd/system/dsh.service:
[Unit]
Description=DeepSeek Harness (dsh) web profile
Documentation=https://github.com/deepseek-ai/deepseek-harness
After=network-online.target
Wants=network-online.target
StartLimitIntervalSec=300
StartLimitBurst=5
[Service]
Type=exec
User=dsh
Group=dsh
WorkingDirectory=/var/lib/dsh/workspace
Environment=HOME=/var/lib/dsh
Environment=DSH_HOME=/var/lib/dsh/harness
ExecStart=/usr/bin/dsh --profile web
Restart=on-failure
RestartSec=5s
TimeoutStopSec=30s
SyslogIdentifier=dsh
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ProtectHome=true
[Install]
WantedBy=multi-user.targetExecStart= przyjmuje ścieżkę bezwzględną uzyskaną za pomocą command -v dsh. systemd przeszukuje ustaloną listę ścieżek w poszukiwaniu nazwy polecenia, ale lista ta nie jest zmienną PATH powłoki, więc ścieżka bezwzględna eliminuje niepewność.
WorkingDirectory= to miejsce, w którym rozwiązywane są ścieżki względne i w którym rozpoczyna pracę wywołanie narzędzia uruchamiające ls bez argumentów. Należy wskazać katalog roboczy przekazywany agentowi. Jeśli katalog nie istnieje lub użytkownik usługi nie ma do niego dostępu, jednostka kończy działanie błędem status=200/CHDIR jeszcze przed uruchomieniem dsh.
ProtectHome=true ukrywa /home oraz /root przed procesem. Jest to bezpieczne, ponieważ wszystkie zasoby, do których odwołuje się usługa, znajdują się w /var/lib/dsh. Wskazanie katalogu roboczego w ścieżce pod /home spowoduje, że agent zgłosi brak katalogu, co jest mylące, dopóki nie pamięta się o tej linii. ProtectSystem=full ustawia /usr, /boot oraz /etc w tryb tylko do odczytu, ponieważ usługa nie musi w nich nic zapisywać.
Dalsze zaostrzanie restrykcji jest kuszące, ale zazwyczaj błędne. ProtectSystem=strict ustawia cały system plików w tryb tylko do odczytu, poza pseudosystemami plików jądra, więc pierwsze wywołanie narzędzia próbujące zapisać plik kończy się błędem EROFS: read-only file system. Jeśli wymagany jest taki poziom zabezpieczeń, należy dodać ReadWritePaths=/var/lib/dsh w tej samej edycji.
Jaki typ Type= należy tutaj zastosować
Type=exec, ponieważ dsh działa w pierwszym planie i nigdy nie tworzy procesu potomnego (fork). Zaletą tego rozwiązania w porównaniu z wartością domyślną jest otrzymanie rzeczywistego komunikatu o błędzie. Przy Type=simple systemd uznaje start za udany natychmiast po wykonaniu forka, zanim jeszcze sprawdzi, czy plik binarny w ogóle istnieje, więc systemctl start dsh kończy się poprawnie, a błąd pojawia się dopiero w dzienniku. Przy Type=exec systemd czeka na powodzenie execve(), więc literówka w ExecStart= powoduje niepowodzenie polecenia, które właśnie wpisano, co jest od razu widoczne.
Dwie błędne odpowiedzi powodują zawieszenie procesu. Type=forking nakazuje systemd czekać na zakończenie procesu nadrzędnego, a dsh nigdy się nie kończy, więc start blokuje się do momentu upłynięcia TimeoutStartSec (domyślnie 90 sekund), po czym zgłaszany jest błąd Job for dsh.service failed because a timeout was exceeded.. Type=notify czeka na komunikat READY=1 przesyłany przez sd_notify, a proces Node, który nigdy go nie wyśle, zawiesza się w ten sam sposób. Pełne porównanie typów usług systemd omawia pozostałe przypadki, w tym sytuacje, w których warto podjąć wysiłek konfiguracji notify.
Reguły restartu kończące się błędem
Restart=on-failure restartuje usługę w przypadku niezerowego kodu wyjścia lub sygnału krytycznego, natomiast pozostawia jednostkę w spokoju po poprawnym zakończeniu pracy. Jest to zachowanie pożądane w przypadku wersji testowych. Jeśli dsh zakończy pracę z kodem 0, ponieważ odczytał nieprawidłową konfigurację, jednostka zatrzymuje się i pozostaje w tym stanie, a systemctl status dsh wyświetla inactive (dead), gdzie można to zweryfikować. Restart=always zmienia to samo zdarzenie w pętlę restartów, która z dystansu wygląda na poprawnie działającą.
Limit częstotliwości to element, który często jest pomijany. Domyślne ustawienia systemd to pięć uruchomień w ciągu dziesięciu sekund, a przy RestartSec=5s nigdy nie osiągniesz pięciu uruchomień w oknie dziesięciu sekund, więc jednostka, która ulega awarii przy starcie, restartuje się w nieskończoność, a informację o tym posiada jedynie journal. StartLimitIntervalSec=300 wraz z StartLimitBurst=5 oznacza, że pięć awarii w ciągu pięciu minut wystarczy: systemd poddaje się i parkuje jednostkę w stanie failed, logując Start request repeated too quickly.. Po usunięciu przyczyny wyczyść ten stan za pomocą sudo systemctl reset-failed dsh. Oba ustawienia powinny znajdować się w [Unit], a nie w [Service]; w niewłaściwej sekcji systemd ignoruje je bez żadnego komunikatu.
Uruchomienie i weryfikacja
sudo systemctl daemon-reload
sudo systemctl enable --now dsh
systemctl status dshenable --now wykonuje dwa zadania. enable odpowiada za przywrócenie usługi po restarcie systemu, natomiast --now uruchamia ją w bieżącej sesji. Sama komenda systemctl start przestaje działać po ponownym uruchomieniu, a aktualizacje jądra wymuszają restarty.
systemctl status dsh powinno wyświetlić Active: active (running), Main PID oraz linię Memory:. Następnie należy potwierdzić, na jakim porcie usługa nasłuchuje:
sudo ss -lntp | grep 3080Oczekiwany wynik to 127.0.0.1:3080. Jeśli widoczny jest adres 0.0.0.0:3080, oznacza to, że coś zmodyfikowało adres powiązania i agent jest wystawiony na publiczny dostęp w Internecie. Nazwa procesu w tym wyniku to node, a nie dsh, ponieważ plik binarny dsh jest skryptem Node, więc pgrep -x dsh nic nie znajduje. Należy użyć systemctl show -p MainPID dsh.
Następnie należy wykonać jeden restart. Usługa, która nie przetrwała restartu, nie jest jeszcze gotowa do pracy.
sudo rebootNależy połączyć się ponownie i uruchomić systemctl is-active dsh. Wyświetli to active.
Odczytywanie logów za pomocą journalctl
Wszystkie dane zapisywane przez dsh do stdout oraz stderr trafiają do dziennika pod nazwą jednostki.
journalctl -u dsh -f
journalctl -u dsh -n 200 --no-pager
journalctl -u dsh --since "10 min ago" -p err-f śledzi nowe linie, -n wyświetla ostatnie N linii, a -p err filtruje według priorytetu. SyslogIdentifier=dsh w jednostce jest powodem, dla którego te linie są oznaczone jako dsh, a nie node, co ma znaczenie przy pierwszym odczycie danych z dziennika, które nie są przefiltrowane według jednostki.
Sprawdź, czy dziennik przetrwa restarty, zanim będzie to konieczne:
journalctl -u dsh -b -1Jeśli polecenie zwróci Specifying boot ID or boot offset has no effect, no persistent journal was found, dziennik znajduje się w /run i każdy restart powoduje jego usunięcie. Utwórz katalog i zrestartuj demona:
sudo mkdir -p /var/log/journal
sudo systemctl restart systemd-journaldDostęp do interfejsu użytkownika przez tunel SSH zamiast portu publicznego
dsh udostępnia interfejs webowy (UI) na 127.0.0.1:3080 i odmawia pracy w jakiejkolwiek innej lokalizacji. W przypadku żądania --host 0.0.0.0 proces kończy działanie z następującym błędem:
error: --host 0.0.0.0 is intentionally not supported yet for safety: it would expose remote code execution to the network; use 127.0.0.1 insteadNie jest to ograniczenie, które należy obchodzić. Interfejs API aplikacji steruje agentem, a agent wykonuje polecenia powłoki, więc dostępny port oznacza dostęp do powłoki na serwerze VPS dla każdego, kto go odnajdzie. Twórcy wskazują brak wbudowanego uwierzytelniania zdalnego jako powód przypisania nasłuchiwania na stałe do interfejsu loopback. Zamiast tego należy przekierować port z własnej maszyny:
ssh -N -L 3080:127.0.0.1:3080 you@203.0.113.10-L 3080:127.0.0.1:3080 otwiera port 3080 na laptopie i przesyła cały ruch przychodzący na ten port do 127.0.0.1:3080, zgodnie z rozpoznaniem adresu na serwerze VPS. -N oznacza brak wykonywania zdalnego polecenia, dzięki czemu sesja służy wyłącznie do utrzymania tunelu. Pozostaw sesję aktywną i otwórz http://127.0.0.1:3080/ w przeglądarce. W tym miejscu należy wprowadzić klucz API DeepSeek w sekcji Settings, a następnie Models, oraz wybrać katalog obszaru roboczego (workspace). Wskaż jako obszar roboczy /var/lib/dsh/workspace, czyli katalog należący do użytkownika usługi, w przeciwnym razie narzędzia plikowe agenta zakończą działanie błędem EACCES: permission denied.
Jeśli port 3080 jest zajęty na laptopie, ssh wyświetli komunikat:
bind [127.0.0.1]:3080: Address already in use
channel_setup_fwd_listener_tcpip: cannot listen to port: 3080Wybierz inny port lokalny za pomocą ssh -N -L 3081:127.0.0.1:3080 you@203.0.113.10, a następnie przejdź pod adres http://127.0.0.1:3081/. Aby uniknąć wpisywania polecenia za każdym razem, zapisz je w pliku ~/.ssh/config na własnej maszynie:
Host dsh-vps
HostName 203.0.113.10
User you
LocalForward 3080 127.0.0.1:3080Po wykonaniu tej czynności, ssh -N dsh-vps wystarczy do uruchomienia tunelu. Tunel ten stanowi teraz jedyną drogę dostępu do agenta, więc to demon SSH zapewnia jego ochronę: należy stosować wyłącznie klucze, wyłączyć uwierzytelnianie hasłem, a pozostałe zasady zabezpieczania SSH na serwerze VPS mają w tym przypadku jeszcze większe znaczenie.
Klucz nie powinien znajdować się w pliku jednostki (unit file). Wartości Environment= są wyświetlane przez systemctl show dsh -p Environment, co może zrobić każdy użytkownik w systemie. Jeśli zainstalowana wtyczka wymaga klucza w zmiennych środowiskowych, umieść go w pliku /etc/dsh.env z uprawnieniami 600, należącym do użytkownika root, i odwołaj się do niego za pomocą EnvironmentFile=/etc/dsh.env. systemd odczytuje ten plik jako root w momencie uruchamiania procesu, a systemctl show nie wyświetla jego zawartości.
Koszty utrzymania
Inferencja odbywa się w API DeepSeek, a nie na Twoim VPS. Twój serwer pokrywa koszty procesu Node, serwowanego interfejsu użytkownika oraz każdego polecenia, które agent zdecyduje się wykonać. Dwa pierwsze elementy są stałe i niewielkie. Trzeci nie jest ograniczony w tym pliku jednostki.
Określ bazowe zużycie zasobów na własnym serwerze, zamiast polegać na danych innych osób:
systemctl show dsh -p MemoryCurrent
systemd-cgtop -1 --depth 2MemoryCurrent jest podawane w bajtach. Monitoruj ten parametr podczas pracy agenta, a nie w stanie spoczynku.
Wywołania narzędzi są procesami potomnymi usługi, więc trafiają do tej samej grupy kontrolnej i wliczają się do tych samych limitów. Agent wykonujący npm install lub zestaw testów wewnątrz obszaru roboczego może zużyć znacznie więcej pamięci niż sam mechanizm sterujący. Na VPS z 1 GB pamięci RAM w tym miejscu pojawiają się problemy: jądro systemu wybiera proces i kończy go, a journalctl -k | grep -i "out of memory" wyświetla linię Out of memory: Killed process wskazującą wybrany proces. Często nie jest to proces, który spowodował problem.
Rozwiązaniem jest celowe ustawienie limitu. MemoryMax= oraz CPUQuota= w sekcji [Service] ograniczają skutki awarii do samej jednostki, dzięki czemu niekontrolowany proces budowania zostanie przerwany, zamiast doprowadzić do zawieszenia całego serwera. Ograniczanie pamięci i procesora za pomocą systemd omawia wartości liczbowe oraz zachowanie systemu w przypadku przekroczenia limitów. Wykorzystanie dysku również rośnie wraz z historią sesji w DSH_HOME oraz plikami tworzonymi przez agenta w obszarze roboczym, dlatego uwzględnij du -sh /var/lib/dsh w narzędziach, których używasz do monitorowania przestrzeni dyskowej.
Jeśli potrzebujesz interaktywnego agenta, do którego można się podłączać i odłączać, usługa systemd nie jest odpowiednim rozwiązaniem. W takim przypadku lepiej sprawdzi się uruchamianie agenta w trwałej sesji tmux. Uruchamiaj dsh jako usługę tylko wtedy, gdy ma być stale dostępny i osiągalny przez tunel.
Tryby awarii i komunikaty, które zobaczysz
status=203/EXEC. systemd nie mógł uruchomić pliku, a dzienniki wskazują na Failed to locate executable /usr/local/bin/dsh: No such file or directory. Ścieżka w ExecStart= nie zgadza się z tym, co wyświetliło command -v dsh. Jest to błąd, który Type=exec zgłasza w czasie systemctl start, zamiast go ukrywać.
status=217/USER. Konto w User= nie istnieje. Potwierdź to za pomocą id dsh.
status=200/CHDIR. WorkingDirectory= nie istnieje lub użytkownik usługi nie ma do niego dostępu. sudo -u dsh ls /var/lib/dsh/workspace pozwala na bezpośrednią reprodukcję tego problemu.
Error: listen EADDRINUSE: address already in use 127.0.0.1:3080. Port jest już zajęty, zazwyczaj przez proces npx pozostawiony w innym terminalu. sudo ss -lntp | grep 3080 wskazuje nazwę tego procesu.
EACCES: permission denied wraz ze ścieżką. Uprawnienia w /var/lib/dsh są nieprawidłowe, zazwyczaj dlatego, że pierwsze uruchomienie nastąpiło jako root lub z niewłaściwym HOME. sudo chown -R dsh:dsh /var/lib/dsh naprawia ten problem.
Start request repeated too quickly. Jednostka osiągnęła limit częstotliwości uruchamiania i przerwała działanie. Rzeczywisty błąd znajduje się w liniach powyżej. Przed ponowną próbą wykonaj sudo systemctl reset-failed dsh.
Jednostka ma status active (running), ale przeglądarka nic nie wyświetla. Wykonaj sprawdzenie na VPS: jeśli curl -fsS http://127.0.0.1:3080/ -o /dev/null && echo up zwraca tam up, usługa działa poprawnie, a problem leży w przekierowaniu portów.
Celowa aktualizacja
Przypięcie wersji oznacza, że aktualizacja jest czynnością wykonywaną świadomie, a nie zdarzeniem losowym. Należy najpierw przeczytać informacje o wydaniu, ponieważ ostrzeżenia twórców o zmianach naruszających kompatybilność są głównym powodem stosowania przypięć. Należy wykonać kopię zapasową katalogu stanu, a następnie zmienić wersję:
sudo systemctl stop dsh
sudo tar czf /root/dsh-home-$(date +%F).tgz -C /var/lib/dsh harness
sudo npm install -g @deepseek-ai/dsh@0.1.0-rc.7
sudo systemctl start dsh
journalctl -u dsh -n 50 --no-pagerWycofanie zmian polega na wykonaniu tej samej procedury npm install -g ze starą wersją oraz przywróceniu archiwum, co jest możliwe tylko w przypadku jego wcześniejszego utworzenia. Środowisko uruchomieniowe agenta w fazie podglądu to dokładnie ten typ oprogramowania, w którym aktualizacja może w sposób nieprzewidziany nadpisać format konfiguracji.
FAQ
Dlaczego dsh zatrzymuje się po zamknięciu sesji SSH?
Ponieważ npx @deepseek-ai/dsh web jest procesem pierwszoplanowym powiązanym z sesją logowania, więc zostaje zakończony w momencie jej zamknięcia. Jednostka systemd jest zarządzana przez system init, dzięki czemu działa po rozłączeniu i uruchamia się ponownie po restarcie systemu. sudo systemctl enable --now dsh to zestaw kroków zapewniający oba te mechanizmy: enable dla restartu oraz --now dla bieżącego uruchomienia.
Czy dla dsh należy użyć Type=simple czy Type=exec?
Type=exec. dsh działa w pierwszym planie i nie tworzy procesów potomnych (fork), więc obie opcje działają, jednak Type=exec sprawia, że systemd czeka na powodzenie execve() przed uznaniem startu za udany. Błędna ścieżka w ExecStart= spowoduje wtedy niepowodzenie systemctl start z widocznym błędem status=203/EXEC. Przy Type=simple ten sam błąd zostanie uznany za sukces i ukryty w dzienniku. Type=forking oraz Type=notify są w tym przypadku niewłaściwe i obie powodują zawieszenie do czasu wygaśnięcia TimeoutStartSec po 90 sekundach.
Jak otworzyć interfejs webowy dsh z poziomu laptopa?
Przekieruj port przez SSH: ssh -N -L 3080:127.0.0.1:3080 you@your-vps, a następnie otwórz http://127.0.0.1:3080/ w przeglądarce. Nie należy wiązać usługi z publicznym adresem IP. dsh odrzuca --host 0.0.0.0 z błędem error: --host 0.0.0.0 is intentionally not supported yet for safety: it would expose remote code execution to the network; use 127.0.0.1 instead, ponieważ API webowe pozwala agentowi na wykonywanie poleceń powłoki, a przed nim nie ma żadnego mechanizmu zdalnego uwierzytelniania.
Czy można uruchomić dsh jako root, aby uprościć uprawnienia?
Nie. Mechanizm ten służy do wykonywania poleceń i zapisu plików, więc wszelkie uprawnienia usługi stają się uprawnieniami agenta. Należy utworzyć konto systemowe za pomocą useradd --system --shell /usr/sbin/nologin dsh, przypisać mu własność /var/lib/dsh i dodać NoNewPrivileges=true do jednostki. Jeśli po tym wystąpi błąd EACCES: permission denied, najczęstszą przyczyną jest wcześniejsze uruchomienie jako root, co pozostawiło pliki z niewłaściwym właścicielem; sudo chown -R dsh:dsh /var/lib/dsh rozwiązuje ten problem.
Którą wersję dsh należy przypiąć w jednostce?
Tę, którą wskazuje npm view @deepseek-ai/dsh version podczas konfiguracji usługi, zainstalowaną za pomocą npm install -g @deepseek-ai/dsh@<that version> i zapisaną w dostępnym miejscu. Wersja 0.1.0-rc.7 była aktualna 18 sierpnia 2026. Nie chodzi o sam numer, lecz o to, że npx bez określonej wersji pobiera pakiet w momencie startu, co może spowodować, że automatyczny restart niepostrzeżenie przeniesie system na wersję z innym formatem konfiguracji.