Настройка статического IP-адреса в Debian и Ubuntu

Опубликовано 12 мин. чтения

Фиксированные адреса IPv4 и IPv6 на Ubuntu 24.04, Ubuntu 22.04, Debian 13 и Debian 12: netplan, ifupdown и systemd-networkd в сравнении, со стратегией отката и дополнительными IP.

Четыре параметра, без которых начинать не стоит

Статический адрес прописывается за минуту. Но причина, по которой после перезагрузки так много серверов молчит, почти никогда не в синтаксисе: просто один из четырёх базовых параметров был угадан, а не считан с работающей системы. Это имя интерфейса, адрес вместе с длиной префикса, шлюз и серверы имён. Считайте эти значения на работающей машине, пока она ещё доступна.

ip -brief address show
ip -4 route show
ip -6 route show
cat /etc/resolv.conf

Первая строка выводит имя интерфейса. На виртуальных серверах он в зависимости от платформы называется ens3, enp1s0 или eth0, на bare metal чаще eno1. Имя нужно списать, а не угадать. Опечатка именно здесь даёт синтаксически безупречную конфигурацию, которая просто не подходит ни к одному существующему адаптеру.

Особенно важна длина префикса. Многие провайдеры маршрутизируют на сервер одиночный адрес IPv4 с маской /32, и тогда шлюз оказывается за пределами собственной подсети. Другие выдают классические сети /24. Какой случай у вас, показывает реально используемый маршрут:

ip route get 1.1.1.1

После этого сделайте резервную копию. Она стоит десяти секунд и определяет разницу между откатом за минуту и тикетом в поддержку.

cp -a /etc/netplan /root/netplan.bak
cp -a /etc/network/interfaces /root/interfaces.bak

Какая система сейчас управляет вашей сетью?

Debian и Ubuntu используют разные инструменты, и самый частый полный отказ возникает тогда, когда два из них одновременно настраивают один и тот же адаптер. Сначала внесите ясность:

ls -l /etc/netplan/
ls -l /etc/network/interfaces /etc/network/interfaces.d/
ls -l /etc/systemd/network/

Простое правило для четырёх актуальных версий: Ubuntu 24.04 и Ubuntu 22.04 настраиваются через netplan, который в фоне управляет systemd-networkd. Debian 13 и Debian 12 после стандартной установки работают с ifupdown и файлом /etc/network/interfaces. systemd-networkd в Debian присутствует, но не активен, а netplan там можно доустановить, хотя штатным способом настройки он не считается.

В облачных образах добавляется ещё один слой: при первом запуске cloud-init пишет собственный файл, обычно /etc/netplan/50-cloud-init.yaml, а в Debian блок в /etc/network/interfaces.d/. Если править этот файл, не остановив cloud-init, после следующей перезагрузки на месте снова окажется старая конфигурация.

Ubuntu 24.04 и 22.04: статический адрес через netplan

netplan читает все файлы в /etc/netplan/ в алфавитном порядке и переводит их в конфигурацию для systemd-networkd. Не создавайте второй файл с тем же интерфейсом, а правьте существующий или аккуратно отключите старый. Полная конфигурация с IPv4 и IPv6 выглядит так:

network:
  version: 2
  renderer: networkd
  ethernets:
    ens3:
      dhcp4: false
      dhcp6: false
      accept-ra: false
      addresses:
        - 203.0.113.10/24
        - "2001:db8:1234::2/64"
      routes:
        - to: default
          via: 203.0.113.1
        - to: default
          via: "2001:db8:1234::1"
      nameservers:
        addresses: [9.9.9.9, 149.112.112.112, 2620:fe::fe]

Три момента здесь стоит разобрать отдельно.

Во-первых, маршруты по умолчанию задаются в блоке routes, а не через gateway4 или gateway6. Оба этих ключа объявлены устаревшими начиная с netplan 0.103. На Ubuntu 22.04 и 24.04 они ещё работают, но каждый вызов сопровождается сообщением `gateway4` has been deprecated, use default routes instead. Кто пишет конфигурацию заново, пишет маршруты.

Во-вторых, accept-ra: false выключает автоматическую настройку IPv6. Если оставить её включённой и одновременно назначить фиксированный адрес, адаптер получит два адреса и два маршрута по умолчанию, а победит тот, у которого лучше метрика, а не тот, который вы задумали.

В-третьих, права на файл. Начиная с netplan 0.106 каждый вызов выдаёт предупреждение, если YAML-файл доступен на чтение другим пользователям: Permissions for /etc/netplan/01-static.yaml are too open. Netplan configuration should NOT be accessible by others. Это не косметика: в таких файлах хранятся в том числе ключи Wi-Fi и параметры туннелей.

chmod 600 /etc/netplan/*.yaml

Если шлюз находится за пределами собственной подсети

При одиночном маршрутизированном адресе с маской /32 ядро не видит прямого пути к шлюзу и отклоняет маршрут. В журнале появляется Could not set route: Network is unreachable, а при ручной попытке через ip route add ответ звучит как RTNETLINK answers: Network is unreachable. Решение называется on-link:

      addresses:
        - 203.0.113.10/32
      routes:
        - to: default
          via: 192.0.2.1
          on-link: true

Для IPv6 этот особый случай как раз и есть правило: во многих сетях в качестве шлюза указан link-local адрес fe80::1. Поскольку netplan всегда привязывает маршруты к интерфейсу, достаточно строки via: "fe80::1" в блоке соответствующего адаптера.

Как утихомирить cloud-init

Если в каталоге лежит 50-cloud-init.yaml, поставьте дополнительно блокировку, иначе при следующем запуске вся работа будет перезаписана:

echo 'network: {config: disabled}' > /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg

netplan try: команда, которая не отрежет вам доступ

Порядок такой: проверить, протестировать, зафиксировать. netplan generate транслирует YAML-файлы, ничего при этом не активируя, и сразу сообщает о синтаксических ошибках. Только после этого идёт собственно тест.

netplan generate
netplan try --timeout 120
netplan apply

netplan try применяет новую конфигурацию и автоматически возвращает прежнюю, если в отведённое время не нажать Enter. Значение по умолчанию — 120 секунд. Именно поэтому на удалённом сервере никогда не начинают с netplan apply: опечатка в адресе шлюза обрывает сессию SSH, а без страховки дело заканчивается работой через консоль или переустановкой.

Не полагайтесь на откат вслепую. Задокументированы случаи, когда netplan try после истечения таймаута так и не восстановил связь, особенно при правке файла, созданного cloud-init. После отката всегда проверяйте, действительно ли файл на диске вернулся в прежнее состояние.

Для всего, что netplan try не покрывает (и для Debian с ifupdown, где такой команды вообще нет), хорошо себя зарекомендовал второй ремень безопасности: фоновое задание, которое возвращает резервную копию, если вы вовремя не отзовётесь.

nohup sh -c 'sleep 300; cp -a /root/netplan.bak/. /etc/netplan/; netplan apply' >/dev/null 2>&1 &

Запомните номер процесса из вывода. Если всё работает, снимите задание командой kill. Если попасть на сервер больше не удаётся, он через пять минут починит систему сам. Работайте дополнительно внутри tmux или screen, чтобы оборвавшаяся сессия SSH не утащила за собой редактор прямо посреди переключения.

На KVM root-серверах последней инстанцией остаётся консоль в личном кабинете, через которую вы попадёте в систему и без работающей сети. На выделенных машинах путь назад заметно сложнее, поэтому там осторожность окупается вдвойне.

Debian 13 и 12 с /etc/network/interfaces

После стандартной установки сетью управляет ifupdown. Конфигурация построчная, и для каждого семейства адресов предусмотрен отдельный блок:

auto lo
iface lo inet loopback

auto ens3
iface ens3 inet static
    address 203.0.113.10/24
    gateway 203.0.113.1

iface ens3 inet6 static
    address 2001:db8:1234::2/64
    gateway 2001:db8:1234::1
    accept_ra 0

Строка auto ens3 действует на оба блока, вторая строка auto не нужна. Если шлюз находится за пределами подсети, помогает та же идея, что и в netplan, только записанная вручную:

iface ens3 inet static
    address 203.0.113.10/32
    post-up ip route add 192.0.2.1 dev ens3
    post-up ip route add default via 192.0.2.1
    pre-down ip route del default via 192.0.2.1

Главная ловушка в Debian — не синтаксис, а активация. systemctl restart networking ненадолго опускает адаптер, и если новая конфигурация не работает, сессия потеряна. ifdown ens3 && ifup ens3 ещё опаснее, потому что ifup никогда не выполнится, если соединение оборвётся уже на ifdown. Поэтому сначала заведите описанное выше фоновое задание, а потом выполняйте:

systemctl restart networking
systemctl status networking

Два сообщения встречаются здесь регулярно. ifup: interface ens3 already configured означает, что ifupdown до сих пор считает адаптер активным, хотя, возможно, это уже не так; состояние записано в /run/network/ifstate. А Job for networking.service failed because the control process exited with error code — это только оболочка, настоящая причина находится в выводе journalctl -xeu networking, чаще всего дважды заданный маршрут по умолчанию с сообщением RTNETLINK answers: File exists.

DNS при работе с ifupdown

Напрашивающаяся строка dns-nameservers 9.9.9.9 в файле работает только тогда, когда установлен посредник, переносящий её в /etc/resolv.conf, классически это пакет resolvconf. Без такого посредника запись остаётся без последствий, и замечают это лишь тогда, когда имена перестают разрешаться: Temporary failure in name resolution. Кто не хочет ничего доустанавливать, правит /etc/resolv.conf напрямую и проверяет командой ls -l /etc/resolv.conf, не является ли файл символической ссылкой, то есть не управляет ли им другая служба.

Debian на systemd-networkd

Если на сервере Debian вы и так пользуетесь инструментами systemd или управляете большим числом интерфейсов и туннелей, с systemd-networkd картина получается более цельной. Переход состоит из трёх шагов: создать конфигурацию, включить новую службу, остановить старую.

[Match]
Name=ens3

[Network]
Address=203.0.113.10/24
Address=2001:db8:1234::2/64
Gateway=203.0.113.1
Gateway=2001:db8:1234::1
DNS=9.9.9.9
DNS=2620:fe::fe
IPv6AcceptRA=no

Этот файл размещается по пути /etc/systemd/network/10-ens3.network. Для шлюза за пределами подсети добавьте отдельный блок маршрута:

[Route]
Gateway=192.0.2.1
GatewayOnLink=yes

Затем переключение, лучше снова со страхующим фоновым заданием за спиной:

systemctl enable --now systemd-networkd
systemctl disable networking
networkctl status ens3

Вывод networkctl status — самая честная обратная связь, которую эта тема вообще может дать. Если там стоит State: routable (configured), служба приняла файл и применила его. Если там configuring или degraded, она попыталась и не смогла, независимо от того, что команда запуска завершилась без ошибок.

Часть, отвечающая за DNS, в Debian живёт отдельно: systemd-networkd вносит серверы имён в разрешение имён только тогда, когда работает systemd-resolved и /etc/resolv.conf указывает на его файл.

apt-cache policy systemd-resolved

Этот запрос зависит от версии и обманывает незаметным образом. Отдельный пакет systemd-resolved существует только начиная с Debian 12 и Ubuntu 24.04, там команда назовёт версию. На Ubuntu 22.04 служба, наоборот, всё ещё входит в состав самого пакета systemd, и там команда отрабатывает без ошибок, но не выводит вообще ничего. Попытка установки соответственно завершается сообщением Unable to locate package systemd-resolved. Пустой вывод, таким образом, означает не отсутствие резолвера, а отсутствие пакета с таким именем в этой версии. На более старых системах вроде Debian 11 всё устроено так же. На этих версиях проверяйте иначе:

apt-cache policy systemd
systemctl status systemd-resolved

Служба включается командой systemctl enable --now systemd-resolved, после чего привычная символическая ссылка указывает на /run/systemd/resolve/stub-resolv.conf. Кому это не нужно, тот обходится без systemd-resolved и прописывает серверы имён статически в /etc/resolv.conf. Чего делать не стоит: и то и другое наполовину.

Как подключить дополнительные IP-адреса

Дополнительные адреса не особый случай, а просто ещё одна запись. В netplan список растёт:

      addresses:
        - 203.0.113.10/24
        - 203.0.113.11/24
        - 203.0.113.12/24
        - "2001:db8:1234::2/64"
        - "2001:db8:1234::3/64"

В systemd-networkd пишут несколько строк Address= одну под другой. В ifupdown дополняют существующее определение, а не заводят второе:

iface ens3 inet static
    address 203.0.113.10/24
    gateway 203.0.113.1
    post-up ip addr add 203.0.113.11/24 dev ens3
    post-up ip addr add 203.0.113.12/24 dev ens3
    pre-down ip addr del 203.0.113.11/24 dev ens3
    pre-down ip addr del 203.0.113.12/24 dev ens3

Старая запись вида ens3:0 по-прежнему работает, но это реликт эпохи до появления утилиты ip. Она не создаёт настоящих дополнительных устройств, только обозначения, и в правилах файрвола вносит больше путаницы, чем пользы.

С дополнительными адресами обычно случаются три вещи. Первая: адрес не выделен на стороне сервера. Никакая настройка операционной системы не заставит работать IP, который не маршрутизирован на ваш сервер, поэтому проверка в личном кабинете должна быть первым шагом, а не последним. Вторая: второму адресу из той же сети не полагается второй маршрут по умолчанию. Вторая запись со шлюзом по умолчанию принесёт вам RTNETLINK answers: File exists или, что хуже, плавающие пути ответа. Третья: у IPv6 почти всегда на сервер маршрутизируется целая сеть /64, то есть выбирать из диапазона можно свободно, но в качестве настроенного адреса интерфейса реально нужен только тот адрес, который назвал провайдер.

Работает ли дополнительный адрес наружу, проверяют прицельно, задав адрес источника:

ping -c 3 -I 203.0.113.11 1.1.1.1

Как понять, что настройка действительно закрепилась

То, что команда отработала без сообщений об ошибках, о состоянии сети говорит мало. А вот эти пять проверок говорят:

  1. Адрес висит на нужном адаптере: ip -brief address show показывает ровно те адреса, которые вы задали, и никаких остатков старой конфигурации.
  2. Путь наружу верный, включая адрес источника: ip route get 1.1.1.1 называет ожидаемый шлюз и ожидаемый src.
  3. У IPv6 есть собственный маршрут по умолчанию: вывод ip -6 route show default не должен быть пустым, иначе весь трафик тихо идёт через IPv4.
  4. Разрешение имён работает независимо от доступности: getent hosts deb.debian.org возвращает адрес, а не тишину.
  5. Единственная настоящая проверка — это перезагрузка. Только после неё вы узнаете, берётся ли конфигурация из файла или всё ещё из оперативной памяти.

На Ubuntu netplan status --all дополнительно выводит компактную сводку, а при systemd-networkd то же самое делает networkctl status. В спорном случае обе команды покажут, что адрес хотя и записан в файле, но так и не был применён.

Сообщения об ошибках дословно

СообщениеПричина и решение
Invalid YAML at /etc/netplan/01-static.yaml line 6 column 8: did not find expected keyТабуляция вместо пробелов или съехавший отступ. YAML не допускает табуляций, используйте по два пробела на уровень.
Error in network definition: unknown key 'gateway'В netplan такого ключа gateway нет. Добавьте запись в блок routes со значением to: default.
`gateway4` has been deprecated, use default routes insteadВсего лишь предупреждение, конфигурация ещё работает. Всё равно переходите на routes.
Permissions for /etc/netplan/… are too openПримените chmod 600 к YAML-файлу.
RTNETLINK answers: Network is unreachableШлюз находится за пределами настроенной подсети. Задайте on-link: true или GatewayOnLink=yes, либо исправьте длину префикса.
RTNETLINK answers: File existsАдрес или маршрут уже существует, чаще всего потому, что одновременно работают две системы настройки.
Error: Cannot find device "eth0"Адаптер называется иначе. Считайте имя командой ip -brief link show.
Temporary failure in name resolutionМаршрутизация работает, DNS нет. Проверьте /etc/resolv.conf и выясните, какая служба пишет этот файл.
ifup: interface ens3 already configuredifupdown считает адаптер активным. Проверьте состояние в /run/network/ifstate.

Четыре дистрибутива в прямом сравнении

Debian 12Debian 13Ubuntu 22.04Ubuntu 24.04
Штатный инструментifupdownifupdownnetplannetplan
Основной файл/etc/network/interfaces/etc/network/interfaces/etc/netplan/*.yaml/etc/netplan/*.yaml
Альтернативаsystemd-networkdsystemd-networkdsystemd-networkd напрямуюsystemd-networkd напрямую
Тест без риска потерять доступсвоё фоновое задание откатасвоё фоновое задание откатаnetplan trynetplan try
systemd-resolvedотдельный пакет, неактивенотдельный пакет, неактивенчасть пакета systemdотдельный пакет, активен
Предупреждение о правах netplanне применяетсяне применяетсяначиная с 0.106да

Если сразу после настройки сети вы запускаете файрвол, учтите, что правила для нового адреса и правила для IPv6 действуют раздельно. Как настроить это аккуратно, описано в нашем руководстве по UFW в Debian и Ubuntu, а как затем защитить доступ, в статье Защита SSH-сервера.

Коротко, для следующего сервера

Значения считать, а не угадывать, сделать резервную копию, написать конфигурацию, протестировать через netplan try или собственное фоновое задание отката, зафиксировать, перезагрузить и только потом ставить галочку. Кто соблюдает этот порядок, теряет в худшем случае пять минут. Кто его сокращает, теряет в худшем случае сервер, пока кто-нибудь не сядет за консоль.

Частые вопросы

Почему после netplan apply сервер перестал быть доступен?
Почти всегда дело в неверном шлюзе или в длине префикса, которая не соответствует сети. Поэтому на удалённых системах сначала используют netplan try: он автоматически возвращает прежнюю конфигурацию через 120 секунд, если никто не нажал Enter. Если это уже случилось, на KVM root-серверах выручает консоль в личном кабинете.
Использует ли Debian 13 netplan?
Нет. После стандартной установки Debian 13 по-прежнему настраивает сеть через ifupdown и файл /etc/network/interfaces. netplan можно доустановить из репозиториев, но в Debian это не штатный путь, и он добавляет лишний слой трансляции конфигурации. В качестве близкой к системе альтернативы подходит systemd-networkd.
Чем заменить gateway4 в netplan?
Записью в блоке routes с параметрами to: default и via: адрес шлюза. Ключи gateway4 и gateway6 объявлены устаревшими начиная с netplan 0.103 и выдают предупреждение о том, что вместо них следует использовать маршруты по умолчанию. На Ubuntu 22.04 и 24.04 старые ключи ещё работают, но при любой правке конфигурации их стоит заменить.
Почему мой /etc/resolv.conf постоянно перезаписывается?
Потому что им управляет служба: systemd-resolved, resolvconf или cloud-init. Проверьте командой ls -l /etc/resolv.conf, не является ли файл символической ссылкой. Либо вносите серверы имён туда, где их ожидает соответствующая служба, либо отключите её и ведите файл статически. Половинчатое сочетание обоих подходов приводит к отказам после перезагрузки.
Как подключить дополнительный IP-адрес?
В netplan как ещё одну запись в списке addresses, в systemd-networkd как дополнительную строку Address=, в ifupdown через post-up ip addr add. Важно, чтобы не появился второй маршрут по умолчанию и чтобы адрес вообще был маршрутизирован на ваш сервер. Это проверяют в личном кабинете, прежде чем искать причину в операционной системе.
Шлюз находится за пределами подсети, что делать?
Для одиночных маршрутизированных адресов с маской /32 это обычная ситуация. В netplan для маршрута по умолчанию задают on-link: true, в systemd-networkd в блоке маршрута GatewayOnLink=yes, в ifupdown сначала создают через post-up отдельный маршрут к шлюзу. Без этого шага ядро сообщает Network is unreachable.

Debian Ubuntu netplan systemd-networkd сеть IPv6 администрирование Linux root-сервер