О 02:13 «невинне» apt upgrade може перетворити спокійний сервер на місце злочину залежностей. Якась бібліотека стрибнула на нову велику версію, ядро обновилося, і раптом ваш стек зберігання «працює як задумано», а ваш пейджер працює понаднормово.
Закріплення версій пакетів — це зрілий крок, який робить Debian передбачуваним, коли потрібно змішувати джерела: stable + security + stable-updates, плюс backports, плюс іноді сторонні репо. Зроблено правильно — нудно. Зроблено неправильно — у вас bespoke FrankenDebian з додатковим простоєм.
Що таке закріплення (і чим воно не є)
apt у Debian не «оновлює все до найновішої знайденої версії» в спрощений спосіб. Він ранжує версії за набором правил і метаданих (origin, release, priorities), а потім намагається знайти узгоджене рішення. Закріплення дозволяє вам перевизначити стандартний рейтинг.
Проблема, яку вирішує закріплення
У продакшні вам потрібно дві властивості, які конфліктують між собою:
- Оперативність з безпекою: ви хочете швидко отримувати виправлення.
- Контроль змін: ви хочете уникати «сюрпризних» нових мажорних версій або нових ланцюгів залежностей.
Закріплення дає змогу сказати «брати оновлення безпеки, але не стрибати на ту нову версію від вендора» або «витягнути рівно один пакет із backports, а не всю його розширену родину».
Чим закріплення не є
- Не замінює читання пропонованого оновлення. Якщо ви сліпо виконуєте оновлення, закріплення — це просто вишуканіша пов’язка на очі.
- Не хак для резольвера залежностей. Якщо два репозиторії надають несумісні стеки, закріплення не примирить сторони; воно лише обирає якусь сторону.
- Не те саме, що “hold”, хоча вони можуть працювати разом. Hold фіксує пакет за ім’ям. Закріплення ж схиляє вибір версії на підставі origin/release/version.
Де живе закріплення
У Debian 13 ви використовуєте:
/etc/apt/preferences(legacy один файл)/etc/apt/preferences.d/*.pref(більш розумний спосіб: модульно, аудитується)
Я віддаю перевагу preferences.d з одним наміром на файл: «backports opt-in», «vendor repo обмежено», «no testing packages» тощо. Це читається як політика, а не як фольклор.
Цитата, яка тримає вас чесним: «Надія — не стратегія.» — парафраз поширеної ідеї в інженерії/операціях.
Жарт №1: Закріплення пакетів — як встановити бортики на боулінговій доріжці. Ви все ще можете викинути кульку в лузу, але за це треба постаратися.
Факти й контекст, які змінюють підхід до закріплення
Ось конкретні історичні й поведінкові факти, які важливі при проєктуванні політики apt. Вони не романтичні, але мають наслідки.
- APT pinning старший за контейнери. До ери «просто відправити власний імідж» закріплення було тим, як адміни поєднували виправлення безпеки з консервативними базовими системами.
- «FrankenDebian» — термін не з порожнього місця. Змішування stable/testing/unstable (або випадкових вендор-репо) без політики часто дає тихі ABI-несумісності і хаотичні зміни залежностей.
- У Debian існує
stable-updates, щоб зменшити тиск на point-релізи. Він призначений для термінових виправлень, які не повинні чекати наступного повного point-релізу. backportsзадумано як opt-in. Debian навмисно дає backports нижчий пріоритет за замовчуванням, щоб stable залишався стандартом.- Pin-priority має різкі грані за дизайном. Пріоритети вище 1000 можуть примусово виконувати даунгрейди; нижче 0 блокують встановлення. Ви можете влучно прострелити собі ногу з математичною точністю.
- Apt враховує не лише версії, а й origin. Поля релізу як
o=(Origin) іa=(Archive) часто важливіші за рядки версій. - Підписана метадані репо — корінь довіри, не пакетний файл. Якщо ви дозволяєте репо, ви довіряєте його ключу підпису та індексу; закріплення контролює вподобання, а не автентичність.
- Транзиції відбуваються. Великі переходи бібліотек (подумайте SSL, libc++, Python) дають хвилі через графи залежностей; закріплення може запобігти несподіваним переходам… але також може блокувати необхідні оновлення безпеки, якщо ви неуважні.
Двигун рішень apt: ментальна модель, яку можна тримати в голові
Коли apt обирає, що встановити, він фактично робить три речі:
- Збирає кандидатські версії з усіх налаштованих джерел (
/etc/apt/sources.list,/etc/apt/sources.list.d/*.list). - Присвоює Pin-Priority кожній версії, використовуючи стандартні налаштування + ваші preferences.
- Вибирає «найкращу» встановлювану версію (найвищий пріоритет; при паритеті — найвищу версію), а потім вирішує залежності.
Правила Pin-Priority, які треба пам’ятати
Це пороги, що змінюють поведінку. Вивчіть їх; це різниця між політикою і хаосом.
- > 1000: може примусово встановити навіть якщо це означає даунгрейд.
- 990–1000: віддає перевагу цій версії навіть над встановленими версіями (типово для «target release»).
- 500: нормальний пріоритет для нецільових релізів.
- 100: нижче за встановлену; зазвичай виграє встановлена версія.
- 0: фактично «не встановлювати» (якщо не запитано явно, і навіть тоді може бути заблоковано за точного збігу).
- < 0: ніколи не встановлювати.
Target release: тихий підступ
Якщо ви встановите APT::Default-Release на stable (або кодову назву Debian 13), ви повідомляєте apt, що «цей реліз — 990». Зазвичай це добре. Але це також означає, що будь-який інший реліз з 500 може бути обраний, якщо кандидат stable неможливо встановити (конфлікти залежностей) або якщо ви явно використаєте -t.
Закріплення — це не просто «встановити число». Це вибір найменшого числа, яке виконує завдання без примусових даунгрейдів або постійного розходження.
Швидкий план діагностики
Ось що я роблю, коли пропозиція оновлення виглядає неправильно або система вже дрейфує. Потрібно швидко отримати сигнал, а не вступати в філософські дебати з apt.
Перш за все: підтвердіть, ким apt вважає кандидата
- Виберіть один проблемний пакет (часто той, у якого стрибок мажорної версії).
- Запустіть
apt-cache policyі подивіться: встановлена версія, кандидат, і яке репо його постачає.
По-друге: спитайте «чому» за допомогою симульованого оновлення
apt -s dist-upgrade— ваш детектор брехні.- Шукайте видалення і «kept back» пакети. Це ранні сигнали тривоги.
По-третє: визначте репо, що тягне граф
apt-cache madisonпоказує версії по репо.apt-get -o Debug::pkgProblemResolver=yes -s dist-upgradeпояснює вибір залежностей.
По-четверте: перевірте, чи ваші правила pin справді спрацьовують
- Більшість помилок pin — не «поганий пріоритет», а «немає збігу». Неправильне Origin поле. Невірна назва релізу. Невірна мітка.
- Валідуйте через вивід
apt-cache policy: пріоритети мають відображати ваші preferences.
По-п’яте: вирішіть, чи виправляєте політику або робите одноразове порятункове рішення
- Якщо система вже змішана, можливо знадобиться контрольований даунгрейд/вирівнювання.
- Якщо це одноразова потреба в пакеті, зафіксуйте тільки цей пакет (або опустіть пріоритет відповідного репо) і рухайтесь далі.
Практичні завдання (команди + значення виводу + рішення)
Ось реальні дії, які я виконую на серверах Debian. Кожне завдання містить: команду, реалістичний уривок виводу, що це означає і яке рішення з цього випливає.
Завдання 1: Перелік налаштованих джерел APT (шукаємо несподівані репо)
cr0x@server:~$ grep -Rhs '^[^#]' /etc/apt/sources.list /etc/apt/sources.list.d/*.list
deb http://deb.debian.org/debian trixie main contrib non-free non-free-firmware
deb http://security.debian.org/debian-security trixie-security main contrib non-free non-free-firmware
deb http://deb.debian.org/debian trixie-updates main contrib non-free non-free-firmware
deb http://deb.debian.org/debian trixie-backports main contrib non-free non-free-firmware
deb [signed-by=/etc/apt/keyrings/vendor.gpg] https://packages.vendor.example/debian stable main
Що це означає: Ви змішуєте stable, security, updates, backports і vendor repo. Це нормально… якщо у вас є політика. Якщо ні — apt її придумає сам.
Рішення: Якщо є репо, якого ви не очікували, відключіть його перед будь-якими діями. Якщо є vendor repo — плануйте закріпити його низько.
Завдання 2: Перевірте Default-Release (щоб уникнути випадкового таргетування)
cr0x@server:~$ apt-config dump | grep -E 'APT::Default-Release|Acquire::'
APT::Default-Release "trixie";
Acquire::Retries "3";
Що це означає: Система віддає перевагу Debian 13 (показана кодова назва) як цільовому релізу.
Рішення: Тримайте його встановленим на кодову назву stable (або stable). Якщо воно порожнє, ви частіше будете дрейфувати при наявності кількох репо.
Завдання 3: Оновіть списки пакетів і слідкуйте за помилками репо
cr0x@server:~$ sudo apt update
Hit:1 http://deb.debian.org/debian trixie InRelease
Hit:2 http://security.debian.org/debian-security trixie-security InRelease
Hit:3 http://deb.debian.org/debian trixie-updates InRelease
Hit:4 http://deb.debian.org/debian trixie-backports InRelease
Get:5 https://packages.vendor.example/debian stable InRelease [3,215 B]
Reading package lists... Done
Building dependency tree... Done
All packages are up to date.
Що це означає: Метадані отримано коректно. Якщо ви бачите помилки підпису — спочатку виправте довіру; закріплення не врятує від зламаного репо.
Рішення: Якщо будь-яке репо працює нестабільно, розгляньте його ізоляцію або використання mirror. Нестабільні метадані призводять до неконсистентних кандидатів на різних хостах.
Завдання 4: Перегляньте кандидатські версії і пріоритети для пакета
cr0x@server:~$ apt-cache policy openssl
openssl:
Installed: 3.2.2-1
Candidate: 3.2.3-1~deb13u1
Version table:
3.2.3-1~deb13u1 990
990 http://security.debian.org/debian-security trixie-security/main amd64 Packages
*** 3.2.2-1 100
100 /var/lib/dpkg/status
3.2.2-1+vendor1 500
500 https://packages.vendor.example/debian stable/main amd64 Packages
Що це означає: Security repo має пріоритет 990 (ймовірно через Default-Release). Vendor repo присутній, але не перемагає.
Рішення: Це здорово. Якби vendor мав пріоритет вище за 990 — закріпіть його негайно вниз.
Завдання 5: Показати всі доступні версії по репо
cr0x@server:~$ apt-cache madison linux-image-amd64
linux-image-amd64 | 6.12.9-1 | http://deb.debian.org/debian trixie/main amd64 Packages
linux-image-amd64 | 6.12.12-1~deb13u1 | http://security.debian.org/debian-security trixie-security/main amd64 Packages
linux-image-amd64 | 6.13.5-1~bpo13+1 | http://deb.debian.org/debian trixie-backports/main amd64 Packages
Що це означає: Backports пропонує новіше ядро. Це привабливо для підтримки обладнання, але небезпечно, якщо ви цього не планували.
Рішення: Вирішіть, чи дозволяєте ядра з backports. Якщо ні — закріпіть backports низько або закріпіть лише пакет ядра, який хочете контролювати.
Завдання 6: Симулюйте оновлення і читайте видалення як кримінальний звіт
cr0x@server:~$ sudo apt -s dist-upgrade
Reading package lists... Done
Building dependency tree... Done
Calculating upgrade... Done
The following packages will be upgraded:
libc6 openssl systemd
The following packages will be REMOVED:
vendor-storage-agent
3 upgraded, 0 newly installed, 1 to remove and 0 not upgraded.
Inst libc6 [2.40-1] (2.40-2~deb13u1 Debian-Security:13/stable-security [amd64])
Remv vendor-storage-agent [2.1.0-4] [vendor-storage-agent:amd64 ]
Inst systemd [257-1] (257-2~deb13u1 Debian-Security:13/stable-security [amd64])
Inst openssl [3.2.2-1] (3.2.3-1~deb13u1 Debian-Security:13/stable-security [amd64])
Що це означає: Оновлення core libc призведе до видалення вендорського агента. Це не «оновлення», це запит на зміну.
Рішення: Стоп. Зафіксуйте або стек залежностей агента (або само репо вендора), або плануйте заміну агента. Не приймайте мовчазних видалень на важливих серверах.
Завдання 7: Увімкніть дебаг резольвера, щоб побачити «чому»
cr0x@server:~$ sudo apt-get -o Debug::pkgProblemResolver=yes -s dist-upgrade
Reading package lists... Done
Building dependency tree... Done
Starting pkgProblemResolver with broken count: 0
Investigating (0) vendor-storage-agent:amd64 < 2.1.0-4 @ii mK Ib >
Conflicts: libc6 (>= 2.40-2~deb13u1)
Removing vendor-storage-agent:amd64 rather than change libc6:amd64
Done
Що це означає: Агента вендора конфліктує з безпековою libc. Apt віддає перевагу зберегти libc актуальною та видалити агента.
Рішення: Варіанти: оновити вендорський агент до сумісної версії, тимчасово закріпити libc (ризиковано), або свідомо видалити/замінити агента.
Завдання 8: Перевірте, які pin наразі діють
cr0x@server:~$ ls -1 /etc/apt/preferences.d
00-default-release.pref
10-backports-optin.pref
20-vendor-low.pref
Що це означає: У вас структурована політика, а не один загадковий файл.
Рішення: Якщо у вас цього немає — створіть. Якщо є — відкрийте і підтвердіть, що вони відповідають реальності.
Завдання 9: Створіть розумний pin «backports — opt-in»
cr0x@server:~$ sudo tee /etc/apt/preferences.d/10-backports-optin.pref >/dev/null <<'EOF'
Package: *
Pin: release a=trixie-backports
Pin-Priority: 100
EOF
Що це означає: Пакети з backports не будуть обиратися автоматично над встановленими stable-версіями. Ви все ще можете встановити з backports явно.
Рішення: Використовуйте це на production-системах, якщо немає сильної причини інакше. «Ми любимо нове» — не причина; це риса характеру.
Завдання 10: Зафіксуйте вендорське репо низько, щоб воно не захопило систему
cr0x@server:~$ sudo tee /etc/apt/preferences.d/20-vendor-low.pref >/dev/null <<'EOF'
Package: *
Pin: origin "packages.vendor.example"
Pin-Priority: 50
EOF
Що це означає: Пакети вендора доступні, але apt не обиратиме їх, якщо ви явно не попросите або якщо stable не пропонує встановлюваний кандидат.
Рішення: Це стандартна захисна позиція для вендор-репо. Підніміть пріоритет лише для конкретних пакетів, які вам реально потрібні з вендора.
Завдання 11: Зафіксуйте одиночний пакет у backports (хірургічне прийняття)
cr0x@server:~$ sudo tee /etc/apt/preferences.d/30-zfs-from-backports.pref >/dev/null <<'EOF'
Package: zfs-dkms zfsutils-linux
Pin: release a=trixie-backports
Pin-Priority: 990
EOF
Що це означає: Лише ZFS-компоненти віддаються перевагою з backports. Все інше залишається stable-першим.
Рішення: Робіть так, коли потрібно новіше драйверне/файлове рішення, але не хочете системного дрейфу.
Завдання 12: Перевірте, що pin спрацював, через policy-вивід
cr0x@server:~$ apt-cache policy zfsutils-linux
zfsutils-linux:
Installed: 2.2.4-1
Candidate: 2.2.6-1~bpo13+1
Version table:
2.2.6-1~bpo13+1 990
990 http://deb.debian.org/debian trixie-backports/main amd64 Packages
*** 2.2.4-1 100
100 /var/lib/dpkg/status
2.2.4-1 990
990 http://deb.debian.org/debian trixie/main amd64 Packages
Що це означає: Для цього пакета backports має пріоритет 990 і стає кандидатом. Добре: саме те, чого ви хотіли.
Рішення: Продовжуйте встановлення, якщо перевірили сумісність ядра/модулів і маєте план відкату.
Завдання 13: Встановіть з backports явно (навіть без pin)
cr0x@server:~$ sudo apt -t trixie-backports install zfsutils-linux
Reading package lists... Done
Building dependency tree... Done
The following NEW packages will be installed:
libnvpair3linux libuutil3linux libzfs5linux libzpool5linux zfsutils-linux
The following packages will be upgraded:
zfs-dkms
Need to get 4,812 kB of archives.
After this operation, 18.2 MB of additional disk space will be used.
Do you want to continue? [Y/n]
Що це означає: Apt тягне узгоджений набір пакетів з backports для ZFS.
Рішення: На серверах з даними плануйте це в вікні. Перебудова модулів ядра та перезавантаження — це не «фонова задача», незважаючи на записи в календарі.
Завдання 14: Утримання пакета, коли потрібна жорстка заморозка
cr0x@server:~$ sudo apt-mark hold linux-image-amd64
linux-image-amd64 set on hold.
Що це означає: Apt не буде автоматично оновлювати цей пакет.
Рішення: Використовуйте holds економно і відстежуйте їх. Утримання — це заборгованість: воно накопичує відсотки у вигляді пропущених безпекових та баг-фіксів.
Завдання 15: Перевірте утримання, щоб не забути, що ви заморозили
cr0x@server:~$ apt-mark showhold
linux-image-amd64
Що це означає: У вас встановлено утримання на пакет ядра.
Рішення: Вирішіть, чи виправдане утримання. Якщо воно «тимчасове», поставте собі нагадування, яке важче проігнорувати, ніж ваше майбутнє я.
Завдання 16: Показати пакети з конкретного origin, що вже встановлені (перевірка дрейфу)
cr0x@server:~$ apt-cache policy | sed -n '1,120p'
Package files:
100 /var/lib/dpkg/status
release a=now
990 http://security.debian.org/debian-security trixie-security/main amd64 Packages
release o=Debian,a=trixie-security,n=trixie-security,l=Debian-Security,c=main,b=amd64
990 http://deb.debian.org/debian trixie/main amd64 Packages
release o=Debian,a=trixie,n=trixie,l=Debian,c=main,b=amd64
100 http://deb.debian.org/debian trixie-backports/main amd64 Packages
release o=Debian Backports,a=trixie-backports,n=trixie-backports,l=Debian Backports,c=main,b=amd64
50 https://packages.vendor.example/debian stable/main amd64 Packages
release o=Vendor,a=stable,n=stable,l=Vendor,c=main,b=amd64
Pinned packages:
Що це означає: Ваші pin-пріоритети видимі на рівні репозиторію: security і stable по 990, backports 100, vendor 50.
Рішення: Якщо ці числа не відповідають вашій політиці — виправте preferences перед будь-якими оновленнями.
Завдання 17: Підтвердіть збіг pin, використовуючи поля origin і release
cr0x@server:~$ apt-cache policy | grep -E 'release o=|release a='
release o=Debian,a=trixie-security,n=trixie-security,l=Debian-Security,c=main,b=amd64
release o=Debian,a=trixie,n=trixie,l=Debian,c=main,b=amd64
release o=Debian Backports,a=trixie-backports,n=trixie-backports,l=Debian Backports,c=main,b=amd64
release o=Vendor,a=stable,n=stable,l=Vendor,c=main,b=amd64
Що це означає: Саме ці рядки мають збігатися з вашими правилами pin. Вгадавши — ви отримуєте мовчазний провал pins.
Рішення: Використовуйте ці точні значення (особливо origin і a=) у ваших preferences.
Завдання 18: Симулювати встановлення вендорського пакета, не даючи йому розповзтися
cr0x@server:~$ sudo apt -s install vendor-storage-agent
Reading package lists... Done
Building dependency tree... Done
The following packages will be installed:
vendor-storage-agent
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Inst vendor-storage-agent (2.1.3-1 Vendor:stable [amd64])
Що це означає: За умови, що вендорське репо зафіксовано низько, apt встановлює тільки те, що ви запросили; він не замінює оппортуністично базові бібліотеки.
Рішення: Це бажаний результат. Якщо симуляція показує ланцюг оновлень від вендора — опустіть пріоритет вендора ще нижче або закріпіть лише конкретний вендорський пакет.
Три корпоративні міні-історії з польових умов
1) Інцидент через хибне припущення: «Оновлення безпеки не змінюють залежностей»
Середня компанія керувала парком Debian-серверів, що обробляли внутрішні артефакти збірки та образи контейнерів. Стороння система зберігання була прозаїчною: RAID, ext4 і вендорський агент моніторингу, який наполягав, що він «легкий». Команда мала щотижневе вікно патчів і правило: швидко застосовувати оновлення безпеки, бо аудитори люблять календарну відповідність.
Одного тижня оновлення безпеки потягнуло нову мінорну ревізію core-бібліотеки. Це не був мажорний стрибок, тому воно пройшло людську перевірку. Хибне припущення було тонким: «репо безпеки не зламає userland». Debian консервативний, але «консервативний» ≠ «ніколи не змінюються залежності», особливо коли виправлення безпеки вимагають перевірки проти оновлених бібілотек.
Вендорський агент мав жорстку залежність і не був перебудований для оновленої бібліотеки. Apt зробив те, що має робити: запропонував видалити агента. Хтось побачив «1 to remove» і подумав, що це старий пакет ядра. Насправді це був елемент, який постачав метрики в NOC.
Після апгрейду нічого явно не «впало». Ось у чому була проблема. NOC мав сліпу зону: місця на диску заповнилися, тиск inode зріс, і кілька build-ноду почали відмовляти при пушах. Інцидент виявили розробники, а не моніторинг. Це культурна помилка з технічною причиною.
Виправлення не було героїчним. Команда зафіксувала вендорське репо низько, потім закріпила вендорський агент так, щоб він залишався встановлюваним без тягнення вендорських бібліотек над Debian. Вони додали правило перевірки: симульоване оновлення має показувати нуль видалень, якщо того не схвалено окремо. Вони припинили ставитись до оновлень безпеки як до нейтральних щодо залежностей.
2) Оптимізація, яка обернулась проти: «Зафіксуємо все на backports заради швидкості»
Команда платформи хотіла підвищити продуктивність. Їхній рівень TLS був завантажений CPU, і хтось помітив новішу крипто-бібліотеку в backports з кращою продуктивністю на сучасних CPU. Ідея виглядала розумною: взяти нову бібліотеку, отримати швидші рукопотискання і насолоджуватись меншим часом затримки.
Вони створили широкий pin: backports високого пріоритету для всіх пакетів. Здавалося чистим і послідовним: одне репо, один напрям, менше сюрпризів. Але це тихо перетворило stable на «переважно ігнорований», що є повною протилежністю мети stable у production.
Перший тиждень пройшов гладко. Потім почалася ланцюгова реакція: новіша бібліотека подтягнула новіший тулчейн, який підтягнув новіший рантайм, який підтягнув новішу системну службу. Система все ще могла завантажуватись, але з’явилися регресії в місцях, які ніхто не пов’язував із «TLS-перформансом». Особливо неприємний був випадок зміни порядку рестарту сервісів, що взаємодіяв з таймінгом монтування сховища. Невеликий відсоток нод піднімався без критичних монтувань, і програми писали в корінь файлової системи. Це той тип помилки, який створює археологічні шари в /.
Відкат був гіршим за зміну. Даунгрейд широко оновленої системи можливий, але повільний і ризикований — краще не допустити дрейфу. Вони в кінці кінців відновлювали ноди, а не «ремонтували» їх на місці, що чесно, але дорого.
Урок: закріплення — не ручка продуктивності. Це інструмент політики. Якщо вам потрібна нова крипто-бібліотека — закріпіть саме її (і лише необхідний набір), або використайте цільовий -t backports з ретельним рев’ю. Backports можуть бути чудовими; «все з backports» — фактично нова трек-дистрибуція.
3) Нудна але правильна практика, яка врятувала день: «Один файл pin на намір і аудит дрейфу»
Команда фінансових послуг керувала Debian на системах зі значним навантаженням на зберігання: файлові сервіси, об’єктні шлюзи та координатори бекапів. Їхнє середовище було протилежністю модності: довго живучі хости, обережні оновлення і документована культура «що змінилося». У них також було одне негарне правило: жоден хост не отримує репо без pin-файлу в /etc/apt/preferences.d.
Вони зафіксували backports на 100 глобально, потім мали короткий allowlist пакетів на 990 коли потрібно було забезпечити обладнання або виправлення файлової системи. Вендор-репо були зафіксовані на 50 по origin, з явними винятками для двох пакетів. Вони також встановили Default-Release на кодову назву stable і включили це в базову конфігурацію.
Момент порятунку стався під час термінової відповіді на вразливість. Нове оновлення безпеки з’явилось одночасно з тим, як вендор опублікував набір пакетів, що по номеру виглядав «новішим». На менш дисциплінованих системах apt міг би дрейфувати до вендорських пакетів. На цих хостах вендор репо не було дозволено перемогти за замовчуванням. Оновлення залишилось в екосистемі Debian, а пакети вендора залишалися доступними лише за явного запиту.
Вони все одно виконували роботу: симулювали оновлення, підтвердили відсутність видалень і розгорнули через канарку. Це майже було нудно. Ось у чому сенс. Їхній найцінніший інструмент відповіді на інциденти не був крутою платформою; це була передбачувана політика селекції пакетів і звичка аудиту.
Типові помилки: симптом → корінь → виправлення
1) Симптом: apt прагне видалити половину системи під час оновлення
Корінь: У вас є конфліктне джерело пакетів (часто vendor) з несумісними залежностями, або ви випадково тягнете з backports/testing.
Виправлення: Визначте пакет, який тригерить видалення через apt -s dist-upgrade, потім перевірте його через apt-cache policy. Зафіксуйте проблемне репо нижче (наприклад 50) і повторіть симуляцію.
2) Симптом: пакети з backports встановлюються, навіть коли ви не просили
Корінь: Backports зафіксовано занадто високо, або APT::Default-Release не встановлено і apt обирає новішу версію при паритеті пріоритетів.
Виправлення: Встановіть backports як Pin-Priority: 100 для Package: *, і задайте APT::Default-Release на кодову назву stable.
3) Симптом: ваш pin-файл «нічого не робить»
Корінь: Селектор Pin: не збігається з фактичними метаданими репо. Типові помилки: неправильний origin; плутанина між a= (Archive) і n= (Codename).
Виправлення: Скопіюйте точні значення з рядків релізу apt-cache policy і використайте їх у вашому правилі pin.
4) Симптом: apt відмовляється даунгрейдити, коли треба відкотитись
Корінь: Ваші pin не дозволяють даунгрейди (пріоритет не > 1000), або вам бракує старішої версії в доступних репо.
Виправлення: Переконайтесь, що потрібна старіша версія є в stable/security і тимчасово встановіть pin для цього пакета на 1001, щоб дозволити даунгрейд, потім видаліть тимчасовий pin.
5) Симптом: не вдається встановити вендорський пакет, бо перемогли Debian-пакети
Корінь: Ви зафіксували vendor низько (добре), але не запросили явно vendor-версії, і Debian дає валідний кандидат.
Виправлення: Встановіть явно по версії або через target release (якщо вендор має окремий release), або створіть вузький pin лише для цього вендорського пакета.
6) Симптом: оновлення безпеки блокуються («kept back») після закріплення
Корінь: Ви занадто агресивно зафіксували залежність (наприклад libc, openssl, systemd), перешкоджаючи security-репо оновити її.
Виправлення: Приберіть pin для критичних компонентів. Якщо треба заморозити — використайте обмежений у часі hold з тикетом і планом відкату. Потім розморозьте.
7) Симптом: різні сервери обирають різних кандидатів
Корінь: Конфігурація репо відрізняється (файли sources), pin-файли різні, або один хост пропустив apt update і працює зі застарілою метаданою. Іноді proxy/cache дає різні вигляди.
Виправлення: Порівняйте /etc/apt/sources.list* і /etc/apt/preferences.d між хостами; забезпечте консистентні оновлення метаданих; стандартизуйте через CM.
Чек-листи / покроковий план (безпечний для production)
Базова політика (зробіть це до того, як знадобиться)
- Встановіть Default-Release на кодову назву stable у керованій конфігурації (або перевірте, що воно є і не змінюється).
- Розділіть pin за наміром у
/etc/apt/preferences.d, а не в одному монолітному файлі. - Зафіксуйте backports на 100 глобально, якщо у вас немає конкретної причини піднімати його.
- Зафіксуйте vendor-репо на 50 по origin як базову оборонну позицію.
- Allowlist-винятки вузько: тільки конкретні пакети отримують 990 з backports/vendor.
- Напишіть правило «немає видалень без схвалення» для оновлень і впровадьте його в процес змін.
Перед будь-яким вікном оновлень
- Запустіть
sudo apt updateі переконайтесь в коректності метаданих репо. - Запустіть
sudo apt -s dist-upgradeі перевірте видалення та великі розширення залежностей. - Для будь-якого дивного кандидата запустіть
apt-cache policy pkgі підтвердіть джерело та пріоритет. - Якщо тягнете з backports — переконайтесь, що це свідомо й обмежено потрібними пакетами.
Коли треба встановити з backports (безпечний шаблон)
- Тримайте backports на 100 глобально.
- Додайте вузький pin для потрібних пакетів на 990 з backports.
- Симулюйте установку/оновлення і перевірте побічні апгрейди.
- Встановіть на канарковому хості першим. Підтвердіть здоров’я сервісів і поведінку при завантаженні (особливо для змін ядра/модулів).
- Поширюйте поступово.
Коли потрібне вендор-репо (безпечний шаблон)
- Зафіксуйте origin вендора на 50 для
Package: *. - Зафіксуйте тільки ті вендор-пакети, які вам справді потрібні, вищими (990), і тримайте їхні ланцюги залежностей видимими.
- Явно перевірте, що core-бібліотеки залишаються з Debian, якщо тільки у вас немає контракту підтримки, який цього вимагає.
- Тримайте чистий шлях для видалення. Вендорські агенти мають звичку застрявати в дивний спосіб.
Жарт №2: APT охоче вирішить вашу проблему залежностей, видаливши ваш додаток. Це як звільнити клієнта, щоб підвищити показники задоволеності клієнта.
Питання й відповіді
1) Чим користуватись: pinning чи apt-mark hold?
Використовуйте pinning для політики («надавати перевагу Debian security над vendor», «backports opt-in»). Використовуйте holds для коротких явних заморозок («не змінювати ядро цього тижня»). Holds повинні бути обмежені в часі.
2) Які числа Pin-Priority варто реально використовувати?
Типові здорові значення: stable/security за замовчуванням (часто 990 при Default-Release), backports 100 глобально, vendor 50 глобально. Використовуйте 990 для конкретних пакетів, які хочете з backports/vendor. Використовуйте >1000 тільки для тимчасових примусових даунгрейдів.
3) Чи можна пінувати за кодовою назвою vs за archive?
Так, але будьте послідовні. Pin за release a=trixie-backports зазвичай стабільний. Pin за n= теж можливий, але перевірте, що метадані репо фактично містять те, що ви очікуєте, через apt-cache policy.
4) Чому apt іноді вибирає «нижчий пріоритет» репо?
Бо кандидат з вищим пріоритетом може бути не встановлюваним через залежності. Apt вибере встановлюване рішення. Ось чому дебаг резольвера корисний: він показує, які обмеження примусили вибір.
5) Як уникнути випадкового створення FrankenDebian?
Не додавайте testing/unstable репо в stable-сервери. Якщо мусите додати не-Debian репо, зафіксуйте його низько по origin і allowlist-уйте конкретні пакети. І завжди симулюйте оновлення перед застосуванням.
6) Чи достатньо pin, щоб зробити сторонні репо безпечними?
Ні. Pin контролює вподобання, а не довіру. Вам все одно потрібне управління keyring, гігієна репо і причина для включення репо.
7) У чому різниця між apt upgrade і apt full-upgrade з pin?
apt upgrade уникає видалень і складних змін, часто залишаючи пакети «kept back». apt full-upgrade (або dist-upgrade) дозволяє видалення, щоб задовольнити залежності. Pin впливають на обидва, але full-upgrade показує реальну вартість вашої політики.
8) Чи можна безпечно пінувати цілі набори залежностей?
Можна, але легко перестаратись. Віддавайте перевагу вузьким pin: пакет, який вам потрібен, плюс мінімальний набір його вимог. Якщо ви пінуєте широкий набір, ви фактично переходите на інший release track для цього підсистеми.
9) Як відновитися, якщо вже зробили апгрейд з неправильного репо?
Спочатку зупиніть подальші оновлення. Додайте pin, які переорієнтують на Debian stable/security, потім симулюйте шлях даунгрейду. Якщо даунгрейд складний — розгляньте відновлення хоста з нуля (часто безпечніше), аніж складні in-place даунгрейди core-бібліотек.
10) Чи варто пінувати ядра?
Якщо вам потрібен суворий контроль ядра (драйвери, DKMS, модулі збереження), так — або тимчасово утримайте мета-пакет, або закріпіть джерела ядра. Але не забувайте про безпеку: заморожування ядра має бути коротким і свідомим.
Наступні кроки, які вам реально варто зробити
Якщо у вас є сервери Debian 13, що мають значення, виконайте ці кроки в порядку:
- Зробіть інвентар репозиторіїв по флоту і видаліть все, що не можете обґрунтувати.
- Встановіть
APT::Default-Releaseна кодову назву Debian 13 послідовно на всіх хостах. - Створіть
/etc/apt/preferences.d/10-backports-optin.prefі тримайте backports на 100 глобально. - Зафіксуйте будь-які vendor-репо на 50 по origin, а потім allowlist лише пакети, які вам справді потрібні.
- Зробіть
apt -s dist-upgradeобов’язковим кроком перед змінами. Жодних видалень без схвалення. - Щомісяця аудитуйте утримання (
apt-mark showhold) і видаляйте ті, що втратили обґрунтування.
Винагорода нудна, але краща: оновлення стають рутинними, дрейф видно, і apt перестає вас дивувати о 02:13. Сервери все одно іноді ламатимуться — це нормально — але не тому, що ви дозволили пакетному менеджеру імпровізувати.