Sshd в виртуальной машине не стартует при загрузке с «Cannot assign requested address», а вручную запускается: ListenAddress на адресе, которого ещё нет

Что было. Виртуальная машина с Debian 13, sshd настроен слушать конкретный адрес и нестандартный порт (ListenAddress 192.0.2.51:8022). После перезагрузки служба в состоянии failed; systemctl start ssh вручную работает. В журнале: Bind to port 8022 on 192.0.2.51 failed: Cannot assign requested address.

Причина. Адрес выдаётся по DHCP, а sshd запускается раньше, чем интерфейс его получил. Привязка к несуществующему адресу невозможна, служба завершается. Автор сначала перевёл интерфейс на статический адрес (помогло), затем нашёл более гибкий вариант: разрешить привязку к нелокальным адресам параметром ядра net.ipv4.ip_nonlocal_bind = 1, после чего sshd стартует до получения адреса и начинает принимать соединения, как только адрес появится. Подтверждено.

Варианты по предпочтительности.

  1. Не привязываться к адресу. ListenAddress 0.0.0.0 (и ::) плюс ограничение доступа брандмауэром по интерфейсу или адресам источника. Для сервера с одним интерфейсом привязка к конкретному адресу ничего не добавляет к безопасности.
  2. Дождаться сети. Drop-in для службы: After=network-online.target, Wants=network-online.target; на Ubuntu с ssh.socket порт задаётся в сокете, и socket-активация сама решает вопрос порядка (отдельный разбор).
  3. Статический адрес в netplan/networkd вместо DHCP, если адрес всё равно постоянный.
  4. ip_nonlocal_bind как последний вариант: работает, но глобально разрешает всем службам биндиться на любые адреса, что скрывает ошибки конфигурации.

Как проверить, что причина именно в порядке загрузки. journalctl -b -u ssh с временными метками против journalctl -b -u systemd-networkd (или NetworkManager): если Bind … failed на секунды раньше DHCPv4 address … acquired, диагноз ясен. systemd-analyze critical-chain ssh.service покажет, от чего служба ждала.

Похожие случаи. Любая служба с bind/listen на конкретный адрес (nginx с listen 192.0.2.51:443, база данных с bind-address, DNS-сервер с listen-on) ведёт себя так же; лечение те же четыре варианта. Для nginx и подобных Restart=on-failure с RestartSec=5 тоже спасает: вторая попытка застаёт адрес на месте.

Параметр ядра описан в документации Linux.