Dovecot ile Yüksek Erişilebilirlik Kurulumu

Mail altyapısı söz konusu olduğunda, tek bir sunucuya bağımlı kalmak bir felakete davet çıkarmak gibidir. Dovecot’un yüksek erişilebilirlik (HA) kurulumu, hem küçük hem de kurumsal ölçekteki ortamlarda mail hizmetinin kesintisiz devam etmesini sağlar. Bu yazıda gerçek dünya senaryoları üzerinden, production ortamına hazır bir Dovecot HA kurulumunu adım adım ele alacağız.

Mimariyi Anlamak

Dovecot ile HA kurulumu yaparken iki temel yaklaşım var: aktif-pasif ve aktif-aktif kümeleme. Küçük ve orta ölçekli ortamlarda aktif-pasif yeterli olurken, binlerce kullanıcıya hizmet veren ortamlarda aktif-aktif kurulum kaçınılmaz oluyor.

Tipik bir kurulum şu bileşenleri içeriyor:

  • Shared storage: NFS, GlusterFS veya Ceph ile tüm mail verisi merkezi depolamada tutulur
  • Load balancer: HAProxy veya Keepalived ile gelen bağlantılar yönetilir
  • Dovecot Director: Dovecot’un kendi proxy katmanı, kullanıcı oturumlarını tek sunucuya yönlendirir
  • Database clustering: Kullanıcı ve kimlik doğrulama verisi için MySQL/PostgreSQL cluster

Bu yazıda Dovecot Director + GlusterFS + HAProxy kombinasyonunu kullanacağız. Bu kombinasyon, hem kurumsal hem de orta ölçekli ortamlarda son derece iyi sonuç veriyor.

Ortam Hazırlığı

Senaryomuzda 4 sunucumuz var:

  • mail-lb: 192.168.10.10 (HAProxy + Keepalived, load balancer)
  • mail-dir1: 192.168.10.11 (Dovecot Director #1)
  • mail-dir2: 192.168.10.12 (Dovecot Director #2)
  • mail-backend1: 192.168.10.21 (Dovecot Backend #1)
  • mail-backend2: 192.168.10.22 (Dovecot Backend #2)
  • VIP: 192.168.10.100 (Sanal IP, kullanıcıların bağlandığı adres)

Önce tüm sunucularda gerekli paketleri kuralım:

# Ubuntu/Debian için
apt update && apt install -y dovecot-core dovecot-imapd dovecot-pop3d 
  dovecot-lmtpd dovecot-mysql glusterfs-server glusterfs-client

# RHEL/CentOS/AlmaLinux için
dnf install -y dovecot dovecot-mysql glusterfs-server glusterfs-client

# Dovecot servisini başlat
systemctl enable --now dovecot
systemctl enable --now glusterd

GlusterFS ile Paylaşımlı Depolama Kurulumu

Backend sunucularda GlusterFS volume oluşturuyoruz. Mail verisi her iki backend’de senkronize tutulacak.

# mail-backend1 ve mail-backend2 üzerinde çalıştır
# Önce brick dizinini oluştur
mkdir -p /data/gluster/mail-brick

# mail-backend1 üzerinde peer bağlantısı kur
gluster peer probe 192.168.10.22

# Volume oluştur (replica 2 = her iki sunucuda kopya tutar)
gluster volume create mail-storage replica 2 
  192.168.10.21:/data/gluster/mail-brick 
  192.168.10.22:/data/gluster/mail-brick force

# Volume'ü başlat
gluster volume start mail-storage

# Performans ayarları
gluster volume set mail-storage performance.cache-size 256MB
gluster volume set mail-storage performance.io-thread-count 16
gluster volume set mail-storage network.ping-timeout 10

# Volume durumunu kontrol et
gluster volume status mail-storage

Tüm sunucularda GlusterFS volume’ü mount edelim:

# /etc/fstab'a ekle (tüm mail sunucularında)
echo "192.168.10.21:/mail-storage /var/vmail glusterfs 
  defaults,_netdev,backup-volfile-servers=192.168.10.22 0 0" >> /etc/fstab

# Dizini oluştur ve mount et
mkdir -p /var/vmail
mount -a

# Mount'u doğrula
df -h /var/vmail

Dovecot Backend Sunucu Yapılandırması

Backend sunucular gerçek mail verilerini işler. Her iki backend’de aynı yapılandırmayı kullanıyoruz.

# /etc/dovecot/dovecot.conf
cat > /etc/dovecot/dovecot.conf << 'EOF'
protocols = imap pop3 lmtp

# Log ayarları
log_path = /var/log/dovecot/dovecot.log
info_log_path = /var/log/dovecot/dovecot-info.log
debug_log_path = /var/log/dovecot/dovecot-debug.log

# Mail depolama
mail_location = maildir:/var/vmail/%d/%n/Maildir

# Kullanıcı ve grup
mail_uid = vmail
mail_gid = vmail

# Performans
mail_max_userip_connections = 20
EOF

Backend’lerde 10-auth.conf yapılandırması:

cat > /etc/dovecot/conf.d/10-auth.conf << 'EOF'
auth_mechanisms = plain login

# MySQL ile kimlik doğrulama
!include auth-sql.conf.ext

# Dovecot Director'dan gelen proxy bağlantıları için
passdb {
  driver = static
  args = nopassword=y proxy=y proxy_maybe=y
  result_success = continue
}
EOF

SQL kimlik doğrulama dosyasını oluşturalım:

cat > /etc/dovecot/conf.d/auth-sql.conf.ext << 'EOF'
passdb {
  driver = sql
  args = /etc/dovecot/dovecot-sql.conf.ext
}

userdb {
  driver = sql
  args = /etc/dovecot/dovecot-sql.conf.ext
}
EOF

cat > /etc/dovecot/dovecot-sql.conf.ext << 'EOF'
driver = mysql
connect = host=192.168.10.30 dbname=mailserver user=dovecot password=GucluParola123

default_pass_scheme = SHA512-CRYPT

password_query = SELECT email as user, password FROM virtual_users 
  WHERE email='%u' AND active=1

user_query = SELECT '/var/vmail/%d/%n' as home, 
  'maildir:/var/vmail/%d/%n/Maildir' as mail, 
  5000 AS uid, 5000 AS gid, 
  concat('*:bytes=', quota) AS quota_rule 
  FROM virtual_users WHERE email='%u' AND active=1
EOF

Dovecot Director Yapılandırması

Director katmanı, her kullanıcının aynı backend sunucuya yönlendirilmesini sağlar. Bu, IMAP oturumlarının tutarlı çalışması için kritik önem taşıyor.

# /etc/dovecot/dovecot.conf (Director sunucularda)
cat > /etc/dovecot/dovecot.conf << 'EOF'
protocols = imap pop3 lmtp

# Director modunda çalış
service director {
  unix_listener login/director {
    mode = 0666
  }
  fifo_listener login/proxy-notify {
    mode = 0600
  }
  unix_listener director-userdb {
    mode = 0600
  }
  inet_listener {
    port = 9090
  }
}

# Director ring yapılandırması
director_servers = 192.168.10.11 192.168.10.12
director_mail_servers = 192.168.10.21 192.168.10.22

# Kullanıcı oturumu tutma süresi (dakika)
director_user_expire = 15 mins

# Proxy ayarları
service imap-login {
  inet_listener imap {
    port = 143
  }
  inet_listener imaps {
    port = 993
    ssl = yes
  }
}

service pop3-login {
  inet_listener pop3 {
    port = 110
  }
  inet_listener pop3s {
    port = 995
    ssl = yes
  }
}

# Proxy modunda kimlik doğrulama
passdb {
  driver = static
  args = proxy=y proxy_maybe=y host=%{director_backend}
}
EOF

Director’ın backend sunucularla iletişimi için kimlik doğrulama:

cat > /etc/dovecot/conf.d/10-director.conf << 'EOF'
# Director ring protokol portu
director_servers = 192.168.10.11:9090 192.168.10.12:9090

# Backend sunucular ve kapasiteleri (vhost count)
director_mail_servers = 192.168.10.21 192.168.10.22

# Consistent hashing algoritması kullan
director_consistent_hashing = yes

# Backend down olduğunda kullanıcıları taşı
director_user_expire = 15 mins
EOF

HAProxy ve Keepalived ile Yük Dengeleme

Load balancer sunucusunda HAProxy yapılandırması:

cat > /etc/haproxy/haproxy.cfg << 'EOF'
global
    log /dev/log local0
    log /dev/log local1 notice
    maxconn 50000
    user haproxy
    group haproxy
    daemon
    stats socket /run/haproxy/admin.sock mode 660 level admin

defaults
    log global
    mode tcp
    option tcplog
    option dontlognull
    timeout connect 5s
    timeout client 60s
    timeout server 60s
    retries 3

# IMAP Frontend
frontend imap_front
    bind *:143
    bind *:993 ssl crt /etc/ssl/dovecot/mail.pem
    default_backend imap_directors

# POP3 Frontend
frontend pop3_front
    bind *:110
    bind *:995 ssl crt /etc/ssl/dovecot/mail.pem
    default_backend pop3_directors

# IMAP Backend (Directors)
backend imap_directors
    balance leastconn
    option tcp-check
    tcp-check connect port 143
    server dir1 192.168.10.11:143 check inter 5s rise 2 fall 3
    server dir2 192.168.10.12:143 check inter 5s rise 2 fall 3

# POP3 Backend (Directors)
backend pop3_directors
    balance leastconn
    option tcp-check
    server dir1 192.168.10.11:110 check inter 5s rise 2 fall 3
    server dir2 192.168.10.12:110 check inter 5s rise 2 fall 3

# HAProxy stats
frontend stats
    bind *:8404
    mode http
    stats enable
    stats uri /stats
    stats refresh 10s
    stats auth admin:SifrenizBuraya
EOF

systemctl restart haproxy

Keepalived ile VIP yönetimi:

# mail-lb (Master) üzerinde /etc/keepalived/keepalived.conf
cat > /etc/keepalived/keepalived.conf << 'EOF'
global_defs {
   router_id MAIL_LB_MASTER
   script_user root
   enable_script_security
}

vrrp_script chk_haproxy {
    script "/bin/kill -0 $(cat /var/run/haproxy.pid)"
    interval 2
    weight -20
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 110
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass MailHA2024
    }
    virtual_ipaddress {
        192.168.10.100/24
    }
    track_script {
        chk_haproxy
    }
    notify_master "/usr/local/bin/haproxy-master.sh"
    notify_backup "/usr/local/bin/haproxy-backup.sh"
}
EOF

systemctl enable --now keepalived

Dovecot’ta SSL/TLS Yapılandırması

Production ortamında SSL mutlaka yapılandırılmalı:

# /etc/dovecot/conf.d/10-ssl.conf
cat > /etc/dovecot/conf.d/10-ssl.conf << 'EOF'
ssl = required
ssl_cert = </etc/ssl/dovecot/fullchain.pem
ssl_key = </etc/ssl/dovecot/privkey.pem
ssl_ca = </etc/ssl/dovecot/chain.pem

# Güvenli protokol ve cipher ayarları
ssl_min_protocol = TLSv1.2
ssl_cipher_list = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:
ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384

# ECDH eğrisi
ssl_curve_list = prime256v1:secp384r1

# SSL oturum önbelleği
ssl_dh = </etc/dovecot/dh.pem
EOF

# Diffie-Hellman parametrelerini oluştur (biraz zaman alır)
openssl dhparam -out /etc/dovecot/dh.pem 4096

İzleme ve Sağlık Kontrolü

Cluster’ın sağlıklı çalıştığını izlemek için bir script hazırlayalım:

cat > /usr/local/bin/dovecot-ha-check.sh << 'SCRIPT'
#!/bin/bash

DIRECTORS=("192.168.10.11" "192.168.10.12")
BACKENDS=("192.168.10.21" "192.168.10.22")
ALERT_EMAIL="[email protected]"
LOG_FILE="/var/log/dovecot-ha-check.log"

timestamp() {
    date '+%Y-%m-%d %H:%M:%S'
}

check_service() {
    local host=$1
    local port=$2
    local timeout=5

    if timeout $timeout bash -c "echo >/dev/tcp/$host/$port" 2>/dev/null; then
        echo "OK"
    else
        echo "DOWN"
    fi
}

check_gluster() {
    gluster volume status mail-storage | grep -c "Online"
}

echo "=== $(timestamp) - Dovecot HA Sağlık Kontrolü ===" >> $LOG_FILE

# Director kontrolü
for dir in "${DIRECTORS[@]}"; do
    imap_status=$(check_service $dir 143)
    echo "Director $dir IMAP: $imap_status" >> $LOG_FILE

    if [ "$imap_status" == "DOWN" ]; then
        echo "UYARI: Director $dir erişilemiyor!" | 
          mail -s "Dovecot HA Uyarı: Director Down" $ALERT_EMAIL
    fi
done

# Backend kontrolü
for backend in "${BACKENDS[@]}"; do
    lmtp_status=$(check_service $backend 24)
    echo "Backend $backend LMTP: $lmtp_status" >> $LOG_FILE

    if [ "$lmtp_status" == "DOWN" ]; then
        echo "UYARI: Backend $backend erişilemiyor!" | 
          mail -s "Dovecot HA Uyarı: Backend Down" $ALERT_EMAIL
    fi
done

# GlusterFS kontrolü
online_count=$(check_gluster)
echo "GlusterFS online brick sayısı: $online_count" >> $LOG_FILE

if [ "$online_count" -lt 2 ]; then
    echo "KRİTİK: GlusterFS brick sayısı yetersiz: $online_count" | 
      mail -s "Dovecot HA KRİTİK: GlusterFS Sorunu" $ALERT_EMAIL
fi

echo "=== Kontrol tamamlandı ===" >> $LOG_FILE
SCRIPT

chmod +x /usr/local/bin/dovecot-ha-check.sh

# Cron'a ekle (her 5 dakikada bir)
echo "*/5 * * * * root /usr/local/bin/dovecot-ha-check.sh" >> /etc/cron.d/dovecot-ha

Başarısızlık Senaryosu ve Test

Kurulumun gerçekten çalıştığını test etmek için birkaç senaryo uygulayalım.

Senaryo 1: Backend Sunucu Çöküyor

# mail-backend1 üzerinde Dovecot'u durdur (simülasyon)
systemctl stop dovecot

# Director üzerinde durumu kontrol et
doveadm director status

# Kullanıcıların mail-backend2'ye taşındığını doğrula
doveadm director ring status

# Birkaç dakika sonra backend1'i geri getir
systemctl start dovecot

# Kullanıcıların geri dengelenmesini izle
watch -n 2 'doveadm director status'

Senaryo 2: Director Sunucu Çöküyor

# mail-dir1 üzerinde servisi durdur
systemctl stop dovecot

# HAProxy otomatik olarak dir2'ye yönlendirmeli
# HAProxy stats sayfasından kontrol et: http://192.168.10.10:8404/stats

# Bağlı istemcileri kontrol et
ss -tn | grep ':143|:993' | wc -l

# Director ring'in tek başına çalıştığını doğrula (dir2 üzerinde)
doveadm director ring status

Senaryo 3: GlusterFS Brick Arızası

# Bozuk brick'i simüle et
gluster volume info mail-storage

# Self-heal durumunu kontrol et
gluster volume heal mail-storage info

# Brick geri geldiğinde self-heal başlat
gluster volume heal mail-storage

# Heal tamamlanana kadar izle
gluster volume heal mail-storage info healed

Performans Tuning

Yüksek yük altında performansı artırmak için:

cat > /etc/dovecot/conf.d/10-master.conf << 'EOF'
service imap {
  # Her IMAP prosesi için
  vsz_limit = 512M
  
  process_limit = 1024
}

service imap-login {
  process_min_avail = 10
  process_limit = 1024
  service_count = 0
  
  # idle_kill = 1 mins -- varsayılan yeterli
}

service auth {
  # Auth prosesi sayısı
  process_count_limit = 10
  client_limit = 4096
}

service auth-worker {
  max_lines = 1
  process_limit = 30
}

# Kernel parametreleri için sysctl
# /etc/sysctl.d/99-dovecot.conf dosyasına ekle:
# net.core.somaxconn = 65535
# net.ipv4.tcp_max_syn_backlog = 65535
# fs.file-max = 2097152
EOF

Kernel parametrelerini de ayarlayalım:

cat > /etc/sysctl.d/99-dovecot.conf << 'EOF'
# Maksimum açık dosya sayısı
fs.file-max = 2097152

# TCP bağlantı kuyruğu
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535

# TCP keepalive
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 5

# Bellek optimizasyonu
net.ipv4.tcp_rmem = 4096 87380 33554432
net.ipv4.tcp_wmem = 4096 65536 33554432
EOF

sysctl -p /etc/sysctl.d/99-dovecot.conf

Yedekleme Stratejisi

HA kurulumu, yedeklemenin yerini tutmaz. Dovecot mail verilerini yedekleyelim:

cat > /usr/local/bin/dovecot-backup.sh << 'BACKUP'
#!/bin/bash

BACKUP_DIR="/backup/mail"
MAIL_DIR="/var/vmail"
RETENTION_DAYS=7
DATE=$(date +%Y%m%d_%H%M%S)

mkdir -p $BACKUP_DIR

# Mail dizinini yedekle (incremental)
rsync -avz --delete 
  --backup --backup-dir=$BACKUP_DIR/incremental/$DATE 
  --link-dest=$BACKUP_DIR/latest 
  $MAIL_DIR/ 
  $BACKUP_DIR/latest/

# Dovecot yapılandırmasını yedekle
tar czf $BACKUP_DIR/config_$DATE.tar.gz /etc/dovecot/

# Eski yedekleri temizle
find $BACKUP_DIR/incremental -maxdepth 1 -type d 
  -mtime +$RETENTION_DAYS -exec rm -rf {} ;

echo "$(date): Yedekleme tamamlandı - $DATE" >> /var/log/dovecot-backup.log
BACKUP

chmod +x /usr/local/bin/dovecot-backup.sh

# Gece 2'de çalıştır
echo "0 2 * * * root /usr/local/bin/dovecot-backup.sh" >> /etc/cron.d/dovecot-backup

Sık Karşılaşılan Sorunlar ve Çözümleri

Gerçek production deneyiminden bazı notlar:

GlusterFS split-brain durumu: Ağ bölünmesi sırasında iki brick çakışan veriye sahip olabilir. gluster volume heal mail-storage full komutu çoğu zaman işe yarasa da, kritik durumlarda manuel müdahale gerekebilir. GlusterFS loglarını her zaman takip edin: /var/log/glusterfs/.

Director ring bölünmesi: İki director arasındaki bağlantı kesilirse, her biri bağımsız karar verebilir. doveadm director ring status çıktısında broken görürseniz, Dovecot servisini sırayla yeniden başlatmak sorunu çözer.

HAProxy’nin bağlantıyı çok erken kesmesi: Büyük mailbox senkronizasyonları sırasında timeout client ve timeout server değerlerini artırmanız gerekebilir. Bazı IMAP istemcileri büyük klasörleri senkronize ederken 60 saniye yetmeyebilir, bu değeri 300 saniyeye çekebilirsiniz.

Vmail kullanıcısı izin sorunları: GlusterFS üzerinde uid/gid tutarsızlığı olabilir. Tüm sunucularda vmail kullanıcısının aynı uid (örneğin 5000) ile oluşturulduğundan emin olun.

# Tüm sunucularda tutarlı uid/gid oluştur
groupadd -g 5000 vmail
useradd -u 5000 -g 5000 -d /var/vmail -s /bin/false vmail
chown -R vmail:vmail /var/vmail

Sonuç

Dovecot ile yüksek erişilebilirlik kurulumu, doğru bileşenler seçildiğinde oldukça kararlı bir mail altyapısı sunar. Bu yazıda anlattığımız mimari ile tek bir bileşenin arızalanması tüm mail servisini çökertemez. GlusterFS mail verisini replika olarak tutar, Dovecot Director kullanıcı oturumlarını tutarlı biçimde yönetir, HAProxy ve Keepalived ise ön tarafta kesintisiz erişim sağlar.

Kurulumu tamamladıktan sonra yapmanız gerekenler şunlar: düzenli failover testleri yapın, izleme sistemini (Prometheus + Grafana ya da Zabbix) entegre edin, GlusterFS heal loglarını günlük takip edin ve yedeklerin gerçekten çalıştığını ayda bir test restore yaparak doğrulayın.

Son olarak şunu söylemek isterim: HA kurulumu bir son nokta değil, başlangıç noktasıdır. Sisteminizi canlı ortamda test etmeden “çalışıyor” diyemezsiniz. Planlı failover testlerini takvime alın ve her seferinde öğrendiklerinizi dokümante edin. Bir gün o notlar sizi kurtarır.

Yorum yapın