~/yazilar/ubuntu-otomatik-guvenlik-guncellemeleri
Ubuntu'da güvenlik güncellemelerini otomatiğe bağlamak
içindekiler
systemctl list-timers 'apt-daily*'NEXT LEFT LAST PASSED UNIT ACTIVATES
... 06:24:51 +03 9h left ... 06:11:02 +03 14h ago apt-daily-upgrade.timer apt-daily-upgrade.service
... 15:47:10 +03 18h left ... 08:03:39 +03 12h ago apt-daily.timer apt-daily.serviceTemiz bir Ubuntu Server kurulumunda bu iki timer zaten çalışıyor. apt-daily paket listelerini günde iki kez yeniliyor, apt-daily-upgrade sabah saatlerinde unattended-upgrades aracını çağırıyor. Yani güvenlik yamalarının otomatik kurulması varsayılan olarak açık geliyor.
Bu yazının derdi onu açmak olmayacak. Neyin, ne zaman, hangi kaynaktan kurulduğunu bilmek, kendi ortamına göre ayarlamak ve en çok tartışılan soruya bir cevap vermek: sunucu kendi kendine yeniden başlasın mı?
Varsayılanlar neler
Otomatik güncellemenin açık olup olmadığına karar veren dosya kısa:
cat /etc/apt/apt.conf.d/20auto-upgradesAPT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";Sayılar gün cinsinden aralık, 0 kapatıyor. Bu dosya yoksa ya da değerler sıfırsa sudo dpkg-reconfigure -plow unattended-upgrades dosyayı yeniden oluşturuyor.
Neyin kurulacağı ise /etc/apt/apt.conf.d/50unattended-upgrades içinde. Yorumları biraz ayıklayınca kaynak listesi şöyle görünüyor:
Unattended-Upgrade::Allowed-Origins {
"${distro_id}:${distro_codename}";
"${distro_id}:${distro_codename}-security";
"${distro_id}ESMApps:${distro_codename}-apps-security";
"${distro_id}ESM:${distro_codename}-infra-security";
// "${distro_id}:${distro_codename}-updates";
// "${distro_id}:${distro_codename}-proposed";
// "${distro_id}:${distro_codename}-backports";
};Varsayılan olarak sadece -security cebinden gelen paketler kuruluyor. İlk satırdaki sürümün kendi cebi, sürüm çıktıktan sonra değişmediği için pratikte bir şey kurmuyor, bağımlılıkların çözülebilmesi için orada. ESM satırları ise sadece Ubuntu Pro bağlı makinelerde işe yarıyor.
-updates satırı yorum olarak duruyor ve ben de sunucularda öyle bırakıyorum. O cepte hata düzeltmeleri ve bazen davranış değişiklikleri var. Güvenlik yamasını gece kendiliğinden kurmaya razıyım, bir paketin davranışının değişmesini ise bakım penceresinde, elimle görmek istiyorum.
Kendi ayarlarını ayrı dosyaya yaz
50unattended-upgrades paketin conffile'ı. Doğrudan düzenlersen paketin yeni sürümü geldiğinde dpkg sana hangi sürümü tutacağını soruyor. apt ayar dosyalarını alfabetik sırayla okuyor ve tekil değerlerde sonra gelen kazanıyor, listelere ise ekleme yapılıyor. Bu yüzden ayarlarımı 52unattended-upgrades-local adında ayrı bir dosyaya yazıyorum:
// /etc/apt/apt.conf.d/52unattended-upgrades-local
// Bu paketleri bakım penceresinde elle güncelliyorum
Unattended-Upgrade::Package-Blacklist {
"postgresql-";
"mariadb-server";
};
// Eski kernel'leri ve artık kullanılmayan bağımlılıkları temizle
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Remove-New-Unused-Dependencies "true";
// Sadece hata olduğunda e-posta at
Unattended-Upgrade::Mail "sistem@example.com";
Unattended-Upgrade::MailReport "only-on-error";
Unattended-Upgrade::SyslogEnable "true";Kara listedeki girdiler düzenli ifade olarak yorumlanıyor, postgresql- sürüm numarası taşıyan bütün PostgreSQL paketlerini yakalıyor. Veritabanı paketlerini listeye almamın nedeni şu: paket güncellenince servis de yeniden başlıyor ve bu kısa kesinti gündüz trafiğin ortasına denk gelebiliyor. Bedeli de var, o paketlerin güvenlik yamalarını artık senin takip etmen gerekiyor. Kara listeye aldığın her paket için bir hatırlatma kurmazsan aylarca yamasız kalabilir.
Remove-Unused-Kernel-Packages satırı /boot bölümünün dolmasını engelliyor. Her kernel güncellemesinde eski kernel'ler birikiyor, Ubuntu'nun kurulumda ayırdığı /boot bölümü de geniş değil.
E-posta ayarının çalışması için sunucunun posta gönderebilmesi gerekiyor. unattended-upgrades mail ya da sendmail komutunu arıyor, ikisi de yoksa e-posta gidemiyor ve bunu sadece kendi loguna bir uyarı satırı olarak yazıyor. Fark etmek kolay değil. Kurumda bir SMTP relay varsa postfix'i "Satellite system" olarak kurup bsd-mailx eklemek yetiyor.
Kurmadan önce prova
Ayarların ne yapacağını görmek için gerçek bir şey kurmadan çalıştırıyorum:
sudo unattended-upgrade --dry-run --debugStarting unattended upgrades script
Allowed origins are: o=Ubuntu,a=..., o=Ubuntu,a=...-security, o=UbuntuESMApps,a=...-apps-security, o=UbuntuESM,a=...-infra-security
Initial blacklist: postgresql- mariadb-server
Initial whitelist (not strict):
...
Packages that will be upgraded: openssl ...Burada iki şeye bakıyorum: Initial blacklist satırında kendi listem var mı, ve Allowed origins satırında beklemediğim bir kaynak görünüyor mu. Apt ayarlarının birleşmiş son halini görmek istersen apt-config dump | grep Unattended-Upgrade işe yarıyor.
Bir paketin hangi cepten geldiğinden emin değilsen apt-cache policy openssl çıktısındaki satırlarda -security ya da -updates ibaresini görürsün.
Saatini kendin seç
apt-daily-upgrade.timer varsayılan olarak sabah altı civarında, bir saatlik rastgele gecikmeyle çalışıyor. Bu saat mesai başına çok yakın, ben güncellemelerin gece bitmiş olmasını tercih ediyorum. Paketin timer dosyasını değiştirmek yerine üstüne bir drop-in yazıyorum:
sudo systemctl edit apt-daily-upgrade.timer[Timer]
OnCalendar=
OnCalendar=*-*-* 03:30
RandomizedDelaySec=20mİlk satırdaki boş OnCalendar= önemli. O olmadan yeni saat eskisinin yerine geçmiyor, ona ekleniyor ve timer günde iki kez tetikleniyor. RandomizedDelaySec ise onlarca sunucunun aynı dakikada yerel aynaya ya da proxy'ye yüklenmesini engelliyor.
systemctl list-timers apt-daily-upgrade.timerTimer'ların ve drop-in'lerin nasıl çalıştığını systemd yazısında daha ayrıntılı anlatıyorum.
Yeniden başlatma kararı
Kernel, glibc ya da OpenSSL gibi paketler güncellendiğinde yama ancak yeniden başlatma ya da servis yenileme sonrası devreye giriyor. Böyle bir güncellemede paketin kendi kurulum script'i /var/run/reboot-required dosyasını oluşturuyor. unattended-upgrades bu dosyaya bakıyor ve istersen yeniden başlatmayı kendisi de yapabiliyor.
Bu soruya tek bir doğru cevap yok, sunucunun ne iş yaptığına bağlı. Benim ayrımım şöyle: yük dengeleyicinin arkasında birden fazla kopyası olan, birinin kısa süre düşmesinin kimseye fark ettirmeyeceği sunucular kendi kendine yeniden başlayabilir. Tek kopya olan ve durduğunda bir şeyin durduğu sunucular (domain controller, veritabanı, dosya sunucusu) yeniden başlamaz. Onlarda izleme sistemi reboot-required dosyasını görüp uyarı üretiyor, yeniden başlatmayı bakım penceresinde ben yapıyorum.
Otomatik yeniden başlayabilen grup için ayrı bir dosya:
// /etc/apt/apt.conf.d/53otomatik-reboot
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "04:15";
Unattended-Upgrade::Automatic-Reboot-WithUsers "true";Automatic-Reboot-WithUsers varsayılan olarak açık ama birçok örnekte false yapılıyor. Bunu kapatırsan sunucuda açık bir oturum varken yeniden başlatma yapılmıyor. İlk bakışta mantıklı. Sorun şu ki biri tmux içinde bir oturumu açık bırakıp unutursa o sunucu hiç yeniden başlamıyor ve bunu fark etmiyorsun. Otomatik yeniden başlatmaya karar verdiğim sunucularda bunu açık bırakıyorum.
Aynı işi yapan iki sunucuya aynı saati verme. web01 04:15'te, web02 04:45'te yeniden başlasın. İkisi aynı dakikada kapanırsa yük dengeleyicinin arkasında kimse kalmaz.
Kernel yamalarını yeniden başlatmadan uygulayan Livepatch servisi de var. Ubuntu Pro aboneliğiyle geliyor, kurumun lisansı varsa tek kopyalık sunucularda yeniden başlatma baskısını azaltıyor. Yine de her yamayı kapsamıyor, yeniden başlatmayı tamamen ortadan kaldırmıyor.
needrestart
Kernel dışındaki güncellemelerde çoğu zaman sunucuyu değil, eski kütüphaneyi bellekte tutan servisleri yeniden başlatmak yetiyor. OpenSSL yamalandı ama nginx eski kütüphaneyle çalışmaya devam ediyorsa yama kâğıt üstünde kalıyor. needrestart bunu buluyor:
sudo needrestart -r lScanning processes...
Scanning linux images...
Running kernel seems to be up-to-date.
Services to be restarted:
systemctl restart cron.service
systemctl restart nginx.service
No containers need to be restarted.
No user sessions are running outdated binaries.-r l sadece listeliyor, hiçbir şeyi yeniden başlatmıyor. needrestart apt'ye bir hook olarak da bağlı ve her paket kurulumundan sonra çalışıyor. Ne yapacağı $nrconf{restart} ayarına bağlı: i sorarak, a kendiliğinden yeniden başlatıyor, l sadece listeliyor.
Ayarı yine ana dosyaya değil conf.d altına yazıyorum. Servisler kendiliğinden yeniden başlasın ama veritabanına dokunulmasın:
# /etc/needrestart/conf.d/kurum.conf
$nrconf{restart} = 'a';
$nrconf{override_rc}{qr(^postgresql)} = 0;
$nrconf{override_rc}{qr(^mariadb)} = 0;Dosya Perl sözdiziminde, satır sonundaki noktalı virgülü unutursan needrestart açılışta hata veriyor.
İzleme tarafı için -b (batch) modu daha kullanışlı, çıktısı makine tarafından okunacak biçimde:
sudo needrestart -bNEEDRESTART-VER: ...
NEEDRESTART-KCUR: ...-generic
NEEDRESTART-KEXP: ...-generic
NEEDRESTART-KSTA: 3
NEEDRESTART-SVC: nginx.serviceKSTA: 3 yeni bir kernel'in kurulduğunu ve yeniden başlatma beklediğini söylüyor, 1 her şeyin güncel olduğunu. Zabbix ya da Nagios gibi bir araçla bu satırı okuyup uyarı üretmek kolay. Nagios uyumlu çıktı için needrestart -p de var.
Logları okumak
unattended-upgrades iki log dosyası tutuyor. İlki ne yaptığını özetliyor, ikincisi dpkg'nin ham çıktısı:
sudo tail -n 20 /var/log/unattended-upgrades/unattended-upgrades.log
sudo less /var/log/unattended-upgrades/unattended-upgrades-dpkg.log... INFO Starting unattended upgrades script
... INFO Allowed origins are: o=Ubuntu,a=..., o=Ubuntu,a=...-security, ...
... INFO Initial blacklist: postgresql- mariadb-server
... INFO Packages that will be upgraded: openssl ...
... INFO Writing dpkg log to /var/log/unattended-upgrades/unattended-upgrades-dpkg.log
... INFO All upgrades installed"Dün gece ne değişti?" sorusunun cevabı ise apt'nin kendi geçmişinde, elle yaptığın kurulumlar da orada:
zcat -f /var/log/apt/history.log* | grep -E '^(Start-Date|Commandline|Upgrade):' | tail -n 12Timer'ın çalışıp çalışmadığını, çalıştıysa ne kadar sürdüğünü journal'dan görüyorsun:
journalctl -u apt-daily-upgrade.service --since "3 days ago"Sık karşılaşılan sorunlar
Elle apt çalıştırınca kilit hatası. Sabah sunucuya girip apt install dediğinde şu çıkıyorsa arka planda unattended-upgrades çalışıyor:
E: Could not get lock /var/lib/dpkg/lock-frontend. It is held by process 2345 (unattended-upgr)
N: Be aware that removing the lock file is not a solution and may break your system.
E: Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), is another process using it?Mesaj zaten söylüyor ama yine yazayım: kilit dosyasını silme. systemctl status apt-daily-upgrade.service ile işin bitmesini bekle. Yarıda kesilen bir dpkg işlemi, beklemekten çok daha fazla vakit alır.
Bir paket hiç güncellenmiyor. unattended-upgrades conffile sorusu soracak paketleri atlıyor, çünkü cevap verecek kimse yok. Logda şuna benzer bir satır görürsün:
Package openssh-server has conffile prompt and needs to be upgraded manuallyÇözüm o paketi bir kez elle güncellemek. Uzun vadeli çözüm ise paketlerin conffile'larını düzenlemeyip ayarları .d dizinlerine koymak. SSH yazısında ayarları sshd_config.d altına yazmamın bir nedeni de buydu.
/boot doldu. Eski kernel'ler temizlenmediyse yeni kernel kurulumu yarıda kalıyor. Remove-Unused-Kernel-Packages açıksa bu sorun azalıyor. Dolmuşsa sudo apt autoremove --purge çoğu zaman yetiyor.
E-posta gelmiyor. Önce sunucunun e-posta gönderebildiğini test et: echo deneme | mail -s deneme sistem@example.com. Bu gitmiyorsa sorun unattended-upgrades'te değil. Gidiyorsa MailReport değerine bak, only-on-error her şey yolundayken sessiz kalıyor.
apt upgrade bazı paketleri bekletiyor. "deferred due to phasing" mesajı hata değil. Ubuntu -updates cebindeki bazı güncellemeleri kademeli olarak dağıtıyor ve senin makinen henüz sırasını almamış. Güvenlik cebi bundan etkilenmiyor.
Hangi sunucuda ne yapıyorum
Kararları tek tabloda toplayınca şöyle duruyor:
| Sunucu tipi | Güvenlik yamaları | Otomatik yeniden başlatma | needrestart |
|---|---|---|---|
| Yük dengeleyici arkasındaki web/uygulama | Otomatik | Evet, kopyalar arasında saat farkıyla | a |
| Tek kopya servis (DC, dosya sunucusu) | Otomatik | Hayır, izleme uyarısı + bakım penceresi | a |
| Veritabanı | Otomatik, DB paketleri kara listede | Hayır | a, DB servisi hariç |
| Test ve geliştirme | Otomatik, -updates dahil | Evet | a |
Test sunucularında -updates cebini de açmamın nedeni, bir güncellemenin bir şeyi bozup bozmadığını production'dan önce orada görmek.
Sıradaki yazı: systemd ile kendi servisini ve timer'ını yazmak