Zimbra’da Yedekleme ve Geri Yükleme Stratejileri

Yıllar önce bir müşterimizin Zimbra sunucusu çöktüğünde, üç günlük mail verisini kaybettik. O gün bir daha asla “zaten çalışıyor, yedek almaya gerek yok” cümlesini kurmadım. Zimbra yedekleme konusu, pek çok sysadmin’in ertelediği ama ilk ciddi olayda pişman olduğu bir alan. Bu yazıda teorik bilgiden ziyade, sahada işe yarayan stratejileri ve komutları paylaşacağım.

Zimbra Yedekleme Mimarisini Anlamak

Zimbra’yı yedeklemeden önce neyi yedeklediğinizi anlamanız gerekiyor. Zimbra, birkaç kritik bileşenden oluşur:

  • LDAP dizini: Kullanıcı hesapları, dağıtım listeleri, domain ayarları
  • Mesaj deposu: Gerçek mail verileri, ekler, takvim ve kişi bilgileri
  • MySQL/MariaDB veritabanı: Posta kutusu metadata’sı, alias’lar, konfigürasyon tabloları
  • Konfigürasyon dosyaları: LocalConfig, global config ayarları

Bunların hepsini ayrı ayrı yedeklemek yerine bütünleşik bir strateji kurmak, geri yükleme anında hayat kurtarır. Ben genellikle kurumsal ortamlarda iki katmanlı bir yaklaşım kullanıyorum: hot backup (servis ayakta iken) ve cold backup (servis durdurularak).

Hot Backup ile Servis Kesintisiz Yedekleme

Çoğu üretim ortamında posta sunucusunu durdurmak lüks sayılır. Zimbra bu ihtiyaca karşılık olarak kendi içinde bazı araçlar sunar.

zmmailbox ile Posta Kutusu Bazlı Yedek Alma

Tek bir kullanıcının verisini dışa aktarmak için zmmailbox aracı kullanılır. Bu özellikle “sadece şu kullanıcının maillerini kurtar” talepleri için biçilmiş kaftandır:

# zimbra kullanıcısına geç
su - zimbra

# Tek kullanıcı için tam yedek
zmmailbox -z -m [email protected] getRestURL '/?fmt=tgz' > /backup/kullanici_backup_$(date +%Y%m%d).tgz

# Belirli bir klasörü yedekle
zmmailbox -z -m [email protected] getRestURL '/Inbox?fmt=tgz' > /backup/kullanici_inbox_$(date +%Y%m%d).tgz

Bu yöntem küçük ölçekli geri yüklemelerde son derece pratik. Ancak büyük posta kutularında (50GB+ gibi) zaman alır ve Zimbra’nın REST API’si üzerinden çalıştığı için sunucu yükünü artırır.

Tüm Sunucu İçin Sıkıştırılmış Yedekleme Scripti

Gerçek bir üretim ortamı için kullandığım script şu şekilde:

#!/bin/bash
# /usr/local/sbin/zimbra_hot_backup.sh

BACKUP_DIR="/backup/zimbra"
DATE=$(date +%Y%m%d_%H%M%S)
LOG_FILE="/var/log/zimbra_backup.log"
ZIMBRA_HOME="/opt/zimbra"

echo "[$(date)] Zimbra hot backup başlatıldı" >> $LOG_FILE

# LDAP yedeği al
su - zimbra -c "zmlocalconfig -s zimbra_ldap_password" | grep -oP '(?<=zimbra_ldap_password = ).*' > /tmp/ldap_pass.tmp

su - zimbra -c "/opt/zimbra/libexec/zmslapcat $BACKUP_DIR/ldap_$DATE"
if [ $? -eq 0 ]; then
    echo "[$(date)] LDAP yedeği alındı" >> $LOG_FILE
else
    echo "[$(date)] HATA: LDAP yedeği başarısız!" >> $LOG_FILE
fi

# MySQL/MariaDB yedeği
MYSQL_PASS=$(su - zimbra -c "zmlocalconfig -s zimbra_mysql_password" | grep -oP '(?<=zimbra_mysql_password = ).*')

mysqldump -u zimbra -p"$MYSQL_PASS" --all-databases --single-transaction 
    > $BACKUP_DIR/mysql_$DATE.sql

gzip $BACKUP_DIR/mysql_$DATE.sql
echo "[$(date)] MySQL yedeği alındı" >> $LOG_FILE

# Konfigürasyon dosyalarını yedekle
tar -czf $BACKUP_DIR/config_$DATE.tar.gz 
    /opt/zimbra/conf/ 
    /opt/zimbra/ssl/ 
    /opt/zimbra/store/ 2>/dev/null

echo "[$(date)] Konfigürasyon yedeği alındı" >> $LOG_FILE

# 30 günden eski yedekleri temizle
find $BACKUP_DIR -type f -mtime +30 -delete
echo "[$(date)] Eski yedekler temizlendi" >> $LOG_FILE

echo "[$(date)] Hot backup tamamlandı" >> $LOG_FILE

Bu scripti crontab’a eklemek için:

# Her gece 02:00'da çalıştır
0 2 * * * /usr/local/sbin/zimbra_hot_backup.sh

Cold Backup: Tam Yedekleme İçin Doğru Yöntem

Kritik bakım pencerelerinde veya büyük versiyon güncellemelerinden önce cold backup şarttır. Servis durdurulduğunda alınan bu yedekler tutarlılık açısından çok daha güvenilirdir.

#!/bin/bash
# Cold backup scripti - servisi durdurarak tam yedek

BACKUP_DIR="/backup/zimbra/cold"
DATE=$(date +%Y%m%d)

echo "Zimbra servisleri durduruluyor..."
su - zimbra -c "zmcontrol stop"
sleep 30

# Zimbra'nın tüm dizinini yedekle
echo "Ana dizin yedekleniyor..."
rsync -avz --progress /opt/zimbra/ $BACKUP_DIR/zimbra_full_$DATE/ 
    --exclude="*.pid" 
    --exclude="log/*.log" 
    --exclude="data/tmp/"

# LDAP yedeği (servis kapalıyken)
echo "LDAP dump alınıyor..."
slapcat -l $BACKUP_DIR/ldap_full_$DATE.ldif

echo "Zimbra servisleri başlatılıyor..."
su - zimbra -c "zmcontrol start"

echo "Cold backup tamamlandı: $BACKUP_DIR"

Burada rsync kullanmayı tercih ediyorum çünkü sonraki yedeklerde sadece değişen dosyaları kopyalıyor ve bu özellikle büyük posta depolarında ciddi zaman kazandırıyor.

Incremental Yedekleme: Gerçek Dünyada Kullanılabilir Strateji

Günlük tam yedek almak hem zaman hem depolama açısından pahalı. Incremental (artımlı) yedekleme ile sadece değişen verileri yedekleyebilirsiniz. Zimbra’nın mesaj deposu için şu yapıyı kullanıyorum:

#!/bin/bash
# Incremental yedekleme - rsync ile

BACKUP_ROOT="/backup/zimbra/incremental"
STORE_PATH="/opt/zimbra/store"
DATE=$(date +%Y%m%d)
YESTERDAY=$(date -d "yesterday" +%Y%m%d)

# İlk tam yedek varsa artımlı al
if [ -d "$BACKUP_ROOT/base" ]; then
    rsync -avz --link-dest=$BACKUP_ROOT/base 
        $STORE_PATH/ 
        $BACKUP_ROOT/inc_$DATE/
    
    echo "Artımlı yedek tamamlandı: inc_$DATE"
else
    # İlk kez çalışıyorsa tam yedek al
    rsync -avz $STORE_PATH/ $BACKUP_ROOT/base/
    echo "Temel yedek oluşturuldu"
fi

# MySQL binlog'larını da yedekle
cp -r /opt/zimbra/db/data/mysql-bin.* $BACKUP_ROOT/binlogs_$DATE/ 2>/dev/null

--link-dest parametresi burada kritik: değişmeyen dosyalar için hard link oluşturur, böylece depolama alanı israf edilmez.

LDAP Verilerini Yönetmek

LDAP, Zimbra’nın iskeletidir. Kullanıcı listesi, domain yapısı, COS (Class of Service) tanımları burada durur. LDAP yedeklemesi ayrı bir önem taşır:

# LDAP'ı dışa aktar (Zimbra çalışırken)
su - zimbra -c "zmlocalconfig -s ldap_master_url"

# ldap verisini ldif formatında dışa aktar
su - zimbra -c "/opt/zimbra/libexec/zmslapcat /tmp/ldap_export"

# Üretilen dosyaları kontrol et
ls -lh /tmp/ldap_export/

# LDAP yedeğini başka bir sunucuya kopyala
scp /tmp/ldap_export/ldap.bak.gz backup-server:/backup/zimbra/ldap/

Bir projede LDAP’ı yanlışlıkla bozdum (evet, olur), ve sadece bu ldif dosyası sayesinde iki saat içinde sistemi eski haline getirebildim. O günden beri LDAP yedeğine özel önem veriyorum.

Geri Yükleme Senaryoları

Yedek almak işin yarısı, asıl mesele o yedeği geri yükleyebilmek. Farklı senaryolar için farklı yaklaşımlar gerekir.

Senaryo 1: Tek Kullanıcı Maillerini Geri Yüklemek

En sık karşılaşılan durum bu. Kullanıcı yanlışlıkla önemli mailleri silmiş ya da hesap başka bir sebepten bozulmuş:

# Kullanıcının TGZ yedeğini geri yükle
su - zimbra

zmmailbox -z -m [email protected] postRestURL '/?fmt=tgz&resolve=reset' 
    /backup/kullanici_backup_20240115.tgz

# Resolve parametreleri:
# reset: Mevcut veriyi sil, yedeği yükle
# ignore: Çakışmaları atla
# replace: Çakışanları üstüne yaz
# modify: Metadata'yı güncelle ama içeriği koru

resolve parametresini dikkatli kullanın. reset seçeneği mevcut posta kutusunu silerek başlar, bu çoğu zaman istediğiniz şeydir ama bazı durumlarda değil.

Senaryo 2: Veritabanı Geri Yükleme

MySQL/MariaDB bozulması durumunda:

# Zimbra servislerini durdur
su - zimbra -c "zmcontrol stop"

# MySQL'i tek başına başlat
su - zimbra -c "mysql.server start"

# Yedeği geri yükle
MYSQL_PASS=$(su - zimbra -c "zmlocalconfig -s zimbra_mysql_password" | 
    grep -oP '(?<=zimbra_mysql_password = ).*')

zcat /backup/zimbra/mysql_20240115.sql.gz | 
    mysql -u zimbra -p"$MYSQL_PASS"

# Tüm servisleri yeniden başlat
su - zimbra -c "zmcontrol start"

Senaryo 3: Tam Sunucu Geri Yükleme

Felaket senaryosu. Sunucu tamamen gitti, yeni bir makineye Zimbra kuruldu ve yedekten dönülecek:

# 1. Aynı hostname ve IP ile yeni sunucu hazırla
# 2. Aynı Zimbra versiyonunu kur (kritik!)
# 3. Servisleri durdur
su - zimbra -c "zmcontrol stop"

# 4. LDAP'ı geri yükle
su - zimbra -c "zmcontrol stop"
service slapd stop

# Mevcut LDAP verisini temizle
rm -rf /opt/zimbra/data/ldap/hdb/db/*

# Yedeği geri yükle
slapadd -l /backup/zimbra/ldap_full_20240115.ldif

# Dosya sahipliklerini düzelt
chown -R zimbra:zimbra /opt/zimbra/data/ldap/

# 5. Mesaj deposunu geri yükle
rsync -avz /backup/zimbra/cold/zimbra_full_20240115/store/ 
    /opt/zimbra/store/

# 6. Tüm servisleri başlat
su - zimbra -c "zmcontrol start"

# 7. İndeksleri yeniden oluştur (büyük ortamlarda zaman alır)
su - zimbra -c "zmreindex -a start"

Yedek Doğrulama: Yedek Aldım ama Çalışıyor mu?

Asıl sorun burada. Pek çok ekip yedek alır ama hiç test etmez. Bunu otomatikleştirmek için basit bir doğrulama scripti:

#!/bin/bash
# /usr/local/sbin/zimbra_backup_verify.sh

BACKUP_DIR="/backup/zimbra"
ALERT_MAIL="[email protected]"
LOG="/var/log/zimbra_backup_verify.log"

echo "[$(date)] Yedek doğrulama başladı" >> $LOG

# En son yedek dosyalarının varlığını kontrol et
LATEST_MYSQL=$(ls -t $BACKUP_DIR/mysql_*.sql.gz 2>/dev/null | head -1)
LATEST_LDAP=$(ls -t $BACKUP_DIR/ldap_*/ldap.bak.gz 2>/dev/null | head -1)

if [ -z "$LATEST_MYSQL" ]; then
    echo "HATA: MySQL yedeği bulunamadı!" | 
        mail -s "Zimbra Yedek Uyarisi" $ALERT_MAIL
    echo "[$(date)] HATA: MySQL yedeği yok" >> $LOG
fi

# MySQL yedeğinin sağlığını kontrol et
if [ -n "$LATEST_MYSQL" ]; then
    FILE_AGE=$(( ($(date +%s) - $(stat -c %Y $LATEST_MYSQL)) / 3600 ))
    if [ $FILE_AGE -gt 26 ]; then
        echo "UYARI: MySQL yedeği $FILE_AGE saat önce alınmış!" | 
            mail -s "Zimbra Yedek Uyarisi" $ALERT_MAIL
    fi
    
    # Dosya boyutu sıfır mı?
    FILE_SIZE=$(stat -c %s $LATEST_MYSQL)
    if [ $FILE_SIZE -lt 1000 ]; then
        echo "HATA: MySQL yedek dosyası çok küçük ($FILE_SIZE bytes)!" | 
            mail -s "Zimbra Yedek Hatasi" $ALERT_MAIL
    fi
fi

echo "[$(date)] Doğrulama tamamlandı" >> $LOG

Bu script’i haftada bir değil, her gün çalıştırın. Yedek sorununu ne kadar erken fark ederseniz o kadar iyi.

Uzak Sunucuya Yedek Aktarımı

Yedeğinizi aynı sunucuda tutmak, sunucu yandığında yedeği de kaybetmek demektir. Basit ama kritik bir nokta:

#!/bin/bash
# Yedekleri uzak sunucuya gönder

BACKUP_DIR="/backup/zimbra"
REMOTE_USER="backupuser"
REMOTE_HOST="192.168.1.100"
REMOTE_DIR="/backup/zimbra-from-prod"

# SSH key authentication kullandığınızı varsayıyoruz
rsync -avz --delete 
    --exclude="*.tmp" 
    -e "ssh -p 22 -i /root/.ssh/backup_key" 
    $BACKUP_DIR/ 
    $REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR/

if [ $? -eq 0 ]; then
    echo "[$(date)] Uzak yedek aktarımı başarılı" >> /var/log/zimbra_backup.log
else
    echo "[$(date)] HATA: Uzak yedek aktarımı başarısız!" >> /var/log/zimbra_backup.log
    # Burada alert mekanizmanızı tetikleyebilirsiniz
fi

--delete parametresi kullanırken dikkatli olun: uzak sunucuda silinen yerel dosyaların da silinmesini sağlar. Bir felaket senaryosunda bu istenmeyebilir. Uzun süreli saklama için --backup ve --backup-dir kombinasyonunu değerlendirin.

Zimbra Network Edition Kullanıcıları İçin

Eğer Zimbra Network Edition kullanıyorsanız, yerleşik backup aracı hayatı kolaylaştırır. Ama bu aracı da doğru yapılandırmak gerekir:

# Network Edition backup aracını yapılandır
su - zimbra

# Backup location ayarla
zmprov modifyConfig zimbraBackupTarget /backup/zimbra

# Backup modunu ayarla (auto veya standard)
zmprov modifyConfig zimbraBackupMode auto

# Otomatik backup zamanlamasını aktif et
zmprov modifyConfig zimbraBackupAutoGroupedNumGroups 7

# Manuel tam yedek başlat
zmbackup -f -a all

# Yedek durumunu kontrol et
zmbackupquery

# Geri yükleme
zmrestore -ra -ct mb -a [email protected] -lb <backup-label>

Network Edition’ın en büyük avantajı incremental mail-level backup yapabilmesi. Tek bir maili dahi geri yükleyebilirsiniz, bu açık kaynak sürümde mümkün değil.

Pratik Öneriler ve Öğrendiğim Dersler

Yıllar içinde Zimbra ortamlarında edindiğim bazı pratik notlar:

  • Yedek öncesi servis durumunu kaydet: zmcontrol status > /tmp/zimbra_status_before_backup.txt ile hangi servislerin çalıştığını kaydedin.
  • Versiyon uyumluluğu kritiktir: Geri yükleme yapacağınız Zimbra versiyonu, yedeği aldığınız versiyon ile aynı olmalı. Versiyon farkı büyükse önce eski versiyona geri yükleyin, sonra yükseltin.
  • Store dizini büyük olabilir: /opt/zimbra/store dizini büyük ortamlarda terabaytlara ulaşabilir. Yedekleme sürenizi ve bant genişliğinizi buna göre planlayın.
  • Test geri yüklemesi yapın: Her ay bir test ortamında gerçek geri yükleme deneyin. “Yedek var” ile “yedekten geri dönebiliyorum” çok farklı şeyler.
  • Log dosyalarını yedeklemeyin: /opt/zimbra/log dizinini yedeklemenize gerek yok, sadece yer kaplar.
  • SSL sertifikalarını ayrıca yedekleyin: /opt/zimbra/ssl dizini özellikle ticari sertifika kullananlar için kritik.

Sonuç

Zimbra yedekleme stratejisi tek bir scriptten ibaret değil. LDAP, MySQL, mesaj deposu ve konfigürasyon olmak üzere dört farklı bileşenin koordineli şekilde yedeklenmesi ve en önemlisi periyodik olarak test edilmesi gerekiyor. Hot backup günlük operasyonel ihtiyacı karşılarken, cold backup büyük değişiklikler öncesi güvence sağlıyor. Uzak sunucuya aktarım ise tek nokta arızasını ortadan kaldırıyor.

Şunu net söyleyeyim: en iyi yedekleme stratejisi, test edilmiş olandır. Altta yatan komutları anlayın, scriptlerinizi kendi ortamınıza göre uyarlayın ve her geri yükleme senaryosunu en az bir kez gerçek ortamda deneyin. O an geldiğinde, ve er ya da geç gelir, paniklemek yerine adımları takip etmek isteyeceksiniz.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir