HardStacked
Partager :

OpenSSH · systemd

« Failed to restart sshd.service: Unit sshd.service not found » sur Ubuntu 24.04 et Debian 13

Publié le · HardStacked · 11 min

Tu as modifié /etc/ssh/sshd_config, probablement PasswordAuthentication yes, et tu veux appliquer le changement. Les tutoriels écrits pour Red Hat, Fedora ou Arch disent sudo systemctl restart sshd. Tu tapes la commande et tu reçois Failed to restart sshd.service: Unit sshd.service not found. Pendant ce temps, SSH fonctionne. Tu es peut-être même en train de taper ça dans une session SSH.

Quelqu'un l'a demandé sur askubuntu en 2024 (question 1523856, 2024-08-19, 16 309 vues, aucune réponse acceptée), en une phrase :

« i tried to restart the daemon using sudo systemctl restart sshd and i keep getting this error »
soit « j'ai essayé de redémarrer le daemon avec sudo systemctl restart sshd et j'ai toujours cette erreur »

La seule réponse (score 8, non acceptée) dit qu'il n'est plus du tout nécessaire de redémarrer, parce que systemd lancerait un sshd tout neuf à chaque connexion. La section 07 montre pourquoi nous ne nous y fions pas. Et personne ne dit pourquoi le nom sshd existe sur certaines machines Debian et Ubuntu et pas sur la tienne, ni pourquoi il marchait avant une mise à niveau.

01. Le verdict en deux lignes

Sur Debian et Ubuntu, le service s'appelle ssh.service. sshd.service n'est pas un service, c'est un surnom : un lien symbolique sur le disque que systemctl enable ssh crée et que systemctl disable ssh retire. Le service peut très bien tourner sans son surnom. Et sur Ubuntu, d'après le script d'installation du paquet lui-même, SSH démarre par socket : une installation neuve n'active jamais ssh.service, et la mise à niveau vers le paquet 24.04 le désactive. Le surnom disparaît pendant que SSH continue de répondre.

Le message dit « l'unité n'existe pas ». La réalité : l'unité existe sous un autre nom, et le lien pour celui-ci n'est pas posé. C'est le voyant qui ment de cet article.

Les chiffres du banc ont été mesurés le 2026-10-17 sur un Raspberry Pi 5, Debian 13 trixie, systemd 257 (257.13-1~deb13u1). Les parties Ubuntu viennent de la lecture du paquet Ubuntu 24.04, pas de son exécution. Nous précisons lequel est lequel au fur et à mesure.

02. Le banc : une unité jetable avec un surnom

Pour voir la mécanique sans toucher à ton vrai sshd, le banc utilise une unité utilisateur jetable, demo-ssh.service, qui joue le rôle de ssh.service, avec Alias=demo-sshd.service pour jouer sshd.service. Elle tourne avec systemctl --user, sans sudo. Les instances utilisateur et système partagent le code d'installation; notre article sur « Cannot alias » l'a lu dans src/shared/install.c, et nous n'avons pas fait tourner ce banc précis en root. Les chemins sont filtrés à la capture ($HOME devient ~), rien n'est retouché après. Mise en place :

Ces commandes sont fournies telles quelles, sans garantie. Teste d'abord sur une machine non critique ou sur un instantané.

mise en place du banc, instance utilisateur
D=~/.config/systemd/user; mkdir -p "$D" cat > "$D/demo-ssh.service" <<'U' [Unit] Description=demo stand-in for ssh.service [Service] ExecStart=/bin/sleep infinity [Install] WantedBy=default.target Alias=demo-sshd.service U r(){ echo "\$ $*" | sed "s#$HOME#~#g"; "$@" 2>&1 | sed "s#$HOME#~#g"; echo "[exit ${PIPESTATUS[0]}]"; } systemctl --user daemon-reload

Cas A : l'unité est démarrée, jamais activée.

cas A : démarrée, jamais activée
$ systemctl --user start demo-ssh.service
[exit 0]
$ systemctl --user is-active demo-ssh.service
active [exit 0]
$ systemctl --user is-enabled demo-sshd.service
not-found [exit 4]
$ systemctl --user restart demo-sshd.service
Failed to restart demo-sshd.service: Unit demo-sshd.service not found. [exit 5]

Le service est active. Son surnom est not-found, et redémarrer par le surnom donne exactement la forme de l'erreur du titre. Cas B : enable.

cas B : enable
$ systemctl --user enable demo-ssh.service
Created symlink '~/.config/systemd/user/demo-sshd.service' → '~/.config/systemd/user/demo-ssh.service'. Created symlink '~/.config/systemd/user/default.target.wants/demo-ssh.service' → '~/.config/systemd/user/demo-ssh.service'. [exit 0]
$ env LC_ALL=C ls -go ~/.config/systemd/user/demo-sshd.service
lrwxrwxrwx 1 50 Oct 17 13:04 ~/.config/systemd/user/demo-sshd.service -> ~/.config/systemd/user/demo-ssh.service [exit 0]
$ systemctl --user is-enabled demo-sshd.service
alias [exit 0]
$ systemctl --user restart demo-sshd.service
[exit 0]
$ systemctl --user is-active demo-sshd.service
active [exit 0]

enable crée deux liens, le premier étant le surnom, et le surnom fonctionne tout de suite. La ligne ls -go montre le surnom lui-même : un lien symbolique, rien de plus.

Le cas C est celui qui compte. Même unité, maintenant disable pendant qu'elle tourne encore :

cas C : disable pendant qu'elle tourne
$ systemctl --user disable demo-ssh.service
Removed '~/.config/systemd/user/default.target.wants/demo-ssh.service'. Removed '~/.config/systemd/user/demo-sshd.service'. [exit 0]
$ systemctl --user is-active demo-ssh.service
active [exit 0]
$ systemctl --user is-enabled demo-sshd.service
not-found [exit 4]
$ systemctl --user restart demo-sshd.service
Failed to restart demo-sshd.service: Unit demo-sshd.service not found. [exit 5]

disable a retiré le lien du surnom. Le service est toujours active. Son surnom est not-found, code 4, et restart par ce nom échoue avec le code 5. Rien n'est cassé. Le surnom n'a jamais été qu'un lien que enable pose et que disable enlève.

03. Pourquoi le surnom vit dans [Install]

Alias=sshd.service est dans la section [Install] de ssh.service. Tout ce qui est dans [Install] n'agit qu'au moment du enable (ou du disable pour le défaire). Le service en marche ne le lit jamais. Nous avons extrait les vraies unités du paquet Ubuntu 24.04 (openssh-server 1:9.6p1-3ubuntu13, arm64, lu le 2026-10-17, rien d'installé) et de Debian 13 (1:10.0p1-7+deb13u4). Les deux fichiers ont exactement la même section [Install] :

ssh.service, identique sur Ubuntu 24.04 et Debian 13
[Install] WantedBy=multi-user.target Alias=sshd.service

L'alias est donc identique des deux côtés. La différence, c'est de savoir si quelque chose lance un jour enable sur ssh.service. Même mécanique que l'article sur Cannot alias : l'alias est un lien posé à l'activation, pas une propriété de l'unité en marche.

04. Ubuntu : une installation neuve n'active jamais ssh.service

Ubuntu démarre SSH par socket. L'annonce officielle, « SSHd now uses socket-based activation (Ubuntu 22.10 and later) » sur discourse.ubuntu.com, dit que le socket est le défaut depuis openssh-server 1:9.0p1-1ubuntu1. Le ssh.socket du paquet a cet [Install] :

ssh.socket, Ubuntu 24.04
[Install] WantedBy=sockets.target RequiredBy=ssh.service

Voyons maintenant le script d'installation du paquet 24.04. Ce sont les vraies lignes, en deux blocs séparés. D'abord le socket (lignes 183 à 192) :

postinst, Ubuntu 24.04, lignes 183 à 192
# was-enabled defaults to true, so new installations run enable. if deb-systemd-helper --quiet was-enabled 'ssh.socket'; then # Enables the unit on first installation, creates new # symlinks on upgrades if the unit file has changed. deb-systemd-helper enable 'ssh.socket' >/dev/null || true else # Update the statefile to add new symlinks (if any), which need to be # cleaned up on purge. Also remove old symlinks. deb-systemd-helper update-state 'ssh.socket' >/dev/null || true fi

Puis le service (lignes 197 à 205) :

postinst, Ubuntu 24.04, lignes 197 à 205
if deb-systemd-helper debian-installed 'ssh.service'; then # The following line should be removed in trixie or trixie+1 deb-systemd-helper unmask 'ssh.service' >/dev/null || true if deb-systemd-helper --quiet was-enabled 'ssh.service'; then # Create new symlinks, if any. deb-systemd-helper enable 'ssh.service' >/dev/null || true fi fi

Ce que dit le script : ssh.socket est activé sur une nouvelle installation, parce que was-enabled vaut vrai par défaut. ssh.service n'est activé que if deb-systemd-helper debian-installed 'ssh.service', c'est-à-dire que le service doit déjà être connu de dpkg. Sur une machine neuve, il ne l'est pas. Donc ssh.service n'est jamais activé, le lien sshd.service n'est jamais créé, et restart sshd répond not found. Ce deuxième pas, le sens de debian-installed sur une machine neuve, est notre lecture du code. Nous ne l'avons pas exécuté sur un vrai Ubuntu. Prends-le comme « ce que dit le script du paquet, lu le 2026-10-17 », pas comme une mesure.

05. Ubuntu : la mise à niveau retire le surnom d'une machine où il marchait

C'est le cas « ça marchait hier ». Dans le même script (ligne 133, puis 143 à 159 ; les lignes 134 à 142 ne font que nettoyer d'anciens fichiers de configuration et sont coupées ici), quand on vient d'une version plus ancienne que 1:9.6p1-3ubuntu3 :

postinst, Ubuntu 24.04, ligne 133 puis 143 à 159
if dpkg --compare-versions "$2" lt-nl 1:9.6p1-3ubuntu3~; then if [ -d /run/systemd/system ]; then if dpkg --compare-versions "$2" ge 1:9.3p1-1ubuntu3~ && ! systemctl --quiet is-enabled ssh.socket; then # If we are upgrading from a version that was # already migrated, but ssh.socket is disabled, # then leave it that way. : else # Make sure ssh.service is disabled. systemctl unmask ssh.service systemctl disable --now ssh.service > /dev/null 2>&1 # sshd-socket-generator is invoked on daemon-reload. systemctl daemon-reload systemctl enable ssh.socket fi fi fi

Lis-le tel qu'écrit : sauf si la machine était déjà migrée avec le socket volontairement désactivé (la première branche, qui laisse tout tel quel), le script lance systemctl disable --now ssh.service, puis systemctl enable ssh.socket. Grâce au cas C du banc, tu sais ce que disable fait au surnom : il retire le lien. Donc sshd.service était un nom valide sur ta machine avant la mise à niveau, et après, il ne l'est plus. SSH répond toujours parce que le socket écoute. Encore une fois : lu dans le paquet, pas exécuté sur une vraie mise à niveau Ubuntu.

06. Debian 13 : le surnom existe tant que ssh.service est activé

Debian, c'est le cas normal. Sortie réelle d'un Pi 5 sous Debian 13, lecture seule, le 2026-10-17, masquée :

un Pi 5 sous Debian 13, lecture seule
OS: Debian GNU/Linux 13 (trixie) openssh-server 1:10.0p1-7+deb13u4
$ systemctl is-enabled ssh.service
enabled
$ systemctl is-enabled ssh.socket
disabled
$ systemctl is-enabled sshd.service
alias
$ ls -go /etc/systemd/system/sshd.service
lrwxrwxrwx 1 35 Jul 26 20:40 /etc/systemd/system/sshd.service -> /usr/lib/systemd/system/ssh.service

ssh.service est activé, ssh.socket est désactivé, et is-enabled sshd.service répond alias. Le lien dans /etc/systemd/system pointe vers ssh.service. C'est une autre machine que celle du banc, la même mécanique que le cas B. Le jour où quelqu'un désactive ssh.service ou passe au socket, cette machine donnerait la même erreur que le titre. Cette partie, c'est le cas C du banc, pas quelque chose que nous avons fait sur ce Pi.

07. Diagnostiquer en trois commandes, puis corriger

Sur ta machine, instance système, donc sans --user.

  1. systemctl is-enabled sshd.service. alias veut dire que le surnom est en place. not-found veut dire qu'il ne l'est pas. Les deux mots apparaissent dans les sorties plus haut.
  2. systemctl is-enabled ssh.service ssh.socket. Ça te dit qui démarre SSH : le service, le socket, ou les deux.
  3. ls -l /etc/systemd/system/sshd.service. Le lien lui-même, présent sur le vrai Debian ci-dessus (nous avons utilisé ls -go, qui retire les colonnes du propriétaire et du groupe).

Faut-il seulement redémarrer ? La seule réponse sur askubuntu dit que non : systemd lancerait un sshd tout neuf à chaque connexion, donc la prochaine connexion lirait la nouvelle config. Le socket livré par Ubuntu dit autre chose. Il contient Accept=no, et le manuel de systemd définit ça ainsi : « only one service unit is spawned for all connections » (une seule unité de service est lancée pour toutes les connexions). Donc dès la première connexion, un seul sshd de longue durée, le même ssh.service, tient le socket. Qu'il relise ta modification à la connexion suivante, nous ne l'avons pas mesuré, donc nous ne nous y fions pas.

La correction, c'est d'utiliser le vrai nom : sudo systemctl reload ssh. Dans les paquets Ubuntu 24.04 et Debian 13, ssh.service définit le rechargement en deux commandes, /usr/sbin/sshd -t puis /bin/kill -HUP $MAINPID. man sshd dit que -t est « Test mode. Only check the validity of the configuration file and sanity of the keys » (mode test : vérifie seulement la validité du fichier de configuration et l'état des clés), et que sshd « rereads its configuration file when it receives a hangup signal » (relit son fichier de configuration quand il reçoit le signal HUP). systemd lance ces commandes dans l'ordre et, d'après son manuel, si l'une échoue, « other lines are not executed » (les lignes suivantes ne sont pas exécutées). Un sshd_config brisé arrête donc le rechargement avant l'envoi du signal. sudo systemctl restart ssh marche aussi, mais reload vérifie d'abord. Ce que -t ne peut pas attraper, c'est un réglage valide qui te met dehors, comme la connexion par mot de passe coupée avant que ta clé soit installée. Si tu es connecté par SSH, garde cette session ouverte et teste une deuxième connexion avant de la fermer ; voir l'article sur le verrouillage.

Si tu veux vraiment retrouver le nom sshd sur Ubuntu, l'annonce d'Ubuntu donne le chemin de retour vers l'ancien comportement : systemctl disable --now ssh.socket, supprimer /etc/systemd/system/ssh.service.d/00-socket.conf et /etc/systemd/system/ssh.socket.d/addresses.conf, systemctl daemon-reload, puis systemctl enable --now ssh.service. C'est ce dernier enable qui recréerait le lien sshd.service (cas B du banc). Nous n'avons pas lancé cette séquence : prends-la comme le chemin documenté par Ubuntu, pas comme quelque chose que nous avons testé.

08. Le piège inverse : les scripts écrits pour une autre distribution

Les scripts, rôles Ansible et tutoriels écrits pour Red Hat, Fedora ou Arch utilisent sshd parce que là-bas l'unité s'appelle vraiment sshd.service. Copie ça sur Ubuntu 24.04 et ça échoue sur ce message exact. Aide-mémoire : RHEL sshd, Debian et Ubuntu ssh. Si tu maintiens un rôle pour les deux familles, choisis le nom par famille au lieu d'en supposer un.

09. Le voisin : changer le port sur Ubuntu

Sur Ubuntu en mode socket, Port et ListenAddress de sshd_config sont lus par un générateur, sshd-socket-generator, livré dans le paquet. Chaînes extraites du binaire :

chaînes de sshd-socket-generator, Ubuntu 24.04
# Automatically generated by sshd-socket-generator ListenStream= ListenStream=%s

Il écrit ssh.socket.d/addresses.conf. L'annonce d'Ubuntu dit la même chose pour 24.04 : « the port and address settings are pulled dynamically from sshd.conf via a systemd generator » (le port et les adresses sont lus dynamiquement par un générateur systemd). Changer le port demande donc probablement un systemctl daemon-reload et un redémarrage de ssh.socket, pas seulement un rechargement du service. Cette dernière étape est inférée du paquet et de l'annonce, pas mesurée. L'histoire du port a son propre article : changer le port SSH.

10. Ce qui a été testé, ce qui ne l'a pas été

Mesuré : Debian 13 trixie, systemd 257, le banc plus une machine réelle. Lu sans exécuter : le paquet Ubuntu 24.04 1:9.6p1-3ubuntu13. Non mesuré : un vrai Ubuntu, Ubuntu 22.10 ou 23.x, Red Hat.

La même forme traverse le reste de cette série, où le système déclare une chose et en fait une autre : un pare-feu que l'unité systemd déclare activé alors qu'il est éteint, un service WireGuard qui se déclare actif alors qu'aucune interface n'existe, et un timedatectl qui affiche NTP service: active alors que l'horloge n'a jamais reçu l'heure.

Partager :