Unbound’u systemd ile Servis Olarak Yönetme
Unbound’u production ortamında çalıştırıyorsanız, onun servis olarak doğru yönetilmesi en az konfigürasyonu yazmak kadar kritik. Kaç kere gördüm: adamlar güzel bir Unbound kurulumu yapmışlar, recursive resolver çalışıyor, DNSSEC doğrulama var, cache ayarları yerinde. Ama ilk sistem yeniden başlatmasında servis açılmıyor çünkü systemd entegrasyonu yarım bırakılmış. Ya da bir şey ters gidince logları nerede arayacaklarını bilmiyorlar. Bu yazıda Unbound’u systemd ile nasıl düzgün yöneteceğinizi, servis davranışını nasıl özelleştireceğinizi ve gerçek ortamlarda karşılaşılan senaryoları ele alacağım.
systemd ile Temel Servis Yönetimi
Unbound kurulumundan sonra ilk yapmanız gereken şey sistemd servis entegrasyonunun sağlıklı olup olmadığını kontrol etmek. Dağıtıma göre servis adı değişebilir; Debian/Ubuntu’da genellikle unbound, RHEL/CentOS/AlmaLinux ailesi üzerinde de aynı şekilde unbound olarak geliyor.
# Servis durumunu detaylı kontrol et
systemctl status unbound
# Servisi başlat
systemctl start unbound
# Sistem açılışında otomatik başlaması için etkinleştir
systemctl enable unbound
# Hem etkinleştir hem de hemen başlat
systemctl enable --now unbound
systemctl status çıktısını dikkatli okuyun. Sadece “active (running)” görmek yetmez. PID, ana process, memory kullanımı ve en son log satırlarına bakın. Unbound’un doğru başladığından emin olmak için başlangıç loglarını da kontrol etmek gerekiyor:
# Son 50 log satırını getir
journalctl -u unbound -n 50
# Gerçek zamanlı log takibi
journalctl -u unbound -f
# Bugünkü logları getir
journalctl -u unbound --since today
# Belirli bir zaman aralığı
journalctl -u unbound --since "2024-01-15 08:00:00" --until "2024-01-15 10:00:00"
Unbound’un systemd Unit Dosyasını Anlamak
Paket yöneticisi ile kurduğunuzda gelen varsayılan unit dosyası genellikle /lib/systemd/system/unbound.service veya /usr/lib/systemd/system/unbound.service konumunda bulunur. Bu dosyayı doğrudan düzenlemek yerine, override mekanizmasını kullanmak çok daha doğru bir yaklaşım. Paket güncellemelerinde yaptığınız değişiklikler ezilmez.
# Mevcut unit dosyasını görüntüle
systemctl cat unbound
# Override dizini ve dosyası oluştur
systemctl edit unbound
systemctl edit unbound komutu sizi /etc/systemd/system/unbound.service.d/override.conf dosyasına götürür. Bu dosya, orijinal unit dosyasındaki değerlerin üzerine yazar.
Tipik bir Unbound unit dosyası şuna benzer:
[Unit]
Description=Unbound DNS Resolver
Documentation=man:unbound(8)
After=network.target
Before=network-online.target nss-lookup.target
Wants=nss-lookup.target
[Service]
Type=notify
Restart=on-failure
EnvironmentFile=-/etc/default/unbound
ExecStartPre=/usr/lib/unbound/package-helper chroot_setup
ExecStartPre=/usr/lib/unbound/package-helper root_trust_anchor_update
ExecStart=/usr/sbin/unbound -d -p
ExecStopPost=/usr/lib/unbound/package-helper chroot_teardown
PrivateTmp=true
# ... devamı var
Burada dikkat etmeniz gereken bazı kritik direktifler var:
- Type=notify: Unbound, hazır olduğunda systemd’ye bildirim gönderir. Bu sayede bağımlı servisler Unbound tam olarak hazır olmadan başlamaz.
- Restart=on-failure: Servis çöktüğünde otomatik yeniden başlar, ama siz durdurunca başlamaz.
- After=network.target: Ağ başladıktan sonra Unbound başlar. Bazı ortamlarda bu yeterli olmayabilir.
Ağ Bağımlılığı Sorunlarını Çözmek
Production’da sık karşılaşılan bir problem şu: sistem açılıyor, Unbound başlıyor ama henüz ağ arayüzleri tam olarak ayağa kalkmamış. Özellikle DHCP ile IP alan ya da bonding/bridging konfigürasyonu olan sunucularda bu can sıkıcı bir hal alıyor.
# Override dosyasını düzenle
systemctl edit unbound
[Unit]
After=network-online.target
Wants=network-online.target
[Service]
Restart=on-failure
RestartSec=5s
StartLimitIntervalSec=60s
StartLimitBurst=3
network-online.target kullanımı tartışmalı bir konu. Systemd dokümantasyonu bunu servisler için değil, ağa ihtiyaç duyan “one-shot” işlemler için öneriy. Ama DNS sunucusu gibi ağa bağımlı bir servis için makul bir tercih. Bununla birlikte, networkd-wait-online veya NetworkManager-wait-online servislerinin aktif olduğundan emin olun:
systemctl enable systemd-networkd-wait-online.service
# veya NetworkManager kullanıyorsanız
systemctl enable NetworkManager-wait-online.service
Servis Yeniden Başlatma Stratejileri
Unbound konfigürasyonunu değiştirdiğinizde DNS çözümlemesinin kesintisiz devam etmesini istersiniz. Tam restart yerine reload kullanmak bu durumda hayat kurtarır:
# Konfigürasyonu doğrula
unbound-checkconf /etc/unbound/unbound.conf
# Servisi yeniden yükle (bağlantıları kesmeden)
systemctl reload unbound
# Tam yeniden başlatma
systemctl restart unbound
# Konfigürasyon değişikliğinden sonra önerilen akış
unbound-checkconf /etc/unbound/unbound.conf && systemctl reload unbound
Bunu bir script haline getirip /usr/local/sbin/ altına koyabilirsiniz:
#!/bin/bash
# /usr/local/sbin/unbound-reload-safe.sh
set -e
CONFIG_FILE="${1:-/etc/unbound/unbound.conf}"
echo "Konfigürasyon kontrol ediliyor: $CONFIG_FILE"
if unbound-checkconf "$CONFIG_FILE"; then
echo "Konfigürasyon geçerli. Servis yeniden yükleniyor..."
systemctl reload unbound
echo "Unbound başarıyla yeniden yüklendi."
systemctl status unbound --no-pager -l
else
echo "HATA: Konfigürasyon geçersiz! Servis yeniden yüklenmedi." >&2
exit 1
fi
chmod +x /usr/local/sbin/unbound-reload-safe.sh
systemd Resource Control ile Kaynak Yönetimi
Unbound’u paylaşımlı bir sunucuda çalıştırıyorsanız, kaynakları sınırlamak isteyebilirsiniz. systemd’nin cgroup entegrasyonu bunu kolaylaştırıyor:
systemctl edit unbound
[Service]
# CPU sınırlaması - toplam CPU kapasitesinin %25'i
CPUQuota=25%
# Memory sınırlaması
MemoryLimit=512M
# Veya daha modern direktif
MemoryMax=512M
MemoryHigh=400M
# Dosya tanımlayıcı limiti - büyük ortamlar için artırın
LimitNOFILE=65536
# Öncelik ayarı
Nice=-5
Bu ayarları uyguladıktan sonra systemd’yi yeniden yükleyin:
systemctl daemon-reload
systemctl restart unbound
# Kaynak kullanımını izle
systemctl status unbound
# veya
cat /sys/fs/cgroup/system.slice/unbound.service/memory.current
Güvenlik Sertleştirmesi: systemd Sandbox Özellikleri
Modern systemd sürümlerinde servisler için kapsamlı sandbox yetenekleri mevcut. Unbound için bunları kullanmak, olası bir güvenlik açığının etkisini ciddi ölçüde sınırlar:
systemctl edit unbound
[Service]
# Ayrı bir /tmp kullan
PrivateTmp=true
# Ağ erişimini kısıtlama (dikkatli kullanın, DNS için ağ şart)
# PrivateNetwork=false
# Sistem dosyalarını salt okunur yap
ProtectSystem=strict
# /home dizinini gizle
ProtectHome=true
# Kernel parametrelerini koru
ProtectKernelParameters=true
ProtectKernelModules=true
# /proc ve /sys erişimini kısıtla
ProtectProc=invisible
ProcSubset=pid
# Capability kısıtlaması
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_SETUID CAP_SETGID
AmbientCapabilities=CAP_NET_BIND_SERVICE
# Sistem çağrısı filtresi
SystemCallFilter=@system-service
SystemCallErrorNumber=EPERM
# Yazma iznini sadece gerekli dizinlere ver
ReadWritePaths=/var/lib/unbound /run/unbound /var/log/unbound
Bu kadar agresif bir sandbox konfigürasyonu Unbound’un çalışmasını bozabilir. Her değişiklikten sonra test edin:
systemctl daemon-reload
systemctl restart unbound
systemctl status unbound
journalctl -u unbound -n 20
# Test sorgusu
dig @127.0.0.1 google.com
systemd-analyze ile Başlangıç Performansı
Sunucu boot süresi kritikse Unbound’un başlangıca ne kadar katkıda bulunduğunu görmek isteyebilirsiniz:
# Boot süresini analiz et
systemd-analyze blame | grep unbound
# Servis bağımlılık ağacını görselleştir
systemd-analyze critical-chain unbound.service
# Plot çıktısı (SVG dosyası)
systemd-analyze plot > /tmp/boot-analysis.svg
Unbound’un boot süresini uzatıp uzatmadığını anlamak için bu çıktıları incelemek değerli. Eğer critical-chain çıktısında Unbound görünüyorsa ve diğer kritik servisler onu bekliyor ise, Type=notify ile gerçekten bildirim gönderip göndermediğini kontrol edin.
Watchdog Entegrasyonu
systemd’nin watchdog özelliği, donmuş ya da yanıt vermeyen servisleri tespit edip yeniden başlatmak için kullanılır. Unbound Type=notify kullandığından, watchdog desteği de mevcut:
systemctl edit unbound
[Service]
# Watchdog süresi - Unbound bu sürede sinyal göndermezse restart
WatchdogSec=30s
Restart=on-watchdog
RestartSec=10s
Unbound’un watchdog bildirimlerini gönderip göndermediğini doğrulamak için:
journalctl -u unbound | grep -i watchdog
Log Yönetimi ve Rotation
Unbound varsayılan olarak syslog’a ya da kendi log dosyasına yazar. systemd journal kullanıyorsanız ek konfigürasyon gerekmez. Ancak dosyaya log yazıyorsanız logrotate konfigürasyonu şart:
# /etc/logrotate.d/unbound
cat > /etc/logrotate.d/unbound << 'EOF'
/var/log/unbound/unbound.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
create 0640 unbound unbound
postrotate
/usr/sbin/unbound-control log_reopen 2>/dev/null || true
endscript
}
EOF
Journal üzerinden log yönetimi için:
# Journal boyutunu sınırla
journalctl --vacuum-size=100M
# Belirli süre öncesini temizle
journalctl --vacuum-time=30d
# Unbound loglarını belirli priority ile filtrele
journalctl -u unbound -p err..emerg
# JSON formatında log çekme (log analiz araçları için)
journalctl -u unbound -o json-pretty | head -100
Birden Fazla Unbound Instance Yönetimi
Bazı ortamlarda birden fazla Unbound instance çalıştırmanız gerekebilir. Örneğin biri recursive resolver, diğeri yalnızca yerel alan adları için authoritative gibi. systemd’nin template unit özelliği burada işe yarıyor:
# Template unit dosyası oluştur
cat > /etc/systemd/system/[email protected] << 'EOF'
[Unit]
Description=Unbound DNS Resolver - %i instance
After=network.target
Documentation=man:unbound(8)
[Service]
Type=notify
User=unbound
Group=unbound
ExecStartPre=/usr/sbin/unbound-checkconf /etc/unbound/unbound-%i.conf
ExecStart=/usr/sbin/unbound -d -c /etc/unbound/unbound-%i.conf
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
# recursive ve local instance başlat
systemctl enable --now unbound@recursive
systemctl enable --now unbound@local
# Durumları kontrol et
systemctl status "unbound@*"
Her instance için ayrı konfigürasyon dosyası oluşturuyorsunuz: /etc/unbound/unbound-recursive.conf, /etc/unbound/unbound-local.conf gibi. Farklı portlarda, farklı ayarlarla çalışabilirler.
Gerçek Dünya Senaryosu: Güncellemeden Sonra Servis Başlamıyor
Geçen ay bir müşteri ortamında şöyle bir durumla karşılaştım. apt upgrade sonrasında Unbound güncellendi ve servis başlamaz oldu. systemctl status unbound çıktısı “Failed to start” diyordu, detay yoktu.
# Önce son logları kontrol et
journalctl -u unbound -n 30 --no-pager
# Servis başlatmayı manuel dene ve çıktısına bak
systemctl start unbound
journalctl -u unbound -f &
systemctl restart unbound
# Çok daha detaylı analiz için
journalctl -u unbound -p debug --since "5 minutes ago"
Sorun şuydu: yeni paket, unit dosyasına yeni bir ExecStartPre satırı eklemiş ve bu script /var/lib/unbound/ dizininde yoktu. Override dosyamız orijinal unit’i kısmen override ettiği için bu yeni satır çalışmıyordu.
Çözüm:
# Override dosyasını incele
cat /etc/systemd/system/unbound.service.d/override.conf
# Orijinal unit ile karşılaştır
systemctl cat unbound
# Gerekirse override'ı sıfırla ve sıfırdan başla
systemctl revert unbound
# Sonra tekrar düzenle
systemctl edit unbound
Bu deneyimden çıkardığım ders: paket güncellemelerinden sonra systemctl cat servis_adı komutuyla mevcut unit durumunu mutlaka kontrol edin.
Monitoring ve Alert Entegrasyonu
systemd servis izleme için basit bir Bash scripti:
#!/bin/bash
# /usr/local/sbin/check-unbound-health.sh
ALERT_EMAIL="[email protected]"
LOG_TAG="unbound-health"
check_service() {
if ! systemctl is-active --quiet unbound; then
logger -t "$LOG_TAG" "KRITIK: Unbound servisi aktif degil!"
# Restart dene
systemctl restart unbound
sleep 5
if systemctl is-active --quiet unbound; then
logger -t "$LOG_TAG" "BILGI: Unbound basariyla yeniden baslatildi."
else
logger -t "$LOG_TAG" "KRITIK: Unbound yeniden baslatma basarisiz!"
# Mail gönder
echo "Unbound servisi $(hostname) sunucusunda yanit vermiyor!" |
mail -s "[KRITIK] DNS Servisi Down" "$ALERT_EMAIL"
fi
fi
}
check_resolution() {
if ! dig @127.0.0.1 google.com A +time=3 +tries=1 &>/dev/null; then
logger -t "$LOG_TAG" "UYARI: DNS cozumlemesi basarisiz!"
fi
}
check_service
check_resolution
# Crontab'a ekle
echo "*/5 * * * * root /usr/local/sbin/check-unbound-health.sh" > /etc/cron.d/unbound-health
chmod 644 /etc/cron.d/unbound-health
Daha profesyonel bir yaklaşım için systemd‘nin OnFailure direktifini kullanabilirsiniz:
systemctl edit unbound
[Unit]
OnFailure=unbound-failure-alert@%n.service
Bu sayede Unbound başarısız olduğunda otomatik olarak bir alert servisi tetiklenir.
Sonuç
Unbound’un systemd ile yönetimi, ilk bakışta basit gibi görünse de gerçek production ortamlarında detaylar önemli. Override mekanizmasını kullanarak paket güncellemelerini güvenli atlatmak, Type=notify ile bağımlı servislerin sırasını doğru yönetmek, sandbox direktifleriyle saldırı yüzeyini küçültmek ve watchdog ile servis sağlığını kontrol altında tutmak. Bunların hepsi birlikte düşünülmesi gereken bir bütün.
En kritik alışkanlık: her konfigürasyon değişikliğinde önce unbound-checkconf, sonra systemctl reload. Tam restart’tan kaçının, DNS çözümlemesinde yaşanacak kısa kesinti bile bazı ortamlarda kabul edilemez. Log takibini ihmal etmeyin; journalctl’nin --since ve -u parametreleriyle sorunları çok daha hızlı tespit edersiniz. Sistemde ne olduğunu anlamadan “restart attım çalıştı” mantığıyla hareket eden sysadmin sayısı maalesef az değil. Loglarla dost olun.
