Huit minutes pour perdre un serveur
J'ai installé Dokploy sur un VPS tout neuf, et un robot a créé le compte admin avant moi, huit minutes après la fin de l'installation. Ce qu'il a fait du serveur, pourquoi le pare-feu n'a rien vu, ce qu'un attaquant plus soigneux aurait effacé, et l'ordre dans lequel j'ai tout réinstallé.
12 octobre 2026 · 7 min de lecture · Julien Lampin
Un dimanche soir, je monte un VPS pour un projet perso : un petit jeu web publié chaque soir, sa plateforme, sa base. Rien de critique. J'installe Dokploy, une sorte de Heroku qu'on héberge soi-même, par-dessus Docker. Son interface web attend un premier compte, et le premier qui le crée devient administrateur.
Je fais tout ça avec Claude Code, qui a la main sur le serveur en SSH. Il met le système à jour, active le pare-feu, installe Dokploy. Trois quarts d'heure plus tard, quand j'ouvre la page pour créer mon compte, elle ne me propose pas de créer un compte. Elle me demande de me connecter.
Quelqu'un était passé avant moi.
Huit minutes
Claude Code a reconstitué la soirée à partir de ce qui restait sur le serveur : l'heure de fin de l'installation, la date de création du compte dans la base de Dokploy, les conteneurs arrêtés.
Un soir, heure de Paris
8 min
entre la fin de l'installation et le compte admin du robot
18 h 34
VPS à jour, pare-feu actif, redémarrage.
18 h 38
Dokploy est installé. Son interface attend un premier compte sur le port 3000.
18 h 46
Un compte admin est créé : lab-orch@localhost.local.
18 h 46
orch-key-inject : un conteneur monte le disque du serveur et écrit une clé SSH chez root.
18 h 47
orch-prep : un petit serveur d'upload est déposé dans /tmp, pour recevoir un binaire.
18 h 48
orch-unit-install échoue.
18 h 54
Deuxième passage : la clé est réécrite, l'installation échoue encore.
19 h 25
J'ouvre la page pour créer mon compte. On me demande de me connecter.
Huit minutes entre la fin de l'installation et le compte admin de l'autre. Ce n'est pas quelqu'un qui me visait. C'est un robot qui balaie Internet en continu, à la recherche d'interfaces Dokploy qui n'ont pas encore d'administrateur. Une adresse IP de VPS neuve a déjà servi à d'autres, et les scanners la connaissent avant vous.
Claude Code, ce soir-là


Ce que le robot a fait
Le compte s'appelait lab-orch@localhost.local. Depuis ce compte, il a utilisé ce que Dokploy sait faire de mieux : lancer des conteneurs Docker. Un conteneur qui monte le disque du serveur peut écrire n'importe où, et ses fichiers appartiennent à root. Administrateur de Dokploy, c'est administrateur de la machine.
Les conteneurs portaient tous un nom en orch- :
orch-key-injecta ajouté une clé SSH, nommée « dokploy », dans les clés autorisées de root et de l'utilisateur ubuntu ;orch-prepa déposé un petit serveur d'upload en Python dans/tmp, fait pour recevoir un binaire « orchestrator » et le ranger dans un dossier caché de root ;orch-unit-installdevait installer ce binaire comme service. Il a échoué, deux fois.
Pourquoi il a échoué, je n'en suis pas sûr. Mon hypothèse : le serveur d'upload écoutait sur un port que Docker ne publiait pas, et que le pare-feu, lui, bloquait bien. Le binaire n'est jamais arrivé. Le robot n'a pas non plus utilisé sa clé : toutes les connexions SSH acceptées venaient de la mienne.
Ça ne change rien à la conclusion. Il a eu un accès root, même quelques minutes, et on ne peut pas prouver qu'un système est propre après ça. On peut seulement prouver qu'on n'a rien trouvé.
Le pare-feu n'a rien vu
Le serveur avait un pare-feu, ufw, réglé pour n'ouvrir que SSH et le web. C'est vrai qu'on avait aussi ouvert le port 3000 de Dokploy, pour que je puisse créer mon compte. Mais même sans cette règle, la page aurait été visible.
Docker contourne ufw. Quand un conteneur publie un port, Docker écrit ses propres règles iptables, qui redirigent le paquet vers le conteneur avant qu'ufw ne le voie.
Deux paquets, deux chemins
Un paquet pour SSH (port 22)
ufw décide : c'est la porte qu'il garde.
Un paquet pour Dokploy (port 3000)
Le paquet ne passe jamais par INPUT : ufw n'est pas consulté.
Parade
DOCKER-USER est la seule chaîne que Docker laisse à l'administrateur. Une règle qui y jette le port 3000 tient même quand Docker réécrit les siennes.
C'est documenté, et ça surprend presque tout le monde. Sur un serveur Docker, ufw status peut afficher une liste parfaitement fermée pendant qu'un conteneur répond au monde entier.
La parade tient en quelques lignes, à la fin de /etc/ufw/after.rules (et de after6.rules pour l'IPv6) :
*filter
:DOCKER-USER - [0:0]
-A DOCKER-USER -i ens3 -p tcp -m conntrack --ctorigdstport 3000 --ctdir ORIGINAL -j DROP
-A DOCKER-USER -i ens3 -p tcp --dport 3000 -j DROP
-A DOCKER-USER -j RETURN
COMMIT
DOCKER-USER est la seule chaîne que Docker laisse à l'administrateur et ne réécrit jamais. Elle s'applique avant ses propres règles. ens3 est la carte réseau publique : le trafic interne, entre conteneurs ou depuis le serveur lui-même, passe toujours.
Ce qu'un attaquant soigneux aurait effacé
Après coup, une question m'a travaillé : si le robot avait supprimé son compte admin, est-ce que j'aurais vu quelque chose ?
Non. J'aurais trouvé une page d'inscription, créé mon compte, et continué ma soirée. Tout le reste était effaçable.
Ce qu'il a laissé derrière lui
Le compte admin lab-orch
La seule chose que j'ai vue, et seulement parce que je voulais créer le mien.
Vu
Sa clé SSH chez root et chez ubuntu
Nommée « dokploy », comme une clé légitime.
Effaçable
Cinq conteneurs arrêtés, nommés orch-…
Un docker rm, et il n'en reste rien.
Effaçable
Le serveur d'upload dans /tmp
Effacé au prochain redémarrage, de toute façon.
Effaçable
La clé SSH surtout. Elle s'appelait « dokploy ». En relisant les clés autorisées de root quelques semaines plus tard, je l'aurais sans doute prise pour une clé installée par Dokploy lui-même.
Ce robot-là était bruyant : un compte au nom évident, des conteneurs laissés en place, une installation ratée. On l'a vu parce qu'il était maladroit, pas parce qu'on surveillait.
Tout réinstaller, dans l'ordre
Nettoyer aurait été tentant : supprimer le compte, la clé, les conteneurs, le fichier dans /tmp. Mais on ne nettoie que ce qu'on a trouvé. J'ai réinstallé le VPS à neuf depuis la console de l'hébergeur, et on a recommencé dans un ordre qui ne laisse aucune fenêtre ouverte :
-
SSH d'abord. Ma clé uniquement, mot de passe désactivé, connexion root interdite.
-
Le pare-feu avant Docker. ufw avec SSH, HTTP et HTTPS, et la règle
DOCKER-USERqui jette le port 3000, posée avant que Docker n'existe sur la machine. -
Un redémarrage, pour vérifier que les règles tiennent seules, sans personne pour les remettre.
-
Dokploy. Puis une vérification depuis l'extérieur : le port 3000 ne répond pas, et la base compte zéro utilisateur.
-
Mon compte, par un tunnel SSH. Le port 3000 du serveur arrive sur mon Mac, chiffré, sans jamais passer par Internet :
ssh -N -L 3000:localhost:3000 mon-vpsJ'ouvre
http://localhost:3000, je crée mon compte, et le premier visiteur est enfin moi. -
Un nom de domaine et HTTPS pour l'interface, derrière le proxy de Dokploy, avec un certificat Let's Encrypt. Le port 3000 reste fermé pour de bon, le tunnel sert de secours.
Toute la différence avec la première fois tient dans l'ordre. La première fois, on a installé, puis on a voulu sécuriser. Entre les deux, il y a eu huit minutes.
Ce que l'agent a refusé de faire
Un détail m'a amusé, après coup. Quand Claude Code a compris ce qui se passait, il a voulu arrêter Dokploy tout de suite. La commande a été refusée par le garde-fou de Claude Code : couper un service qui tourne, c'est le genre d'action qu'il ne fait pas sans mon accord. Même chose quand il a voulu lire les sessions et les clés d'API de Dokploy pour mieux comprendre : ce sont des secrets, il s'est arrêté et me l'a demandé.
Sur le moment, c'est frustrant. Le serveur est à quelqu'un d'autre et on ne peut même pas l'éteindre. Mais c'est exactement le comportement qu'on veut d'un agent qui a la main sur une machine : il regarde, il explique, et il laisse l'humain décider de ce qui casse quelque chose. De toute façon, la vraie réponse n'était pas d'arrêter Dokploy, c'était de tout réinstaller, et ça, c'était à moi de le faire.
L'erreur de départ, elle, vient aussi de l'agent : c'est lui qui avait ouvert le port 3000 au public, pour que je puisse créer mon compte. Il me l'a dit sans détour. Et je n'avais rien vérifié non plus : on a été deux à trouver ça normal.
Ce que j'en retiens
La prochaine étape, c'est d'être prévenu sans avoir de chance : une alerte quand les clés autorisées changent, quand un conteneur inconnu démarre, quand un compte est créé dans Dokploy. Ce robot-là s'est fait voir. Le prochain sera peut-être plus discret.
Et une règle, que je croyais connaître : un service qui donne l'administration au premier venu ne doit jamais être joignable avant qu'on soit ce premier venu. « Je sécurise juste après » n'existe pas sur Internet. Les scanners passent pendant le « juste ».