Systemd против NetworkManager: кто запускает VPN при загрузке?
Три механизма могут поднять один и тот же профиль Ubuntu, у каждого свой триггер. Сравните их, оставьте одного владельца и уберите дубликат.
Две машины Ubuntu из одного образа, один профиль VPN, противоположные результаты при входе: на одной туннель поднят ещё до появления рабочего стола, на другой он не поднимается никогда. Профиль здесь не переменная. Разница в том, какому из трёх компонентов было поручено его запускать, и эти три не делят один переключатель.
Сравнить их рядом быстрее, чем гадать. Каждый из них отказывает узнаваемым образом, и именно поэтому сравнение того стоит.
Три средства запуска с тремя разными триггерами
Пакетная служба openvpn — самый старый путь. Её init-скрипт читает список автозапуска из /etc/default/openvpn. Если список закомментирован или оставлен пустым, скрипт запускает все конфигурации, найденные в этом каталоге, а не ту единственную, которую вы добавили. Один файл, добавленный для одного туннеля, может тихо поднять несколько.
| Starter | What triggers it | Typical failure |
|---|---|---|
| Init script and templated units | Boot, plus anything in the autostart list | Starts every config, not the one you meant |
| NetworkManager secondary | Activation of the base Wi-Fi or Ethernet profile | Nothing happens until that base link comes up |
| Hand-written unit or wrapper | Whatever its WantedBy and ExecStart say | Runs a different binary or environment than your shell |
Вторая строка — та, которую настраивают неправильно. NetworkManager держит импортированный профиль и запустит его, но только как вторичный у другого соединения, то есть триггер принадлежит сетевому звену, а не VPN.
Сравните стоимость настройки и охват
Путь через init-скрипт стоит одну строку и покрывает каждую конфигурацию на машине. Это годится для роутера и не годится для ноутбука, который подключается к разным сетям. Путь через NetworkManager стоит поиска UUID и привязывает туннель к одному базовому соединению. Он поднимается в рабочей сети и остаётся выключенным в гостиничной.
Написанный вручную unit стоит дороже всего и даёт больше всего контроля, включая порядок относительно других служб. Решающий фактор — охват. Если у машины одна сеть и один туннель, пакетная служба честна и предсказуема. Если туннель должен следовать за конкретной сетью Wi-Fi, вторичный — единственный из трёх, кто выражает это условие без дополнительных скриптов.
Выберите одного владельца и уберите остальных
Профиль, который запускают два владельца, даёт тайминг, меняющийся от загрузки к загрузке, а это хуже любого из механизмов по отдельности. Выберите владельца и затем отключите конкурирующий путь намеренно, а не случайно.
# who is configured to start something?
grep -v '^#' /etc/default/openvpn
systemctl list-units 'openvpn*'
nmcli -g connection.secondaries connection show 'Work Wi-Fi'
# NetworkManager: attach the tunnel to the base link by UUID
TUNNEL=$(nmcli -g UUID connection show 'Corp Tunnel')
nmcli connection modify 'Work Wi-Fi' +connection.secondaries "$TUNNEL"
Если выводится именно пакетный путь, делайте это в правильном порядке: установите AUTOSTART в none, выполните systemctl daemon-reload, чтобы сгенерированные unit-ы подхватили новый список, и затем отключите шаблонный экземпляр, который больше не нужен. Пропуск перезагрузки оставляет старые unit-ы активными, и кажется, будто изменение ни на что не повлияло.
Зависающая остановка — отдельная проблема с ограниченным ответом. TimeoutStopSec задаёт, сколько systemd ждёт перед отправкой SIGKILL. Правильное место задать это — drop-in, потому что правка пакетного unit-а теряет изменение при следующем обновлении.
Проверьте, что именно запустилось
Перезагрузите машину и читайте доказательства, а не доверяйте файлу конфигурации. Unit, владеющий туннелем, покажет активное состояние и время запуска, совпадающее с загрузкой, а интерфейс VPN будет существовать ещё до вашего входа.
systemctl is-enabled openvpn-client@office
systemctl status openvpn-client@office --no-pager
nmcli -f GENERAL.STATE,connection.secondaries connection show 'Work Wi-Fi'
ip -brief link show tun0
Здесь уместна ещё одна проверка: убедитесь, что ExecStart unit-а указывает на тот бинарник, о котором вы думаете. Клиент, собранный локально, или пакет snap часто требует явного пути или обёртки snap run, потому что systemd не наследует порядок поиска вашей оболочки. Сравнение command -v openvpn с файлом unit-а решает это за секунды.
Запишите выбранного владельца в заметки машины, рядом с именем профиля. Следующий человек, который будет искать пропавший туннель, начнёт с этой строки, а не станет повторять сравнение.