Что было. Виртуальная машина с 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 стартует до получения адреса и начинает принимать соединения, как только адрес появится. Подтверждено.
Варианты по предпочтительности.
- Не привязываться к адресу.
ListenAddress 0.0.0.0(и::) плюс ограничение доступа брандмауэром по интерфейсу или адресам источника. Для сервера с одним интерфейсом привязка к конкретному адресу ничего не добавляет к безопасности. - Дождаться сети. Drop-in для службы:
After=network-online.target,Wants=network-online.target; на Ubuntu сssh.socketпорт задаётся в сокете, и socket-активация сама решает вопрос порядка (отдельный разбор). - Статический адрес в netplan/networkd вместо DHCP, если адрес всё равно постоянный.
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.