Debian 13: APT-оновлення пішло не так — відкотити один пакет без каскаду доміно

Було корисно?

Ви оновили сервер на Debian 13, один пакет пішов боком, і система почала поводитися так, ніби грає в трагедію: сервіси тріпаються, дивні помилки символів, а якщо невпала — можливо навіть не завантажиться. Вам не потрібен повний відкат. Вам потрібно повернути один пакет у попередній стан. Ви також не хочете, щоб APT «допоміг», понизивши півстека, бо ви вже бачили цей фільм і фінал завжди означає понаднормову роботу.

Ось підхід рівня продакшен: точно визначити, що змінилося, вибрати правильну версію, понизити її з контрольованим впливом на залежності, а потім зафіксувати/утримати, щоб вона залишалася на місці до готовності. По дорозі поговоримо про снапшоти, ребра залежностей і чому «просто apt install старий .deb» — це шлях стати попереджувальною історією.

Основні правила: що насправді означає «відкотити один пакет» в Debian

Debian не має вбудованої кнопки «відкат пакета», бо APT — це не машина часу; це розв’язувач залежностей. Відкотити один пакет можливо, але ви ведете переговори з відносинами:

  • Залежності: пакет, який ви хочете, міг вимагати новішу бібліотеку, ніж старіша версія, або навпаки.
  • ABI- сумісність: бібліотеки і частини, що взаємодіють з ядром, дають гарантії сумісності… поки не перестають, або ваш додаток не користується крайнім випадком.
  • Стан репозиторію: версія, яку ви хочете, має бути доступна у налаштованому джерелі або в локальному кеші.
  • Політика: APT обирає «найкращого» кандидата за pins, origin, priority і suite. Якщо політику не задати — отримаєте інтуїцію замість передбачуваности.

Мета не в «примусовій інсталяції старого .deb». Мета: знизити одну пакетну версію до відомо робочої, запобігаючи неконтрольованій каскаді понижень або видалень.

Друга мета: змушувати систему пояснювати себе. Якщо ви не можете передбачити, що зробить APT, ви не відкатуєте — ви граєте в азарт.

Жарт #1: APT — як надто впевнений інтерн: швидкий, корисний і цілком здатний переставити ваш будинок, щоб знайти степлер.

Швидкий план діагностики

Коли під тиском, не починайте з «пробуй випадкові пониження». Почніть з мінімуму перевірок, що розкривають форму залежностей і пакування інциденту.

Перш за все: ідентифікуйте, що змінилося і що зараз ламається

  • Яка версія пакета встановлена зараз?
  • Яка версія була встановлена раніше?
  • Який сервіс чи бінар ламається і чому (символи, конфіг, дозволи, ABI)?
  • Чи dpkg у напівсконфігурованому стані?

По-друге: визначте, чи можливий відкат без ланцюгової реакції

  • Чи залежить цільовий пакет від бібліотек, які тепер новіші, ніж очікувала стара версія?
  • Чи змусить його пониження понизити бібліотеки, які потрібні іншим пакетам?
  • Чи стара версія ще доступна в налаштованих репозиторіях або в кеші?

По-третє: реалізуйте контрольований відкат

  • Смоделюйте з APT і проінспектуйте пропоновані зміни.
  • Понизіть з явним вибором версії.
  • Піньте/утримуйте, щоб запобігти повторному оновленню.
  • Проведіть мінімальну перевірку: статус сервісу, логи та простий запит на працездатність.

По-четверте: запобігайте повторенню

  • Знімайте снапшоти перед оновленнями (файлова система або VM-снапшот).
  • Починайте оновлення поетапно (canary-host спочатку).
  • Відслідковуйте зміну версій у change management, а не в пам’яті когось.

Факти й контекст, що роблять поведінку APT менш загадковою

Це не запитання для вікторини. Це ментальна модель, що потрібна, коли APT починає пропонувати «видалити 37 пакетів» і називати це фічею.

  1. APT — це розв’язувач, dpkg — інсталятор. APT вирішує, що має статися; dpkg виконує, відслідковує стан і може залишитися напівзавершеним, якщо щось перервалося.
  2. «Depends» суворий, «Recommends» (переважно) опціональний. Debian історично трактував Recommends як опціональні, потім APT за замовчуванням почав їх встановлювати, що дивує тих, хто вчив Debian раніше.
  3. Версіоновані залежності поширені в критичних стек-продакшенах. Бібліотеки часто вимагають «>= x.y» і іноді «<< x.z» (рідко, але гостро). Ці обмеження диктують, наскільки далеко можна відкотитися.
  4. Pin-priority контролює вибір кандидата. Це не магія: pins створюють частковий порядок; APT вибирає кандидат версії з найвищим пріоритетом, що задовольняє залежності.
  5. Debian «stable» консервативний; «testing» рухливий. Якщо ваш Debian 13 тягне змішані suite або сторонні репозиторії, ви фактично керуєте кастомною дистрибуцією.
  6. Downgrades підтримуються, але не без тертя. APT їх виконає, але багато мейнтейнерів переважно тестують forward upgrades. Ви плаваєте вверх по течії.
  7. Скрипти підтримки пакета можуть змінювати стан поза файлами. postinst-скрипти можуть вмикати сервіси, створювати користувачів, мігрувати дані або переписувати конфіги. Відкат пакета не завжди відкочує ці побічні ефекти.
  8. «apt-get» vs «apt» — це не лише відчуття. Новіший apt дружніший до людей; apt-get стабільніший для скриптів. В інциденті надавайте перевагу передбачуваності.
  9. Debian має multiarch вже роки. Один і той самий пакет може мати кілька архітектур (наприклад, :amd64 та :i386), і це ускладнює «відкат одного пакета».

12+ практичних завдань: команди, виводи й рішення

Кожне завдання включає: команду для запуску, приклад виводу, що це означає і яке рішення ви приймаєте. Не всі з них будуть потрібні, але ви маєте знати, яке питання кожне відповідає.

Task 1: Confirm dpkg isn’t half-configured

cr0x@server:~$ sudo dpkg --audit
The following packages are only half configured, probably due to problems configuring them the first time.
 libssl3:amd64

Що це означає: Система не в чистому стані пакетів. Відкат під час того, як dpkg в процесі — це шлях отримати «працює в моєму терміналі», а після перезавантаження пошкодувати.

Рішення: Спочатку виправте стан dpkg: запустіть sudo dpkg --configure -a і вирішіть помилки перед спробою пониження.

Task 2: Get the installed version and the candidate version

cr0x@server:~$ apt-cache policy libssl3
libssl3:
  Installed: 3.3.1-1
  Candidate: 3.3.2-1
  Version table:
     3.3.2-1 500
        500 http://deb.debian.org/debian trixie/main amd64 Packages
 *** 3.3.1-1 100
        100 /var/lib/dpkg/status

Що це означає: Встановлена версія відрізняється від кандидата. Ви можете понизити/оновити залежно від доступності. Version table показує походження версій і їхні пріоритети pin.

Рішення: Якщо потрібної версії немає в таблиці, доведеться додати репозиторій, який її містить, або знайти її в локальному кеші.

Task 3: Find what upgraded recently (APT history)

cr0x@server:~$ sudo zgrep -h "Start-Date\|Upgrade:" /var/log/apt/history.log*
Start-Date: 2025-12-29  02:13:41
Upgrade: nginx:amd64 (1.26.1-2, 1.26.2-1), nginx-common:amd64 (1.26.1-2, 1.26.2-1)
End-Date: 2025-12-29  02:14:12

Що це означає: Це каже, що фактично змінилося, а не те, що ви думаєте.

Рішення: Якщо проблемний пакет є в цьому списку, відкат — валідна гіпотеза. Якщо ні, ви можете гнатися за неправильною підказкою (наприклад, за оновленням бібліотеки).

Task 4: Check dpkg logs for maintainer script failures

cr0x@server:~$ sudo grep -E "install |upgrade |configure " /var/log/dpkg.log | tail -n 8
2025-12-29 02:13:45 upgrade nginx:amd64 1.26.1-2 1.26.2-1
2025-12-29 02:13:46 status half-configured nginx:amd64 1.26.2-1
2025-12-29 02:13:47 status installed nginx:amd64 1.26.2-1

Що це означає: Якщо ви бачите «half-configured», яке ніколи не вирішилось, ймовірно проблема в postinst (синтаксис конфігу, дозволи, перезавантаження systemd).

Рішення: Якщо скрипт підтримки зламався, відкат може допомогти, але виправлення конфігурації може бути швидшим і безпечнішим, ніж пониження.

Task 5: Inspect why a package is installed and who depends on it

cr0x@server:~$ apt-cache rdepends --installed nginx | head -n 12
nginx
Reverse Depends:
  nginx-extras
  nginx-full
  myapp-web

Що це означає: Відкат nginx вплине на все, що від нього залежить.

Рішення: Якщо критичний внутрішній пакет вимагає мінімальної версії nginx, відкат nginx може змусити відкотити й той пакет. Вирішіть, чи це прийнятно.

Task 6: Show dependency constraints (the ones that bite)

cr0x@server:~$ apt-cache show nginx | sed -n '1,80p'
Package: nginx
Version: 1.26.2-1
Depends: nginx-common (= 1.26.2-1), libc6 (>= 2.38), libpcre2-8-0 (>= 10.34)

Що це означає: Залежності, зафіксовані по рівності ((= 1.26.2-1)) означають, що ви не зможете відкотити nginx самостійно; потрібно відкотити пов’язаний пакет теж.

Рішення: Плануйте відкат на рівні «групи вихідних пакетів», коли бачите жорсткі рівняння залежностей.

Task 7: Check what versions are available for downgrade

cr0x@server:~$ apt list -a nginx 2>/dev/null | sed -n '1,6p'
nginx/trixie 1.26.2-1 amd64
nginx/trixie 1.26.1-2 amd64

Що це означає: Репозиторій пропонує обидві версії. Добре: ви можете попросити APT конкретну версію без полювання на .deb-файли.

Рішення: Якщо потрібна версія відсутня — зупиніться і спершу виріште проблему доступності (suite репо, снапшот або кеш).

Task 8: Dry-run the downgrade and inspect the blast radius

cr0x@server:~$ sudo apt-get -s install nginx=1.26.1-2 nginx-common=1.26.1-2
Reading package lists... Done
Building dependency tree... Done
The following packages will be DOWNGRADED:
  nginx nginx-common
0 upgraded, 0 newly installed, 2 downgraded, 0 to remove and 0 not upgraded.
Inst nginx [1.26.2-1] (1.26.1-2 Debian:13.0/trixie [amd64])
Inst nginx-common [1.26.2-1] (1.26.1-2 Debian:13.0/trixie [amd64])

Що це означає: Ідеальний результат: лише цільові пакети понизяться. Жодних видалень, жодних несподіваних понижень бібліотек.

Рішення: Продовжуйте, якщо симуляція вузька. Якщо APT хоче видаляти пакети або понижувати базові бібліотеки — не продовжуйте без плану (pinning, альтернативна версія або відкат снапшота).

Task 9: Execute the downgrade with explicit versions

cr0x@server:~$ sudo apt-get install nginx=1.26.1-2 nginx-common=1.26.1-2
Reading package lists... Done
Building dependency tree... Done
The following packages will be DOWNGRADED:
  nginx nginx-common
Need to get 0 B/1,233 kB of archives.
After this operation, 0 B of additional disk space will be used.
Do you want to continue? [Y/n] y
dpkg: warning: downgrading nginx:amd64 from 1.26.2-1 to 1.26.1-2

Що це означає: Dpkg понижує; це підтримувана поведінка.

Рішення: Слідкуйте за помилками скриптів підтримки. Якщо вони з’являться — негайно зберіть логи і вирішіть, чи виправити конфіг, знову запустити configure або відкотитись зі снапшота.

Task 10: Verify the service and surface errors quickly

cr0x@server:~$ systemctl status nginx --no-pager -l
● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; preset: enabled)
     Active: active (running) since Mon 2025-12-29 02:21:06 UTC; 12s ago
       Docs: man:nginx(8)

Що це означає: Сервіс запущено. Не зупиняйтеся на цьому — статус не означає коректність, це лише пульс.

Рішення: Якщо він не активний, перегляньте журнали далі.

Task 11: Read the journal for the package’s failure mode

cr0x@server:~$ sudo journalctl -u nginx -b --no-pager -n 30
Dec 29 02:20:58 server nginx[1422]: nginx: [emerg] unknown directive "http2_push_preload" in /etc/nginx/conf.d/site.conf:12
Dec 29 02:20:58 server systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE

Що це означає: Це не проблема бінарника/ABI. Це несумісність конфігу. Відкат може «виправити» це, але справжнє рішення — узгодити конфіг з підтримуваним синтаксисом.

Рішення: Вирішіть, чи відкатувати конфіг або адаптувати його під нову версію. Пониження веб-сервера через застарілий конфіг зазвичай — поганий вибір.

Task 12: Verify shared library / symbol errors (classic post-upgrade pain)

cr0x@server:~$ /usr/bin/myapp-web
/usr/bin/myapp-web: symbol lookup error: /lib/x86_64-linux-gnu/libssl.so.3: undefined symbol: EVP_MD_get_type

Що це означає: ABI mismatch. Ваш бінар очікує символ, якого немає в поточній версії бібліотеки (або навпаки).

Рішення: Визначте, який пакет забезпечує бібліотеку, і підберіть сумісну пару версій (або перебудуйте додаток). Відкат лише самого додатка може не допомогти, якщо бібліотека змінилася.

Task 13: Map a file to its owning package (when you only know the broken .so)

cr0x@server:~$ dpkg -S /lib/x86_64-linux-gnu/libssl.so.3
libssl3:amd64: /lib/x86_64-linux-gnu/libssl.so.3

Що це означає: Зламаний символ знаходиться в libssl3. Це ціль відкату або додаток потрібно перебудувати під новий ABI.

Рішення: Перевірте доступні версії libssl3 і хто від неї залежить, перш ніж торкатися критичної бібліотеки криптографії.

Task 14: Inspect who depends on a core library before touching it

cr0x@server:~$ apt-cache rdepends --installed libssl3 | head -n 20
libssl3
Reverse Depends:
  openssh-client
  curl
  nginx
  myapp-web

Що це означає: Пониження libssl3 може вплинути на кілька критичних пакетів. Тут «відкат одного пакета» стає «зміна фундаменту».

Рішення: Якщо список зворотних залежностей включає критичні інструменти безпеки (ssh, curl), віддавайте перевагу перебудові додатка або ізоляції через контейнер, а не пониженню системної бібліотеки.

Task 15: Find cached .debs already on the box (when repos moved on)

cr0x@server:~$ ls -1 /var/cache/apt/archives | grep -E '^nginx_'
nginx_1.26.1-2_amd64.deb
nginx_1.26.2-1_amd64.deb

Що це означає: Можливо, у вас вже є потрібний .deb без зміни репозиторіїв. Корисно для швидкого відкату під час інциденту.

Рішення: Якщо встановлюєте з кешу, все одно віддавайте перевагу APT з явною версією, щоб зберегти керування залежностями.

Task 16: See what APT would remove if you attempt a downgrade (red flag)

cr0x@server:~$ sudo apt-get -s install libssl3=3.3.0-2
Reading package lists... Done
Building dependency tree... Done
The following packages have unmet dependencies:
 openssh-client : Depends: libssl3 (>= 3.3.1-1) but 3.3.0-2 is to be installed
E: Unable to correct problems, you have held broken packages.

Що це означає: Пониження несумісне з іншими встановленими пакетами. APT відмовляється, і це подарунок.

Рішення: Не форсуйте dpkg. Або відкотіть залежні пакети також (якщо прийнятно), або оберіть іншу стратегію (перебудова додатка, ізоляція в контейнері або відкат снапшота).

Вибір цілі відкату: версія, джерело та обсяг

Відкат «пакету, який зламався» часто помилковий, бо видима поломка — лише перше доміно. Справжня причина зазвичай одна з таких:

  • Зміна ABI бібліотеки (openssl, libc, zlib, libstdc++): отримаєте помилки symbol lookup або аварії.
  • Зміна схеми конфігу (nginx, systemd units, конфіг баз даних): сервіс не стартує, логи скаржаться на невідомі директиви або неправильні значення.
  • Зміна поведінки інструментів (python packaging, node tooling, openssh defaults): ваші скрипти тихо ламаються або поводяться інакше.
  • Невідповідність інтерфейсу kernel/userspace (драйвери, eBPF-утиліти): особливо з out-of-tree модулями або вендорними агентами.

Вирішіть: відкотити додаток, бібліотеку чи обидва?

Мій нахил: відкотіть додаток перед тим, як чіпати системне підґрунтя. Пониження пакетів додатків зазвичай локалізоване. Пониження бібліотек криптографії та libc — це шлях розширити інцидент до «чому ми не можемо ssh?».

Але іноді додаток в порядку, а регресія в бібліотеці. Тоді є три практичні опції:

  1. Оновити вперед (переважно коли є виправлена версія). Якщо баг у 1.2.3, а 1.2.4 це виправляє — відкат відволікає.
  2. Перебудувати додаток проти нового ABI бібліотеки, якщо ви контролюєте збірку. Це уникає системних понижень.
  3. Понизити бібліотеку тільки якщо (a) репо пропонує сумісний набір і (b) зворотні залежності можуть це витримати.

Вирішіть: який репозиторій «володіє» потрібною версією

У світі Debian доступні версії залежать від налаштованих джерел і їх пріоритетів. Змішувати suite (stable/testing/unstable) можливо, але це як змішувати різні сорти пального з байдужею усмішкою.

Використовуйте apt-cache policy і apt list -a, щоб побачити, що реально доступне. Якщо версія недоступна, ви не зможете чисто понизити через APT, не змінивши джерела або не використавши кеш.

Безпечний пониження: мінімізація радіусу ураження

Ось робочий процес, що тримає вас подалі від пекла залежностей:

  1. Смоделюйте пониження з apt-get -s.
  2. Огляньте список дій: пониження, видалення, нові інсталяції.
  3. Понизіть з явними версіями для набору пакетів (зазвичай включає -common або -data пакети).
  4. Негайно зафіксуйте/утримайте пакети, щоб APT не «виправив» їх при наступному оновленні.
  5. Перевірте поведінку в рантаймі: сервіс, логи і реальний запит/запитання.

Симулюйте як серйозно

Симуляція не опціональна. У продакшені ви не «пробуєте» пакетні операції. Ви їх передбачаєте.

Якщо APT хоче видалити пакети, уважно прочитайте список. Видалення може бути раціональним (конфлікти), але це також шлях втратити агента моніторингу й потім провести дві години «відлагодження проблеми з продуктивністю» без графіків.

Знайте, коли зупинитися і використати снапшот

Якщо відкат вимагає пониження базових компонентів, таких як libc6, systemd, openssl або ядро, ви вже не робите «відкат одного пакета». Це частковий відкат дистрибуції. Тут снапшоти файлової системи/VM блищать: вони повертають узгоджений стан системи.

Жарт #2: Найшвидший відкат — це той, для якого ви зробили снапшот учора. Другий найшвидший — той, який ви можете пояснити майбутньому собі без плачу.

Pinning і hold: не дайте APT «виправити» вашу правку

Пониження — це перший крок. Утримання пониженим — другий. Саме на другому кроці люди тихо програють, а потім дивуються під час наступного unattended upgrade вікна.

Використовуйте hold для негайного стримування

Hold грубий, швидкий і оборотний. Він забороняє оновлення цього пакета.

cr0x@server:~$ sudo apt-mark hold nginx nginx-common
nginx set on hold.
nginx-common set on hold.

Значення: Ці пакети не будуть оновлені, доки ви їх не знімете з hold.

Рішення: Використовуйте hold для стримування інциденту. Потім реалізуйте pinning, якщо потрібна довгострокова політика.

Використовуйте APT pinning, коли потрібна політика, а не пластир

Pinning кращий, коли ви маєте змішані репозиторії або хочете дозволяти загальні оновлення, але змусити конкретний пакет залишатися в обраній версії.

Створіть файл preferences, наприклад:

cr0x@server:~$ sudo tee /etc/apt/preferences.d/nginx-rollback.pref >/dev/null <<'EOF'
Package: nginx nginx-common
Pin: version 1.26.1-2
Pin-Priority: 1001
EOF

Значення: Пріоритет > 1000 каже APT, що можна вибрати цю версію навіть якщо це пониження.

Рішення: Використовуйте високопріоритетні pins економно. Ви перевизначаєте розв’язувач; робіть це з коментарем у change management і нагадуванням зняти pin пізніше.

Підтвердіть, що pin активний

cr0x@server:~$ apt-cache policy nginx | sed -n '1,12p'
nginx:
  Installed: 1.26.1-2
  Candidate: 1.26.1-2
  Version table:
     1.26.2-1 500
        500 http://deb.debian.org/debian trixie/main amd64 Packages
 *** 1.26.1-2 1001
        500 http://deb.debian.org/debian trixie/main amd64 Packages
        100 /var/lib/dpkg/status

Значення: Candidate дорівнює вашій pinned-версії. Це те, чого ви хочете.

Рішення: Якщо Candidate все ще новіша версія — ваш preferences-файл некоректний (невідповідність імені пакета, неправильний рядок версії або інший pin пріоритет перевищує його).

Три корпоративні міні-історії з практики

1) Інцидент через неправильне припущення: «То лише пакет додатка»

Команда керувала флотом Debian веб-нод з маленьким Go-сервісом перед TLS-термінальним проксі. Після рутинного оновлення health-checks почали падати на кількох хостах, потім на більше. Помилку, на якій всі зациклилися, бачили в логах додатка: TLS handshake failures. Тому швидко сформувалося припущення: «оновлення додатка зламало TLS».

Хтось відкотив пакет додатка на двох хостах. Ніякої різниці. Хтось інший відкотив проксі. Все ще зламано. Інцидент-командир почав тиснути на ширші відкати, один за одним, бо системи були доступні, а дашборд бізнесу — ні. Вікно оновлення перетворилось на рулетку.

Справжня коренева причина — невідповідність бібліотек, введена частковим оновленням: один хост перезавантажився посеред оновлення (виник інцидент з живленням у стійці), залишивши dpkg у неконсистентному стані. Деякі вузли мали нову криптобібліотеку і старий залежний пакет; інші — навпаки. Проксі був у порядку, додаток був у порядку. ABI-узгодження — ні.

Коли вони нарешті подивилися на dpkg --audit і логи dpkg, все стало очевидним. Виправлення не було «відкат додатка». Це було «добудувати оновлення чисто» на напівоновлених нодах, потім перезапустити сервіси. Урок: повідомлення про помилку вказувало на TLS, але режим відмови був у стані пакування.

Після цього додали правило: жодне автоматичне розгортання не триває, поки dpkg не чистий і остання транзакція APT не завершена. Це було нудно. Воно ж і запобігло повтору.

2) Оптимізація, що відкотилася назад: «Пришвидшимо оновлення, змішавши suite»

Група платформи хотіла нові фічі в одному компоненті — назвімо це реверс-проксі або драйвер БД — без очікування стабільного циклу. Вони зробили те, що багато розумних людей роблять під терміном: додали testing у sources.list і поставили низький pin. Намір — час від часу підбирати пакет. Реальність — графи залежностей не поважають намірів.

Це працювало місяцями. Потім рутинне оновлення підтягнуло новішу бібліотеку з testing, бо вона мала вищий pin-priority, ніж очікували для походження цього пакета (тонка невідповідність правил пріоритету). Проксі оновився, його модулі підтягнули суворішу бібліотечну залежність, і раптом кілька інших пакетів стали придатними для оновлення. APT виконав свою роботу: знайшов узгоджене рішення. Просто воно не було узгоджене з операційною безпекою.

Через два тижні вони спробували відкотити «один пакет, що ми оновили з testing». APT запропонував понизити бібліотеку, що означало пониження інших пакетів, які вже чекали новішої. Відкат перетворився на перетягування канату між suite. Кожне «виправлення» ускладнювало наступне оновлення.

Кінцевий ремонт був не героїчний. Видалили змішаний suite, повернулись до одного suite плюс контрольований backport-підхід, й використовували явні pins з датою завершення (так, буквально тикет-нагадування зняти pin). Покращення було помітним: оновлення знову стали передбачуваними. «Оптимізація» пожертвувала довгостроковою стабільністю заради короткострокової швидкості.

3) Скучно, але правильно: снапшоти і canary-host виручили

Система у фінансовому середовищі мала строгі SLA і контроль змін. Команда не була яскравою. Вони були обережними. Процес перед оновленням: снапшот, оновлення canary, smoke-тести, потім продовжують. Всім було нудно через паперування, поки воно не знадобилося.

Оновлення до Debian 13 ввело регрес у пакеті для генерації PDF. Сервіс стартував, але вихід був тонально неправильним для певних шрифтів. Якщо думаєте «та яка різниця», аудитори не погоджуються. Canary впіймав це, бо smoke-тест включав генерацію репрезентативного документу і його хешування. Не юніт-тест; реальний тест.

Замість метушні вони зафіксували версію того пакета, відкотили лише його на canary, підтвердили коректність виходу, а потім застосували той самий відкат на продакшен-ноди. Жодної каскади. Жодних випадкових видалень. Жодної драми.

Тим часом відкрили внутрішній тикет, щоб оцінити новішу версію пакета і вирішити, чи патчити конфіг або чекати фіксованого білду. Снапшот так і не довелося відновлювати, але знання, що він є, змінило всю постановку інциденту. Спокій перевищує хитрість.

Поширені помилки: симптом → коренева причина → виправлення

Цей розділ — місце, куди інциденти приходять, аби не повторюватися. Ставте його як чекліст пасток.

1) «APT хоче видалити півсистеми»

Симптоми: При спробі пониження APT пропонує видалити великі блоки (десктоп, python-стек, базу даних).

Коренева причина: Ви намагаєтеся встановити версію, що конфліктує з поточним набором залежностей; часто викликано змішаними suite, сторонніми репозиторіями або версіонально-залежними залежностями.

Виправлення: Зупиніться. Смоделюйте й інспектуйте. Запінуйте конкретну версію, яку хочете, і переконайтеся, що відповідний набір залежностей існує в тому ж репозиторному suite. Якщо залучені базові бібліотеки — віддавайте перевагу відкату снапшота або оновленню вперед.

2) «Unmet dependencies, held broken packages»

Симптоми: APT помилки з unmet dependencies; dpkg не може виправити проблеми.

Коренева причина: У вас часткове оновлення, зламані pins або конфлікт пріоритетів репозиторіїв. Іноді пакет знаходиться в hold і блокує потрібний шлях оновлення/пониження.

Виправлення: Перевірте hold за допомогою apt-mark showhold. Перевірте pin-priority з apt-cache policy. Відремонтуйте стан dpkg з dpkg --configure -a і apt-get -f install якщо доречно.

3) «Сервіс не стартує після оновлення; відкат «виправляє» його»

Симптоми: systemd unit не стартує; логи показують невідому директиву або неправильну опцію конфігу.

Коренева причина: Дрег конфігу. Ваш конфіг опирається на поведінку, яка була видалена або змінена в новій версії. Відкат відновлює старий парсер, а не коректність.

Виправлення: Оновіть конфіг відповідно до поточної версії, або керуйте версіями конфігу явно. Використовуйте journalctl, щоб знайти рядок і директиву. Відкат — лише тимчасовий засіб утримання.

4) «Symbol lookup error»

Симптоми: Виконавчі файли падають з undefined symbol errors у shared libraries.

Коренева причина: ABI mismatch між бінарником і версією бібліотеки; часте явище з локально зібраними бінарями або агентами від вендора.

Виправлення: Віддавайте перевагу перебудові/реінсталяції бінарника під нову бібліотеку. Якщо мусите понизити бібліотеку — перевірте зворотні залежності і уникайте пониження критичних інструментів безпеки.

5) «Пониження пройшло, але наступне оновлення знову ламає»

Симптоми: Після пониження все працює, а потім unattended-upgrades повертають погану версію.

Коренева причина: Немає hold або pin; APT все ще вважає новішу версію кандидатом.

Виправлення: Використовуйте apt-mark hold для негайного стримування, потім налаштуйте pin у /etc/apt/preferences.d/ для довшого контролю.

6) «dpkg locked, upgrades stuck»

Симптоми: APT повідомляє, що lock зайнято; операції не проходять.

Коренева причина: Інший apt/dpkg процес запущений (unattended-upgrades, apt-daily), або попередній процес впав, залишивши lock, але реальна проблема — напівзавершений стан dpkg.

Виправлення: Перевірте процеси, не видаляйте lock-файли напряму. Зупиніть таймери при потребі, потім відремонтуйте стан dpkg.

Контрольні списки / покроковий план

Checklist A: Contain the incident (5–15 minutes)

  1. Підтвердьте, що саме ламається (сервіс відключено? помилка бінарника? неправильний вихід?).
  2. Перевірте стан dpkg (dpkg --audit). Відремонтуйте, якщо потрібно.
  3. Визначте, що змінилося (apt history, кінець логу dpkg).
  4. Вирішіть, чи підходить відкат (питання: конфіг проти ABI проти реального регресу).
  5. Смоделюйте пониження, щоб виміряти радіус ураження (apt-get -s install pkg=ver).

Checklist B: Roll back one package without collateral damage

  1. Перелік доступних версій: apt list -a package.
  2. Перевірка залежностей: apt-cache show package.
  3. Перевірка зворотних залежностей: apt-cache rdepends --installed package.
  4. Симулюйте пониження з явними версіями для всіх тісно пов’язаних пакетів (часто -common, -data).
  5. Виконайте пониження з явними версіями.
  6. Негайно зафіксуйте або утримайте.
  7. Перевірте сервіс і логи.

Checklist C: Prevent the next domino collapse

  1. Видаліть змішані suite, якщо у вас немає явної політики для них.
  2. Використовуйте canary-оновлення і smoke-тести, що відображають реальні навантаження.
  3. Робіть снапшоти перед оновленнями (VM, LVM, btrfs, ZFS — що у вас є).
  4. Відслідковуйте pins і holds як тимчасові міри з власниками та датою завершення.

Питання і відповіді

1) Can I downgrade a package with dpkg directly?

Можете, але зазвичай не слід. Dpkg не розв’язує залежностей. Якщо ви встановите старіший .deb, який конфліктує з встановленими залежностями, ви створите зламаний стан системи, який APT потім муситиме розібрати. Віддавайте перевагу apt-get install pkg=version, щоб зберегти целостність розв’язування залежностей.

2) Why does APT want to downgrade a bunch of other packages?

Тому що запрошена вами версія змінює обмеження залежностей. Якщо стара версія вимагає старіших бібліотек або конфліктує з новішими, APT намагається знайти узгоджений набір. Розв’язувач робить свою роботу; ви поставили йому задачу складнішу, ніж планували. Це сигнал симулювати, інспектувати і, можливо, змінити стратегію.

3) What’s the difference between a hold and a pin?

Hold блокує зміну пакета (оновлення/пониження), поки ви явно не знімете hold. Pin впливає на вибір кандидата і може бути дуже точним або дуже небезпечним залежно від налаштувань. Holds добре підходять для швидкої ізоляції; pins — для політики.

4) How do I see if a package is held?

cr0x@server:~$ apt-mark showhold
nginx
nginx-common

Якщо пакет, який ви хочете пересунути, знаходиться в hold, цей hold може бути причиною повідомлення APT «held broken packages». Знімайте unhold усвідомлено, а не імпульсивно.

5) What if the old version isn’t in my repositories anymore?

Спочатку перевірте /var/cache/apt/archives. Якщо там немає — вам потрібен репозиторій, що надає версію (наприклад, контрольований внутрішній mirror або сервіс снапшотів). Уникайте випадкових .deb з інтернету; ланцюг довіри та замикання залежностей важливі.

6) Is it safe to roll back libraries like libssl or libc?

Іноді, але рідко це найкращий перший крок. Ці бібліотеки мають багато залежників і є критичними для безпеки. Якщо один додаток ламається через оновлення бібліотеки, краще перебудувати додаток або ізолювати його (контейнер, chroot), ніж понижувати системну криптобібліотеку або libc.

7) How do I know which package provides a failing shared object?

Використовуйте dpkg -S /path/to/file. Це зіставляє файл з пакетом-власником. Потім можна перевірити версії і вирішити, чи бібліотека — справжня ціль відкату.

8) What if the failure is due to a config change and not the binary?

Тоді відкат — тимчасова милиця. Виправте конфіг, щоб він був сумісний з новим пакетом. Використовуйте journalctl -u service для точної директиви/рядка. Також перевірте нові конфігурації за замовчуванням у /usr/share/doc або conffile-повідомлення в /etc, які могли бути пропущені під час оновлення.

9) Should I use apt or apt-get during incidents?

Я користуюся apt-get для інцидентної роботи, бо його інтерфейс стабільний і передбачуваний, особливо для симуляцій (-s) і скриптової відтворюваності. apt підходить, але дружелюбність не завжди рівна контролю.

10) How do I audit what APT changed last night?

Використовуйте /var/log/apt/history.log і /var/log/dpkg.log. Вони показують, що APT планував і що dpkg фактично зробив. Якщо ці два файли не збігаються — це підказка (переривання, помилки скриптів підтримки або ручні втручання).

Висновок: наступні кроки, які можна зробити сьогодні

Відкотити один пакет у Debian 13 без колапсу залежностей — це не чорна магія. Це політика, симуляція і стриманість. Ваш план дій:

  1. Передусім зробіть dpkg чистим.
  2. Доведіть, що змінили через логи, а не пам’ять.
  3. Смоделюйте пониження і відмовтесь від великих радіусів ураження.
  4. Понизуйте з явними версіями для тісно пов’язаних пакетів.
  5. Негайно зафіксуйте/утримайте, потім перевірте реальним навантаженням.
  6. Після ліквідації пожежі видаліть ad-hoc змішані репозиторії і впровадьте снапшоти + canary-оновлення.

Одна цитата, варта того, щоб приклеїти її на монітор: Hope is not a strategy. — Edsger W. Dijkstra

Якщо нічого більше не робитимете: почніть робити снапшоти перед оновленнями і завжди симулюйте пониження. Це саме по собі врятує вас від наступного моменту «APT запропонував видалити мій стек моніторингу», що є унікально сучасною формою самоствореної сліпоти.

← Попередня
Електронна пошта: приплив вхідного спаму — вижити під час атаки, не блокуючи реальних користувачів
Наступна →
Caps Lock і лють через паролі: найменша клавіша, що породжує найбільший хаос

Залишити коментар