Как безопасно обновить Linux-сервер через apt
Разница между upgrade, full-upgrade и dist-upgrade, придержанные пакеты, запросы dpkg о файлах конфигурации, перезагрузка после обновления ядра с needrestart и смена версии дистрибутива как отдельная задача.
На свежем сервере обновление — чистая формальность: ломаться там просто нечему. Но как только на сервере работают боевые службы, всё решают детали: пройдёт ли обновление незаметно или после него окажется перезаписан файл конфигурации, останется служба со старой библиотекой в памяти, а работающее ядро будет уже не тем, что лежит на накопителе. В этой статье все эти детали разобраны по порядку. Краткая версия для только что выданного сервера собрана в чек-листе для нового root-сервера.
Все сведения относятся к Debian 13 (trixie), Debian 12 (bookworm), Ubuntu 24.04 LTS и Ubuntu 22.04 LTS. Команды рассчитаны на работу от имени root. Если вы работаете под обычным пользователем, добавляйте перед каждой командой sudo.
Прежде чем ввести первую команду: путь назад
Обновление может дорого обойтись тремя способами: диалог о файле конфигурации перезапишет настройки SSH, новое ядро не загрузится, или соединение оборвётся посреди транзакции dpkg. Все три случая управляемы, но только если позаботиться об этом заранее.
Сессия, которая переживёт обрыв соединения
Если SSH-соединение оборвётся во время распаковки, работающий процесс получит SIGHUP, и dpkg завершится посреди транзакции. В итоге вы получите наполовину настроенную базу пакетов. Поэтому длительные обновления запускайте в такой сессии, которая продолжит работать на сервере, даже когда ваш терминал исчезнет:
apt install -y tmux
tmux new -s upgrade
Если соединение пропало, войдите заново и верните сессию командой tmux attach -t upgrade. Всё это время процесс продолжал работать.
Как попасть на сервер, когда SSH больше не отвечает
На KVM root-серверах и выделенных серверах KernelHost вам доступна VNC-консоль в личном кабинете. Она не зависит от сетевого стека гостевой системы и работает даже тогда, когда ни одна служба уже не слушает порт. Зайдите через неё один раз заранее и убедитесь, что знаете пароль root.
На случай, если ядро не загрузится, вам понадобится ещё и видимое меню загрузки. На серверах его часто скрывают:
grep -E '^GRUB_TIMEOUT|^GRUB_TIMEOUT_STYLE' /etc/default/grub
Если там указано GRUB_TIMEOUT_STYLE=hidden или GRUB_TIMEOUT=0, поставьте GRUB_TIMEOUT_STYLE=menu и GRUB_TIMEOUT=5, а затем выполните update-grub. В аварийной ситуации выберите в VNC-консоли в разделе «Advanced options» предыдущее ядро.
Проверить и зафиксировать состояние
Три предварительные проверки, которые находят что-нибудь чаще, чем принято думать:
df -h / /boot /var
dpkg --audit
apt-get check
Контрольная проверка: dpkg --audit ничего не выводит, apt-get check отрабатывает без строк с ошибками, а в /boot свободно не меньше 300 МБ. Заполненный /boot — самая частая причина сорвавшегося обновления ядра, подробнее об этом в статье диск заполнен в Linux. Если dpkg --audit о чём-то сообщает, сначала почините это командой dpkg --configure -a.
Затем сохраните текущее состояние, чтобы позже было с чем сравнивать:
dpkg --get-selections > /root/packages-before-upgrade.txt
apt-mark showhold > /root/holds-before-upgrade.txt
cp -a /etc/apt /root/apt-config-$(date +%F)
update, upgrade, full-upgrade и dist-upgrade
Эти четыре слова путают постоянно. Разница между ними не косметическая: именно от неё зависит, установится ли новое ядро и разрешено ли пакетам исчезать.
| Команда | Новые пакеты | Удаляет пакеты | Когда применять |
|---|---|---|---|
apt update | нет | нет | только скачивает списки пакетов, в системе ничего не меняет |
apt-get upgrade | нет | нет | самый осторожный вариант, придерживает обновления ядра |
apt upgrade | да, если этого требует зависимость | нет | обычный случай на боевых системах |
apt full-upgrade | да | да, при необходимости | когда вы осознанно допускаете удаление |
apt-get dist-upgrade | да | да, при необходимости | более старое название того же самого |
Отсюда следуют два вывода. Первый: dist-upgrade не имеет никакого отношения к переходу на новую версию дистрибутива. Название историческое, а сама команда остаётся в пределах вашей текущей версии.
Второй: именно разница между apt upgrade и apt-get upgrade объясняет, почему некоторые серверы остаются без нового ядра. В Debian ядро подключается через метапакет linux-image-amd64, в Ubuntu через linux-image-generic или linux-image-virtual. При каждой смене ABI этот метапакет начинает указывать на новый пакет, номер версии которого входит в имя. apt-get upgrade принципиально не устанавливает новые пакеты и поэтому оставляет ядро лежать нетронутым, а apt upgrade его ставит, потому что этого требует зависимость. Если вы используете apt-get upgrade в скрипте обслуживания, добавьте туда ещё и --with-new-pkgs.
О выборе инструмента: при запуске из скрипта apt выводит строку WARNING: apt does not have a stable CLI interface. Use with caution in scripts. Это не сообщение об ошибке, но предупреждение по делу. В скриптах и ролях Ansible место у apt-get, а в интерактивной работе удобнее apt.
Порядок действий с проверкой после каждого шага
Шаг 1: получить списки пакетов.
apt update
Контрольная проверка: в выводе нет ни одной строки, начинающейся с Err: или W:. В конце стоит либо All packages are up to date., либо число, за которым следует packages can be upgraded. Любая строка с ошибкой здесь означает, что дальше вы работали бы с неполной картиной.
Шаг 2: посмотреть, что именно придёт. Этого шага нет в большинстве инструкций, а он самый важный во всём порядке действий.
apt list --upgradable
apt full-upgrade -s
Ключ -s только моделирует и ничего не меняет. Строки под заголовком The following packages will be REMOVED: — единственное, что действительно нужно проверить. Если там пусто, full-upgrade так же безобиден, как и upgrade. Если там оказался нужный вам пакет, возьмите apt upgrade, а причину разберите отдельно.
В Debian дополнительно стоит выполнить apt install apt-listchanges. Этот пакет показывает перед установкой changelog и, что важнее, файлы NEWS от сопровождающих пакетов. Именно там написано то, что придётся делать руками.
Шаг 3: установить обновления.
apt upgrade
Не отходите от терминала. Процесс задаёт вопросы, а -y отвечает только на собственный вопрос apt, но не на запросы по файлам конфигурации. Их задаёт dpkg, и он терпеливо ждёт, пока кто-нибудь ответит.
Контрольная проверка:
apt list --upgradable
dpkg --audit
systemctl --failed
journalctl -p 3 -b --no-pager | tail -n 20
Ожидается следующее: apt list --upgradable не выводит ничего, кроме Listing..., dpkg --audit молчит, а systemctl --failed сообщает 0 loaded units listed. Что произошло на самом деле, постоянно хранится в /var/log/apt/history.log, а полный вывод dpkg в /var/log/apt/term.log.
Придержанные пакеты: две разные причины
Если apt пропускает пакеты, у этого бывают две принципиально разные причины, которые регулярно путают.
Первая: настоящая блокировка. Кто-то явно зафиксировал пакет:
apt-mark showhold
Если команда что-то выводит, это было осознанное решение, чаще всего для баз данных или модулей ядра. Снимается блокировка командой apt-mark unhold ИМЯ_ПАКЕТА, ставится командой apt-mark hold ИМЯ_ПАКЕТА. Блокировку на уровне dpkg видно через dpkg --get-selections | grep -w hold.
Вторая: сообщение The following packages have been kept back:. Это не блокировка. Оно означает, что ради такого обновления apt пришлось бы дополнительно установить один пакет или удалить другой, а использованная команда этого делать не вправе. Проверить это можно одной строкой, ничего не меняя:
apt full-upgrade -s | head -n 20
Если пакет там появляется, объяснение найдено, и apt full-upgrade снимает вопрос. В Debian 13 новое поколение apt форматирует этот вывод иначе, но по содержанию не меняется ничего.
Особый случай Ubuntu. Ubuntu выкатывает обновления поэтапно, и не все серверы получают их в один день. Поэтому пакет может оказаться придержанным, хотя ни блокировки нет, ни зависимость не мешает. Диагностика идёт методом исключения: apt-mark showhold пуст, apt full-upgrade -s не показывает удалений, а apt-cache policy ИМЯ_ПАКЕТА всё равно сообщает о более новом кандидате. Тогда подождите несколько дней или заберите обновление досрочно:
apt -o APT::Get::Always-Include-Phased-Updates=true upgrade
В Debian 13 и Debian 12 поэтапной выкатки нет, там эта причина отпадает сразу.
Когда apt спрашивает про файл конфигурации
Такой запрос появляется только при совпадении двух условий: файл после установки меняли локально, и пакет приносит с собой новую версию. Выглядит это так:
Configuration file '/etc/ssh/sshd_config'
==> Modified (by you or by a script) since installation.
==> Package distributor has shipped an updated version.
What would you like to do about it ? Your options are:
Y or I : install the package maintainer's version
N or O : keep your currently-installed version
D : show the differences between the versions
Z : start a shell to examine the situation
The default action is to keep your current version.
*** sshd_config (Y/I/N/O/D/Z) [default=N] ?
По умолчанию выбрано N, то есть сохранить вашу версию. Это безопасный ответ, но не во всех случаях правильный.
| Ситуация | Ответ |
|---|---|
| Вы уже не помните, что именно меняли | D, посмотреть разницу и только потом решать |
| Ваши правки внесены осознанно, а пакет меняет только комментарии | N, затем сравнить с файлом .dpkg-dist |
| Файл создан инструментом вроде cloud-init или Ansible | N, затем запустить этот инструмент заново |
| Новые значения важны для безопасности, а ваша правка не нужна | Y, затем заново внести свои настройки |
| Файл критичный, и вы не уверены | Z, скопировать файл в сторону, выйти из shell, затем N |
С /etc/ssh/sshd_config нужна особая осторожность: ответ Y может вернуть PermitRootLogin и PasswordAuthentication к значениям из пакета, а именно от них зависит ваш доступ. Поэтому собственные настройки SSH стоит держать в отдельном файле в каталоге /etc/ssh/sshd_config.d/, как описано в статье защита SSH и вход по ключу. Файл, которого в пакете вообще нет, никогда не вызовет такой запрос.
Что бы вы ни ответили, dpkg ничего не выбрасывает. При N новая версия ложится рядом с расширением .dpkg-dist, при Y ваша прежняя сохраняется как .dpkg-old. Разбор этих файлов и есть настоящая работа после обновления:
find /etc -name '*.dpkg-dist' -o -name '*.dpkg-old' -o -name '*.dpkg-new' -o -name '*.ucf-dist'
diff -u /etc/ssh/sshd_config /etc/ssh/sshd_config.dpkg-dist
Для автоматических запусков, например в скрипте обслуживания, поведение задают заранее. Такая комбинация сохраняет вашу версию и ничего не спрашивает:
DEBIAN_FRONTEND=noninteractive apt-get -y \
-o Dpkg::Options::="--force-confdef" \
-o Dpkg::Options::="--force-confold" \
upgrade
--force-confnew делает ровно противоположное и всегда берёт версию из пакета. На сервере с собственной конфигурацией это редко то, чего вы хотите.
Обновления ядра и вопрос о перезагрузке
Новое ядро при установке попадает в /boot и в меню загрузки. А работающее ядро остаётся в памяти без изменений вплоть до перезагрузки. Поэтому сервер может быть одновременно полностью обновлённым и уязвимым. Проще всего проверить это сравнением:
uname -r
ls -1 /boot/vmlinuz-*
Если в /boot лежит версия выше той, которую сообщает uname -r, перезагрузка назрела. В Ubuntu 24.04 и 22.04 есть ещё и файл-признак, который учитывает также обновления библиотек:
test -f /var/run/reboot-required && cat /var/run/reboot-required.pkgs
Второй файл перечисляет пакеты, которые запросили перезагрузку. В Debian 13 и Debian 12 этот признак создаётся не всегда надёжно, поэтому там правильный путь — needrestart.
needrestart: какие службы всё ещё используют старую библиотеку
Обновление OpenSSL или glibc заменяет файл на накопителе. Но каждый процесс, который уже загрузил его, продолжает работать со старой версией. needrestart находит именно такие процессы. В Ubuntu 24.04 и 22.04 он предустановлен и после каждого обновления открывает полноэкранный диалог, а в Debian его нужно доустановить:
apt install -y needrestart
needrestart -b
Режим -b выдаёт машиночитаемый вывод. Два значения в нём решающие: NEEDRESTART-KSTA со значением 1 означает, что работает ожидаемое ядро, а любое другое значение говорит, что наготове уже более новое. Каждая строка NEEDRESTART-SVC называет службу, которую следует перезапустить.
Поведением управляет переменная окружения NEEDRESTART_MODE: a перезапускает службы автоматически, l только выводит список, i спрашивает. На постоянной основе то же самое задаётся в /etc/needrestart/needrestart.conf. Для скриптов переменная подходит лучше, потому что она ничего не меняет в конфигурации:
NEEDRESTART_MODE=a DEBIAN_FRONTEND=noninteractive apt-get -y upgrade
Об одном ограничении стоит знать: needrestart смотрит на процессы хостовой системы. Службы внутри контейнеров он не обновляет, там нужны новые образы.
Смена версии дистрибутива — отдельная категория
Переход с Debian 12 на Debian 13 или с Ubuntu 22.04 на 24.04 — это не обновление в описанном выше смысле. Он подменяет источники пакетов и заменяет практически каждый пакет. Здесь всегда действуют три правила: одна версия за один заход, никаких пропущенных промежуточных версий и заранее сделанная резервная копия, из которой сервер можно восстановить.
В Debian сначала переключают источники. Debian 12 использует для этого /etc/apt/sources.list, Debian 13 — файл /etc/apt/sources.list.d/debian.sources в новом формате. Дальше идёт намеренно двухступенчатый порядок действий, который так и предписан в примечаниях к выпуску:
apt update
apt-get upgrade --without-new-pkgs
apt full-upgrade
Средний шаг сначала обновляет пакеты, которые обходятся без перестройки зависимостей. Так число одновременно перемещаемых пакетов остаётся небольшим, а прерванный процесс поддаётся ремонту. Не забудьте про компонент non-free-firmware: начиная с Debian 12 он вынесен отдельно и в старых файлах источников отсутствует. Если ваш apt знает команду apt modernize-sources (проверяется через apt --version), она переведёт старый файл источников в новый формат.
В Ubuntu для этого есть собственный инструмент, и пользоваться следует исключительно им:
apt install -y ubuntu-release-upgrader-core
do-release-upgrade -c
do-release-upgrade
Ключ -c только проверяет и ничего не меняет. Предложат ли вам переход, зависит от параметра Prompt в /etc/update-manager/release-upgrades: при значении lts предлагается только переход на следующую LTS-версию, причём лишь после её первого промежуточного выпуска. Путь с 20.04 на 24.04 обязательно проходит через 22.04.
Деталь, которая многих удивляет: если do-release-upgrade запущен через SSH, он поднимает дополнительную службу SSH на порту 1022 как запасной путь и предупреждает, что этот порт, возможно, придётся открыть в файрволе. Пользуйтесь этим, но не полагайтесь только на него. Сессия tmux и доступ через VNC-консоль надёжнее.
Уборка после обновления
После крупного обновления остаются три вида мусора: скачанные файлы пакетов, осиротевшие пакеты и остатки конфигурации от удалённых пакетов.
apt autoremove --purge
apt autoclean
autoclean удаляет из /var/cache/apt/archives только те файлы, которые всё равно больше не предлагаются. apt clean очищает кэш полностью, то есть освобождает больше места, но зато превращает каждую повторную установку в новую загрузку.
Остатки конфигурации узнаются по статусу dpkg rc, то есть пакет удалён, а конфигурация ещё на месте:
dpkg -l | awk '/^rc/ {print $2}'
Всё, что там перечислено, окончательно удаляется командой apt purge ИМЯ_ПАКЕТА. Со старыми ядрами нужна большая аккуратность, потому что одна ошибка сделает сервер незагружаемым:
uname -r
dpkg -l 'linux-image-*' | awk '/^ii/ {print $2}'
Никогда не удаляйте ядро, которое называет первая строка, и дополнительно оставьте одно рабочее ядро постарше, чтобы в меню загрузки был запасной вариант. Обычно apt autoremove --purge и так делает это правильно.
Частые ошибки и их решения
E: Could not get lock /var/lib/dpkg/lock-frontend. It is held by process 1234 (unattended-upgr): уже идёт вторая операция с пакетами, чаще всего автоматическое обновление безопасности. Её не надо прерывать, надо дать ей доработать до конца. Полный порядок действий вместе с ремонтом описан в статье apt не удалось получить блокировку.
E: dpkg was interrupted, you must manually run 'dpkg --configure -a' to correct the problem.: предыдущий запуск был прерван, как правило обрывом соединения. Выполните ровно эту команду и после неё повторите обновление.
E: Unmet dependencies. Try 'apt --fix-broken install' with no packages (or specify a solution).: пакет установлен, а его зависимостей не хватает. apt --fix-broken install доустанавливает их. Если ошибка возвращается, дело почти всегда в стороннем источнике, который предлагает пакеты для другой версии дистрибутива.
E: Release file for http://deb.debian.org/debian/dists/trixie/InRelease is not valid yet (invalid for another 5h 3min 2s).: часы сервера отстают. Проверьте через timedatectl status, сообщается ли System clock synchronized: yes, поправьте время и повторите apt update. Репозиторий здесь ни при чём.
W: GPG error: ... The following signatures couldn't be verified because the public key is not available: NO_PUBKEY ..., а следом E: The repository '...' is not signed.: ключ подписи стороннего источника отсутствует или был заменён. Сегодня ключ кладут в /etc/apt/keyrings/ и ссылаются на него в записи источника через signed-by либо через поле Signed-By:. apt-key объявлен устаревшим, и пользоваться им больше не следует.
E: Repository '... InRelease' changed its 'Suite' value from 'stable' to 'oldstable': это штатная ситуация, когда выходит новая версия Debian, а ваши источники указывают на stable вместо кодового имени. Подтвердите один раз через apt update --allow-releaseinfo-change, а затем переведите источники на кодовое имя. Иначе сервер, который следует за stable, однажды сменит версию дистрибутива без вашего ведома.
E: The repository 'http://... Release' does not have a Release file.: источник ничего не предлагает для вашей версии, обычно потому, что сторонний репозиторий ещё не поддерживает кодовое имя или дистрибутив достиг конца срока поддержки. Отключите проблемную строку и проверьте источник.
No space left on device посреди распаковки: заполнен /boot или /var. Приведите систему в порядок командой dpkg --configure -a, освободите место и повторите. Перед каждым обновлением ядра стоит заглянуть в df -h /boot.
debconf: unable to initialize frontend: Dialog: это только уведомление, а не сбой. Оно появляется без полноценного терминала, например внутри скрипта. С DEBIAN_FRONTEND=noninteractive оно исчезает.
Четыре системы в сравнении
| Тема | Debian 13 | Debian 12 | Ubuntu 24.04 | Ubuntu 22.04 |
|---|---|---|---|---|
| Файл источников | sources.list.d/debian.sources | sources.list | sources.list.d/ubuntu.sources | sources.list |
| needrestart | доустановить | доустановить | предустановлен | предустановлен |
| Признак перезагрузки | ненадёжный, используйте needrestart | ненадёжный, используйте needrestart | /var/run/reboot-required | /var/run/reboot-required |
| Поэтапная выкатка | нет | нет | да | да |
| Смена версии | переключить источники, затем в два шага | do-release-upgrade | ||
Итоговая проверка
То, что команда вернулась без ошибок, ещё не значит, что с системой всё в порядке. А вот эти шесть проверок действительно о чём-то говорят:
apt list --upgradableне выводит ничего, кромеListing....apt-mark showholdсодержит только то, что вы заблокировали осознанно.dpkg --auditмолчит.needrestart -bсообщаетNEEDRESTART-KSTA: 1и не оставляет служб, ожидающих перезапуска.systemctl --failedничего не перечисляет.find /etc -name '*.dpkg-dist'больше ничего не находит, потому что вы разобрали каждое расхождение.
Если четвёртый пункт требует перезагрузки, запланируйте её и выполните. Сервер, который месяцами ждёт отложенной перезагрузки, копит ровно те уязвимости, ради закрытия которых вы и обновлялись. После этого в последний раз проверьте uname -r и systemctl --failed. Перезагрузка — это тот момент, когда становится видно, поднимается ли всё обратно.
Частые вопросы
Чем apt upgrade отличается от apt full-upgrade?
Означает ли dist-upgrade переход на следующую версию дистрибутива?
Почему apt пишет «The following packages have been kept back»?
apt спрашивает, заменять ли файл конфигурации. Что отвечать?
Как понять, что после обновления нужна перезагрузка?
Зачем нужен needrestart, если я всё равно перезагружаю сервер?
Как обновляться без присмотра, чтобы запуск не завис на вопросе?
Можно ли обновлением закрыть себе доступ к серверу?
2026 KernelHost GmbH. Все права защищены. Эта инструкция охраняется авторским правом. Публикация на других сайтах, в том числе частично или в изменённом виде, без нашего письменного согласия не разрешается. Цитирование с указанием источника и активной ссылкой мы приветствуем.

