معظم عمليات اقتحام الخوادم الناجحة لا تتم عبر ثغرات بارعة بل عبر ثغرة صدرت رقعتها قبل أشهر عدة. والسبب ليس الكسل عادة: فالتحديث يدويًا على خادم عامل مخيف، لأن apt upgrade يعيد أحيانًا تشغيل أشياء لم يطلب أحد إعادة تشغيلها. والتحديثات التلقائية تغلق هذا الملف، لكن سمعتها سيئة — وهي سمعة مستحقة بقدر ما تُضبَط على عجل.

لنستعرض ترتيبًا تصل فيه رقع الأمان من تلقاء نفسها ولا يتغيّر فيه إصدار PHP بين ليلة وضحاها.

التثبيت

sudo apt install unattended-upgrades apt-listchanges
sudo dpkg-reconfigure -plow unattended-upgrades

ينشئ الحوار الملف /etc/apt/apt.conf.d/20auto-upgrades. تحقّق مما نتج عنه:

APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";

الآحاد تعني «يوميًا». وكل هذا يقوده مؤقّت systemd لا cron الكلاسيكي:

systemctl list-timers | grep apt

الأهم: الأمان فقط

الملف الرئيسي هو /etc/apt/apt.conf.d/50unattended-upgrades. يحتوي على قائمة Allowed-Origins (وفي Debian Origins-Pattern)، وافتراضيًا لا يكون مفعّلًا هناك سوى مستودع الأمان وحده. اتركه هكذا.

وإغراء إزالة التعليق عن سطر -updates — «فليتحدّث كل شيء» — قوي. لا تفعل: فمستودع التحديثات يجلب إصدارات جديدة لا إصلاحات فحسب، ومن هناك بالضبط تأتي المفاجآت الليلية. فالأمان والحداثة مهمتان مختلفتان، والثانية تُنجَز يدويًا وأنت أمام لوحة المفاتيح على نحو أفضل.

وإن كان ثمة حزمة لا يجوز تحديثها تلقائيًا، فهناك قائمة سوداء لذلك:

Unattended-Upgrade::Package-Blacklist {
    "mariadb-server";
    "php8.3-fpm";
};

استخدمها بوعي: فكل سطر هنا يعني «هذه أحدّثها بنفسي» — وهذا وعد سيتعيّن عليك الوفاء به.

عمليات إعادة التشغيل

السطر المفصلي:

Unattended-Upgrade::Automatic-Reboot "false";

وإبقاؤه على false صحيح لخادم عليه موقع: فإعادة تشغيل غير معلنة في الثالثة فجرًا أسوأ من رقعة تأجّلت يومًا. لكن لهذا القرار نصفًا ثانيًا إلزاميًا، وهو النصف الذي يُنسى.

فحين تُحدَّث النواة أو libc أو openssl ينشئ النظام الملف /var/run/reboot-required. وحتى تحدث إعادة التشغيل تبقى النسخة المصحّحة على القرص بينما تعمل القديمة في الذاكرة — أي أن الثغرة لم تذهب إلى أي مكان مع أن الحزمة تُعد محدَّثة. تحقّق صراحة:

ls -l /var/run/reboot-required
cat /var/run/reboot-required.pkgs

ويسرد الملف الثاني ما الذي استوجب إعادة التشغيل بالضبط. والقاعدة بسيطة: ما إن ترى العلامة، خطّط لنافذة خلال اليوم أو اليومين القادمين، لا «في وقت ما».

والمكتبات حالة منفصلة. فـ openssl يُحدَّث بينما يواصل nginx و PHP-FPM العمل بالنسخة القديمة في الذاكرة، ولا تظهر أي علامة لإعادة التشغيل. ومن يحتاج إلى إعادة تشغيل يعرضه needrestart:

sudo apt install needrestart
sudo needrestart -b

واضبطه فقط على وضع «بلّغ ولا تسأل» — وإلا بدأ يطرح أسئلة في منتصف تثبيت غير تفاعلي فيعلّقه. ولذلك ضع ملفًا في /etc/needrestart/conf.d/ فيه السطر $nrconf{restart} = 'l';.

تحقّق أنه يعمل أصلًا

تشغيل تجريبي بلا تثبيت:

sudo unattended-upgrade --dry-run --debug

يُظهر المخرج أي الحزم تنطبق عليها القواعد وأيها رُفض ولماذا. وما حدث فعلًا موجود في السجلات:

sudo tail -50 /var/log/unattended-upgrades/unattended-upgrades.log

وكم تحديثًا ينتظر الآن:

apt list --upgradable 2>/dev/null | grep -i security

هذا الأمر الأخير هو الأنفع بينها جميعًا. فللتحديثات التلقائية المضبوطة عادة أن تتعطّل بصمت: امتلأ /boot، أو غيّر مستودع مفتاحه، أو عُطِّل المؤقّت بعد تعديل يدوي ما. ظاهريًا كل شيء على ما يرام، والرقع لم تُثبَّت منذ أشهر.

المساحة في /boot

حالة كلاسيكية: لا تُحذف النوى القديمة، فيمتلئ القسم /boot، ويفشل تثبيت نواة جديدة، وتتوقف التحديثات برمّتها. ومرة كل بضعة أشهر يستحق الأمر نظرة:

df -h /boot
sudo apt autoremove --purge

أو فعّل التنظيف التلقائي في الملف نفسه 50unattended-upgrades: Remove-Unused-Kernel-Packages "true" وRemove-Unused-Dependencies "true".

ما يبقى للإنسان

تزيل التحديثات التلقائية الروتين لا المراقبة. وثمة سؤالان ينبغي أن تكون قادرًا على الإجابة عنهما في أي لحظة: كم تحديث أمان ينتظر، وهل رُفعت علامة إعادة التشغيل. وكلتا الإجابتين سطر واحد على صفحة، وكل المعنى أن يقع هذا السطر في عينك من تلقاء نفسه بدل أن تبحث عنه بمبادرة منك مرة كل ربع سنة.