SSD Nodes Learn 🎉 VPS dès $5.50/mois
Guides Matt ConnorPar Matt Connor

DeepSeek Harness sur VPS : installation privée

Installez DeepSeek Harness sur un VPS Linux, bloquez la version npm, comprenez les plugins et ouvrez l’UI du port 3080 via un tunnel SSH sécurisé.

Présentation de DeepSeek Harness

DeepSeek Harness (dsh) est un runtime d’agent Node.js que vous pouvez exécuter sur un VPS (serveur privé virtuel). Pour l’exécuter de manière sûre, liez-le à 127.0.0.1 et accédez-y depuis votre navigateur via un tunnel SSH (secure shell). Il fournit une interface web (UI, user interface) sur le port 3080 au lieu de fonctionner dans un terminal. Ce serveur web ne demande aucun mot de passe. Un port 3080 exposé publiquement donne donc à toute personne qui le découvre accès à un agent capable de lire vos fichiers et d’exécuter des commandes avec les privilèges de votre utilisateur Linux.

DeepSeek l’a publié le 13 August 2026 sous licence MIT, sous la forme du package npm @deepseek-ai/dsh. Le projet se présente comme une version de prévisualisation destinée aux développeurs et précise que des changements incompatibles sont attendus. Tous les numéros de version ci-dessous correspondent à un instantané d’August 2026. Consultez donc le dépôt avant de copier ces éléments sur un serveur important.

Une idée guide toute la conception : tout est un plugin. L’adaptateur du modèle, le registre des outils, le journal de session, le sandbox, le scheduler et la boucle de l’agent elle-même sont des plugins chargés dans un contexte partagé unique. Chacun peut être remplacé. Il n’existe pas de core privilégié que les plugins se contenteraient d’enrichir. C’est ce qui rend le harness intéressant à tester, mais c’est aussi là que se trouve le seul risque réel.

Un harness n’est pas un modèle

Le harness exécute la boucle de l’agent. Le raisonnement a lieu dans un modèle distinct. Rien ne fonctionne donc tant que vous ne lui avez pas fourni une clé d’API (application programming interface) ou l’adresse d’un endpoint de modèle que vous hébergez vous-même.

Vous configurez cela dans l’interface, sous Settings, puis Models. Le catalogue propose des fiches prêtes à l’emploi pour les grands fournisseurs d’API (DeepSeek, OpenAI, Anthropic), dans lesquelles vous collez une clé. L’option « Add a custom provider » est la plus intéressante : elle demande un identifiant de fournisseur, un nom d’affichage, une URL de base, un protocole d’API et un identifiant d’accès. Elle utilise le protocole compatible avec OpenAI. Tout gateway ou serveur local qui implémente ce protocole fonctionne donc. Les fournisseurs personnalisés peuvent également interroger l’endpoint compatible avec OpenAI GET /models pour remplir automatiquement la liste des modèles.

C’est ainsi que vous pointez le harness vers un modèle exécuté sur le même VPS. Ollama expose une API compatible avec OpenAI à l’adresse http://127.0.0.1:11434/v1/. Le champ de clé d’API doit contenir n’importe quelle chaîne, par convention ollama, car ce champ est obligatoire mais sa valeur est ensuite ignorée. La question la plus difficile est de savoir si un modèle suffisamment petit pour tenir sur votre VPS est assez performant pour piloter un agent. La différence entre Ollama et vLLM en tant que serveur de modèle local détermine la quantité de RAM nécessaire.

Les clés saisies dans l’interface sont accessibles en écriture uniquement. Le harness les stocke dans $DSH_HOME/.credentials.yaml et conserve uniquement une référence d’identifiant d’accès dans settings.yaml. $DSH_HOME utilise ~/.dsh par défaut. Traitez ce fichier comme un fichier de mots de passe, car c’en est un : toute personne qui peut le lire peut dépenser votre budget d’API.

Prérequis

  • un VPS sous Ubuntu 24.04 ou une autre distribution Linux récente, avec un accès SSH
  • Node.js 22.19 ou une version ultérieure de la branche 22.x, ou Node.js 24 ou une version ultérieure, car c’est avec ces versions que le projet est compilé et testé
  • un compte utilisateur standard, et non root, car l’agent exécute les commandes shell avec les privilèges de l’utilisateur qui a démarré le processus
  • pnpm dans le PATH si vous prévoyez d’installer des plugins, car la commande du plugin l’exécute via un shell
  • le port 3080 fermé dans votre pare-feu et dans le pare-feu réseau distinct de votre fournisseur

Le paquet nodejs fourni par Ubuntu est plus ancien que la version requise par le harness. Installez donc Node avec NodeSource ou nvm, plutôt qu’avec apt install nodejs. Si le VPS est neuf, renforcer SSH avant toute autre opération prend dix minutes et vaut la peine, car le tunnel dont vous allez dépendre est limité par la sécurité du serveur SSH qui se trouve derrière.

Installer DeepSeek Harness sur un VPS en épinglant une version

node --version
npx @deepseek-ai/dsh@0.1.0-rc.6 web

npx télécharge le package et exécute son binaire dsh. web est un alias de --profile web, qui démarre l’application web, puis le processus affiche l’adresse sur laquelle il est en écoute. La valeur par défaut est http://127.0.0.1:3080.

Épinglez la version. npx @deepseek-ai/dsh web résout la cible du tag latest au moment de son exécution, et le projet a déjà publié plusieurs release candidates tout en annonçant des changements incompatibles à venir. 0.1.0-rc.6 correspond à la cible de latest le 13 août 2026. Une version épinglée garantit que le serveur configuré aujourd’hui se comportera de la même manière le mois prochain. Une mise à niveau devient ainsi une décision que vous prenez, et non une modification découverte par accident.

Pour l’utilisation quotidienne, installez-le une seule fois au lieu de refaire la résolution à chaque démarrage.

npm install -g @deepseek-ai/dsh@0.1.0-rc.6
dsh --profile web --help

La deuxième ligne mérite d’être exécutée, car le launcher et l’application web utilisent des ensembles de flags distincts. dsh --help affiche les options propres au launcher. dsh --profile web --help affiche les flags acceptés par l’application web. C’est là que se trouvent --port, --host et --trusted-host, qui peut être répété.

Vérifiez maintenant sur quelle adresse le processus est en écoute.

ss -tlnp | grep 3080

La colonne de l’adresse locale doit afficher 127.0.0.1:3080. Si elle affiche 0.0.0.0:3080, l’interface est accessible depuis Internet. Arrêtez le processus avant toute autre opération.

Pourquoi vous ne devez jamais publier le port 3080

Le serveur web ne possède aucune couche d’authentification. Sa configuration expose une adresse d’écoute et un port d’écoute. C’est toute sa surface d’exposition. Le contrôle d’accès pour les déploiements hors boucle locale repose sur un paramètre distinct de trusted host. Il ne s’agit pas d’un écran de connexion.

Examinez maintenant ce qui se trouve derrière ce port. L’agent modifie des fichiers dans l’espace de travail et exécute des commandes shell. Vos identifiants de fournisseur sont stockés sur le disque, à côté de lui. Un port 3080 ouvert équivaut donc à un shell distant avec une interface de chat, exécuté sous l’utilisateur qui l’a lancé, avec votre clé d’API associée. Un exploit n’est pas nécessaire. Il suffit de connaître le numéro du port. Les scanners trouvent les ports ouverts dans les heures qui suivent la mise en ligne d’un hôte.

La CLI (interface de ligne de commande) confirme ce comportement. Depuis 0.1.0-rc.6, elle ne prend volontairement pas en charge --host 0.0.0.0 et quitte avec une erreur d’utilisation au lieu de démarrer. Ce refus est une fonctionnalité. Ne cherchez donc pas de patch pour le supprimer.

Deux autres modes de déploiement sont raisonnables lorsqu’un tunnel ne vous convient pas. Placez le serveur sur un réseau overlay privé afin qu’il possède uniquement une adresse vers laquelle vos propres appareils peuvent router le trafic. C’est ce que permet un serveur de contrôle Headscale auto-hébergé. Vous pouvez aussi le placer derrière un reverse proxy qui authentifie la requête avant qu’elle n’atteigne le port 3080, par exemple un serveur d’authentification unique Authentik utilisant forward auth. Un reverse proxy sans authentification devant ce service n’est pas un contrôle de sécurité. C’est une URL plus longue.

Accéder à l’interface web via un tunnel SSH

Exécutez cette commande sur votre ordinateur portable, pas sur le serveur.

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

-L ouvre le port 3080 sur votre ordinateur portable et transmet toute connexion qui y arrive via la session SSH chiffrée. La partie 127.0.0.1:3080 est résolue sur le serveur. La connexion arrive donc au harness depuis loopback, exactement comme si vous étiez devant la machine. -N indique de ne pas démarrer de shell distant, car vous voulez uniquement le forwarding.

Ouvrez ensuite http://127.0.0.1:3080 dans le navigateur local. Si le port 3080 est déjà utilisé sur votre ordinateur portable, modifiez le nombre de gauche : ssh -N -L 3180:127.0.0.1:3080 you@your-server, puis accédez à http://127.0.0.1:3180. Le nombre de gauche correspond au port local et celui de droite au port du serveur. Seul le nombre de gauche doit donc changer.

Enregistrez-le dans ~/.ssh/config et ne le saisissez plus manuellement.

Host dsh
  HostName 203.0.113.10
  User deploy
  IdentityFile ~/.ssh/id_ed25519
  LocalForward 3080 127.0.0.1:3080

Ensuite, ssh -N dsh démarre le tunnel. Si le navigateur indique que la connexion a été refusée, cela signifie généralement que le tunnel est actif, mais que rien n’écoute à l’autre extrémité. SSH transfère le port, que le harness soit démarré ou non. Vérifiez le serveur avec la commande ss ci-dessus.

Garder le harness actif après la déconnexion

Une commande npx s’arrête avec votre shell. Un service utilisateur systemd continue de fonctionner et relance le harness après un crash ou un redémarrage.

loginctl enable-linger $USER
mkdir -p ~/.config/systemd/user
command -v dsh

enable-linger est nécessaire, car les services utilisateur s’arrêtent normalement à la fin de votre dernière session. Sans cette option, le harness s’arrête dès que vous fermez le tunnel. Prenez le chemin absolu affiché par command -v dsh et indiquez-le dans l’unité, car systemd ne recherche pas les exécutables dans le PATH construit par votre shell de connexion.

[Unit]
Description=DeepSeek Harness web UI
After=network-online.target

[Service]
Type=simple
WorkingDirectory=%h/projects/site
ExecStart=/usr/local/bin/dsh web
Restart=on-failure
RestartSec=5

[Install]
WantedBy=default.target

WorkingDirectory n’est pas un détail esthétique. Le processus dsh utilise son répertoire de lancement comme emplacement par défaut dans le système de fichiers. Un service lancé au mauvais endroit donne donc à l’agent un workspace par défaut incorrect. Vous pouvez toujours sélectionner le workspace dans l’interface utilisateur.

systemctl --user daemon-reload
systemctl --user enable --now dsh
systemctl --user status dsh

Une unité qui refuse de démarrer utilise presque toujours un chemin ExecStart incorrect ou une version de Node que le binaire refuse ; journalctl --user -u dsh -n 50 indique laquelle. La même méthode permet de garder un agent de codage actif sur un VPS, avec des modes de défaillance identiques.

Ce qu’un plugin est autorisé à faire

Un plugin est un module qui ajoute des services, des événements typés et des effets réversibles à un contexte partagé. Les points d’extension méritent une lecture attentive :

  • enregistrer un fournisseur de modèles sur ctx.llm
  • ajouter des outils accessibles au modèle sur ctx.tools
  • fournir le backend shell derrière ctx.shell
  • fournir l’accès au système de fichiers ou la policy derrière ctx.fs
  • enregistrer des commandes utilisateur sur ctx.commands
  • exécuter des tâches en arrière-plan via ctx.jobs
  • envelopper les processus lancés avec un backend ctx.sandbox
  • intercepter les requêtes et les appels d’outils via les événements agent/* et tools/*
  • étendre l’état durable de la session
  • piloter l’interface utilisateur via ctx.agents

Lisez cette liste comme le ferait un attaquant. Un plugin peut fournir la couche système de fichiers et la couche shell. Il peut aussi s’intercaler dans chaque appel d’outil effectué par le modèle. Aucun dialogue d’autorisation ne s’interpose entre un plugin et ces points d’extension, car un plugin est du code Node ordinaire chargé dans le même processus que tout le reste. Installer un plugin revient à exécuter le code d’un tiers avec les permissions de votre agent, qui sont celles de votre utilisateur Unix.

Il s’agit de la même décision de confiance que lorsque vous attachez un serveur MCP à un agent sur un VPS, MCP désignant le protocole de contexte du modèle. C’est aussi pourquoi exécuter un agent de programmation en toute sécurité sur un VPS commence par le compte sous lequel il s’exécute, et non par le modèle, et pourquoi les attaques de la supply chain npm sont si graves sur les serveurs : l’étape d’installation constitue la compromission, et aucun avertissement ne s’affiche.

D’où viennent les plugins

Les plugins résident dans des profils. Un profil est une composition nommée stockée sous $DSH_HOME, qui pointe par défaut vers ~/.dsh. Chaque répertoire de profil contient les plugins externes qu’il installe. La CLI les gère en transmettant directement vos arguments à pnpm, avec le répertoire du profil comme répertoire de travail.

dsh plugin --profile web add github:deepseek-harness/turtle-ui
dsh plugin --profile web remove turtle-ui

Comme les arguments parviennent à pnpm sans modification, add, remove, update et why se comportent comme dans n’importe quel projet pnpm. Un plugin peut être un package npm ou une référence GitHub. pnpm doit d’abord être disponible dans le PATH. Avec Node 22 et les versions ultérieures, corepack enable pnpm l’y ajoute.

La découverte passe par un topic GitHub. Les auteurs de plugins ajoutent le topic dsh-plugin à leur dépôt. Vous pouvez ensuite parcourir ce topic pour voir les plugins disponibles. Un topic est une étiquette qu’un auteur applique à son propre dépôt. Personne ne le vérifie ni ne le signe. La page du topic classe les dépôts selon leur nombre d’étoiles, ce qui mesure la popularité, pas la sécurité.

Quatre habitudes permettent de garder la situation sous contrôle. Lisez le code source avant l’installation, car la plupart des plugins sont assez petits pour être examinés en dix minutes. Épinglez la version exacte ou le commit exact au lieu de suivre une branche. Exécutez le harness avec un utilisateur qui ne possède rien d’autre, sur un VPS que vous accepteriez de réinstaller. Donnez à l’agent sa propre clé API et sa propre limite de dépenses, distinctes de la clé utilisée par vos services de production.

Si vous préférez comparer les architectures avant de choisir, le harness multi-agent Omnigent répond au même problème avec une structure différente. Les compromis deviennent évidents dès que les plugins entrent en jeu.

Ce qui tombe en panne en premier

Node est trop ancien. Le projet cible Node 22.19 et les versions ultérieures de la branche 22.x, ainsi que Node 24 et les versions suivantes. La CI les teste. Un runtime plus ancien échoue au démarrage, car le code utilise une syntaxe et des API qu’il ne prend pas en charge. Exécutez node --version avant toute autre commande.

Le port 3080 est déjà utilisé. Il peut être occupé par un deuxième harness, un processus obsolète ou une autre application qui utilise également 3080. Identifiez le processus avec ss -tlnp | grep 3080, puis arrêtez-le ou démarrez le harness ailleurs avec dsh web --port 3180. --port appartient à l’application web et doit donc être exécuté après web.

Le navigateur ne peut pas se connecter via le tunnel. Vérifiez que vous avez ouvert 127.0.0.1, et non l’adresse publique du serveur, car le port redirigé n’existe que sur votre ordinateur portable. Vérifiez ensuite que le harness est en écoute sur le serveur, car SSH configure la redirection même si aucun service ne répond à l’autre extrémité.

dsh plugin échoue immédiatement. Cette commande encapsule pnpm. L’absence du binaire pnpm l’arrête donc avant le début du traitement des plugins.

L’agent ne voit pas votre projet. Par défaut, l’espace de travail correspond au répertoire depuis lequel le processus a été démarré. Ainsi, si le WorkingDirectory d’une unité correspond à votre répertoire personnel, l’agent reçoit accès à ce répertoire. Sélectionnez l’espace de travail dans l’interface ou corrigez l’unité, puis rechargez-la.

FAQ

Est-il sûr d’exposer l’interface web de DeepSeek Harness sur le port 3080 ?

Non. Le serveur web n’a pas de mécanisme de connexion propre, et l’agent qui s’exécute derrière modifie des fichiers et lance des commandes shell avec les privilèges de l’utilisateur qui a démarré le processus. Votre clé API de fournisseur est également stockée sur le même disque. Laissez le listener sur 127.0.0.1 et utilisez-le via un tunnel SSH. Un réseau overlay privé ou un reverse proxy qui authentifie chaque requête avant de la transmettre au port convient également. Depuis la version 0.1.0-rc.6, la CLI refuse --host 0.0.0.0 et se termine avec une erreur d’utilisation. Cela indique clairement ce que les auteurs pensent de cette configuration.

Ai-je besoin d’une clé API DeepSeek, ou puis-je utiliser un modèle local ?

Les deux sont possibles, car le harness est un runtime, pas un modèle. Dans Settings, puis Models, vous pouvez coller une clé dans la fiche d’un fournisseur du catalogue. Vous pouvez aussi sélectionner « Add a custom provider » et lui fournir une URL de base qui parle le protocole compatible avec OpenAI. Un serveur Ollama local répond sur http://127.0.0.1:11434/v1/ et accepte n’importe quelle chaîne dans le champ de clé API. Les clés sont enregistrées dans $DSH_HOME/.credentials.yaml, dont la valeur par défaut est ~/.dsh/.credentials.yaml.

Que donne réellement l’installation d’un plugin DeepSeek Harness au plugin ?

Les permissions du compte qui exécute le harness. Un plugin est du code Node chargé dans le même processus. Les points d’extension comprennent le backend shell, la couche filesystem, le registre des outils et les événements qui entourent chaque appel d’outil. Rien n’isole un plugin de ces interfaces, sauf si le plugin fournit lui-même sa sandbox. Lisez le code source avant l’installation. Exécutez aussi le harness avec un utilisateur qui ne possède aucune donnée importante pour vous.

Quelle version dois-je installer et continuera-t-elle de fonctionner ?

Installez une version exacte, par exemple npx @deepseek-ai/dsh@0.1.0-rc.6 web. C’est la version vers laquelle pointait le tag latest le 13 août 2026. Le projet se présente comme une developer preview et indique que des changements incompatibles sont prévus. Une commande sans version figée peut donc se comporter différemment d’un jour à l’autre. Consultez le repository avant toute mise à niveau. Attendez-vous à ce que les clés de configuration et les interfaces des plugins évoluent tant que la version commence par 0.

#deepseek#agent-harness#auto-hébergement#nodejs#plugins