Otomatik Yedekleme ve Rotasyon: Restic ile Eksiksiz Veri Güvenliği
Yedekleme işini ciddiye almayan sysadmin’lerin “disk öldü, ne yapacağız?” sorusuyla karşılaştığında yaşadığı paniği hepimiz ya bizzat deneyimledik ya da yakından izledik. Restic, bu paniği tarihe gömmek için tasarlanmış, modern ve son derece pratik bir yedekleme aracı. Deduplication, şifreleme, hızlı snapshot yönetimi ve çoklu backend desteğiyle Restic, elle yazılmış bash scriptlerin veya eski rsync tabanlı çözümlerin çok ötesine geçiyor. Bu yazıda Restic’i sıfırdan kurup, gerçek bir yedekleme stratejisi oluşturacak, rotasyon politikalarını otomatikleştirecek ve her şeyi cron ile bağlayacağız.
Restic Neden Bu Kadar Popüler Oldu?
Yedekleme dünyasında onlarca araç var ama Restic birkaç temel özelliğiyle öne çıkıyor.
İçerik tabanlı adresleme (content-addressed storage): Restic, verileri sabit boyutlu bloklara bölmek yerine değişken boyutlu “chunk”lara ayırır ve her chunk’ı SHA-256 hash’iyle tanımlar. Aynı veri iki kez yedeklendiğinde disk üzerinde sadece bir kez saklanır. Bu deduplication mekanizması sayesinde yedekleme boyutları inanılmaz küçülüyor.
Uçtan uca şifreleme: Repository’deki her şey AES-256 ile şifrelenir. Uzak bir sunucuya veya bulut depolamaya gönderdiğinizde provider tarafında kimse dosyalarınızı göremez.
Çoklu backend desteği: Local disk, SFTP, S3, Azure Blob Storage, Google Cloud Storage, Backblaze B2 ve daha fazlası. Rclone ile entegre ettiğinizde desteklenen backend sayısı neredeyse sınırsız hale geliyor.
Anlık snapshot’lar: Her yedekleme bir snapshot oluşturur. Belirli bir tarihteki duruma geri dönmek restic restore komutundan ibarettir.
Kurulum
Debian/Ubuntu
apt update && apt install restic -y
# Güncel sürüm için:
restic self-update
RHEL/CentOS/AlmaLinux
dnf install restic -y
# veya
yum install restic -y
Binary olarak manuel kurulum
wget https://github.com/restic/restic/releases/latest/download/restic_linux_amd64.bz2
bunzip2 restic_linux_amd64.bz2
chmod +x restic_linux_amd64
mv restic_linux_amd64 /usr/local/bin/restic
restic self-update
Kurulumu doğrulamak için:
restic version
Repository Oluşturma
Restic’te her şey bir “repository” üzerinden döner. Repository, yedeklerin depolandığı şifreli depodur. Önce bir repository oluşturmak gerekir.
Yerel Disk Repository
restic init --repo /mnt/backup/myrepo
Komut çalıştırıldığında bir parola istenir. Bu parola repository’nin şifreleme anahtarıdır. Bu parolayı kaybederseniz yedeklerinize bir daha erişemezsiniz. Parolayı bir parola yöneticisinde veya güvenli bir yerde saklayın.
SFTP ile Uzak Repository
Uzak sunucuya SSH key-based authentication kurulu olduğunu varsayıyorum:
restic init --repo sftp:[email protected]:/opt/restic-repos/webserver
SSH config dosyasındaki alias’ları da kullanabilirsiniz:
# ~/.ssh/config
Host backup-server
HostName 192.168.1.50
User backup
IdentityFile ~/.ssh/backup_key
Port 22
restic init --repo sftp:backup-server:/opt/restic-repos/webserver
S3 Uyumlu Depolama (MinIO, AWS S3, Wasabi)
export AWS_ACCESS_KEY_ID="your-access-key"
export AWS_SECRET_ACCESS_KEY="your-secret-key"
# AWS S3
restic init --repo s3:s3.amazonaws.com/bucket-name/restic-repo
# MinIO (kendi sunucunuzda)
restic init --repo s3:http://minio.example.com:9000/backup-bucket/restic-repo
Parola Yönetimi: Güvenli ve Otomatik
Manuel parola girmek otomasyonu bozar. Bunun için birkaç yöntem var:
Environment variable ile:
export RESTIC_PASSWORD="guclu-bir-parola-buraya"
restic -r /mnt/backup/myrepo snapshots
Parola dosyası ile (önerilen yöntem):
echo "guclu-bir-parola-buraya" > /etc/restic/password.txt
chmod 600 /etc/restic/password.txt
restic --repo /mnt/backup/myrepo --password-file /etc/restic/password.txt snapshots
Parola dosyasının sadece root tarafından okunabilir olduğundan emin olun. Cron job’larında ve script’lerde bu yöntemi kullanmak hem güvenli hem de pratik.
İlk Yedekleme
Repository hazır, şimdi gerçek bir yedekleme yapalım. Örnek senaryo: bir web sunucusunun /var/www, /etc/nginx ve veritabanı dump dizinini yedeklemek.
restic --repo sftp:backup-server:/opt/restic-repos/webserver
--password-file /etc/restic/password.txt
backup /var/www /etc/nginx /opt/db-dumps
--exclude="/var/www/cache"
--exclude="*.tmp"
--exclude="*.log"
--tag "webserver"
--tag "production"
Parametreleri açıklayalım:
- –repo: Repository’nin konumu
- –password-file: Parola dosyasının yolu
- backup: Yedeklenecek dizinler
- –exclude: Yedekleme dışında tutulacak pattern’lar
- –tag: Snapshot’lara etiket ekler, ileride filtrelemeyi kolaylaştırır
Yedekleme tamamlandıktan sonra snapshot’ları listelemek için:
restic --repo sftp:backup-server:/opt/restic-repos/webserver
--password-file /etc/restic/password.txt
snapshots
Çıktıda her snapshot’ın ID’si, tarihi, kaynağı ve boyutu görünür. Bu ID’leri geri yükleme işlemlerinde kullanacaksınız.
Kapsamlı Yedekleme Script’i
Gerçek dünyada tek satır komutlar yetmez. Hata yönetimi, loglama ve bildirim mekanizmaları içeren bir script gerekir. İşte production’da kullandığım yapıya yakın bir örnek:
#!/bin/bash
# /usr/local/bin/restic-backup.sh
# --- Konfigürasyon ---
REPO="sftp:backup-server:/opt/restic-repos/webserver"
PASSWORD_FILE="/etc/restic/password.txt"
LOG_FILE="/var/log/restic/backup-$(date +%Y%m%d).log"
BACKUP_DIRS="/var/www /etc/nginx /etc/apache2 /opt/db-dumps"
EXCLUDES="--exclude=/var/www/cache --exclude=*.tmp --exclude=*.log --exclude=*.sock"
TAGS="--tag webserver --tag $(hostname) --tag $(date +%A)"
NOTIFY_EMAIL="[email protected]"
# --- Fonksiyonlar ---
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
send_alert() {
echo "$1" | mail -s "Restic Backup HATA - $(hostname)" "$NOTIFY_EMAIL"
}
# --- Dizin Kontrolü ---
mkdir -p /var/log/restic
mkdir -p /opt/db-dumps
# --- MySQL/MariaDB Dump ---
log "Veritabani dump basliyor..."
if command -v mysqldump &> /dev/null; then
mysqldump --defaults-file=/etc/restic/mysql.cnf
--all-databases
--single-transaction
--routines
--triggers
> /opt/db-dumps/all-databases-$(date +%Y%m%d-%H%M%S).sql
if [ $? -ne 0 ]; then
log "HATA: Veritabani dump basarisiz!"
send_alert "MySQL dump alınamadı. Backup işlemi durdu."
exit 1
fi
log "Veritabani dump tamamlandi."
fi
# --- Repository Erisilebilirlik Kontrolu ---
log "Repository kontrol ediliyor..."
restic --repo "$REPO" --password-file "$PASSWORD_FILE" check --read-data-subset=5% >> "$LOG_FILE" 2>&1
if [ $? -ne 0 ]; then
log "UYARI: Repository integrity check basarisiz. Backup devam ediyor..."
fi
# --- Ana Yedekleme ---
log "Yedekleme basliyor: $BACKUP_DIRS"
restic --repo "$REPO"
--password-file "$PASSWORD_FILE"
backup $BACKUP_DIRS
$EXCLUDES
$TAGS
--verbose
>> "$LOG_FILE" 2>&1
BACKUP_STATUS=$?
if [ $BACKUP_STATUS -ne 0 ]; then
log "HATA: Yedekleme basarisiz! Cikis kodu: $BACKUP_STATUS"
send_alert "Yedekleme başarısız oldu. Log: $LOG_FILE"
exit 1
fi
log "Yedekleme basariyla tamamlandi."
# --- Eski Snapshot'lari Temizle (Rotasyon) ---
log "Snapshot rotasyonu basliyor..."
restic --repo "$REPO"
--password-file "$PASSWORD_FILE"
forget
--keep-daily 7
--keep-weekly 4
--keep-monthly 6
--keep-yearly 2
--prune
>> "$LOG_FILE" 2>&1
log "Rotasyon tamamlandi."
# --- Eski Log Dosyalarini Temizle ---
find /var/log/restic/ -name "*.log" -mtime +30 -delete
log "=== Backup islemi tamamlandi ==="
exit 0
Bu script’i çalıştırılabilir yapın:
chmod +x /usr/local/bin/restic-backup.sh
MySQL bağlantı bilgilerini güvenli tutmak için:
# /etc/restic/mysql.cnf
[mysqldump]
user=backup_user
password=guclu-sifre
host=localhost
chmod 600 /etc/restic/mysql.cnf
Rotasyon Politikası: forget ve prune
Restic’te rotasyon iki adımda gerçekleşir:
forget: Hangi snapshot’ların silineceğine karar verir, işaretler.
prune: İşaretlenmiş snapshot’lara ait ve artık hiçbir snapshot tarafından referans edilmeyen veri bloklarını repository’den fiziksel olarak siler.
--prune flag’ini forget komutuyla birlikte kullanmak her ikisini de tek seferde yapar.
Rotasyon Parametreleri
- –keep-last n: Son n snapshot’ı tut
- –keep-hourly n: Her saatten son n tane tut
- –keep-daily n: Her günden son n tane tut
- –keep-weekly n: Her haftadan son n tane tut
- –keep-monthly n: Her aydan son n tane tut
- –keep-yearly n: Her yıldan son n tane tut
- –keep-tag tag: Belirli etiketlere sahip snapshot’ları her zaman koru
- –keep-within 30d: Son 30 gün içindeki tüm snapshot’ları koru
- –group-by host,tags: Rotasyonu gruplar halinde uygula
Gerçek Dünya Rotasyon Örneği
Kurumsal bir ortam için tipik bir rotasyon politikası:
restic --repo "$REPO"
--password-file "$PASSWORD_FILE"
forget
--keep-daily 7
--keep-weekly 4
--keep-monthly 12
--keep-yearly 3
--keep-tag "critical"
--group-by "host,tags"
--prune
--verbose
Bu politikayla:
- Son 7 günün her günü korunur
- Son 4 haftanın her haftasından birer snapshot korunur
- Son 12 ayın her ayından birer snapshot korunur
- Son 3 yılın her yılından birer snapshot korunur
- “critical” etiketiyle işaretlenmiş snapshot’lar hiç silinmez
--verbose flag’i hangi snapshot’ların tutulduğunu, hangilerinin silindiini gösterir. İlk kez çalıştırmadan önce –dry-run` ile test etmenizi şiddetle tavsiye ederim:
restic --repo "$REPO"
--password-file "$PASSWORD_FILE"
forget
--keep-daily 7
--keep-weekly 4
--keep-monthly 12
--prune
--dry-run
Cron ile Otomatikleştirme
Script hazır, rotasyon politikası belirlendi. Şimdi bunları zamana bağlayalım.
crontab -e
# Restic Yedekleme - Her gece 02:30'da
30 2 * * * /usr/local/bin/restic-backup.sh >> /var/log/restic/cron.log 2>&1
# Haftalık integrity check - Pazar 04:00'te
0 4 * * 0 restic --repo sftp:backup-server:/opt/restic-repos/webserver
--password-file /etc/restic/password.txt
check >> /var/log/restic/integrity.log 2>&1
Systemd timer kullanmayı tercih edenler için:
# /etc/systemd/system/restic-backup.service
[Unit]
Description=Restic Backup Service
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/restic-backup.sh
User=root
Environment="RESTIC_PASSWORD_FILE=/etc/restic/password.txt"
[Install]
WantedBy=multi-user.target
# /etc/systemd/system/restic-backup.timer
[Unit]
Description=Restic Backup Timer
Requires=restic-backup.service
[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true
[Install]
WantedBy=timers.target
systemctl daemon-reload
systemctl enable --now restic-backup.timer
systemctl list-timers | grep restic
Geri Yükleme Senaryoları
Yedekleme almak kolaydır, asıl soru şudur: Geri yükleme ne kadar hızlı ve ne kadar güvenilir?
Belirli Bir Snapshot’tan Geri Yükleme
# Önce snapshot'ları listele
restic --repo sftp:backup-server:/opt/restic-repos/webserver
--password-file /etc/restic/password.txt
snapshots
# Belirli snapshot'tan geri yükle
restic --repo sftp:backup-server:/opt/restic-repos/webserver
--password-file /etc/restic/password.txt
restore abc12345
--target /tmp/restore-test
Belirli Bir Dosyayı Geri Yükleme
Tüm sistemi geri yüklemek yerine sadece silinen bir dosyayı kurtarmak istediğinizde:
restic --repo sftp:backup-server:/opt/restic-repos/webserver
--password-file /etc/restic/password.txt
restore latest
--target /tmp/restore
--include "/var/www/html/wp-config.php"
Snapshot’ları Mount Ederek Göz Atma
Bu özellik gerçekten harika. Snapshot’ı bir dizine mount ederek içinde gezebilirsiniz:
mkdir /mnt/restic-browse
restic --repo sftp:backup-server:/opt/restic-repos/webserver
--password-file /etc/restic/password.txt
mount /mnt/restic-browse
# Başka bir terminalde:
ls /mnt/restic-browse/snapshots/
ls /mnt/restic-browse/snapshots/latest/var/www/
# İşiniz bitince:
umount /mnt/restic-browse
Repository Bakımı ve Sağlık Kontrolü
Yedekleme alıyorsunuz ama repository bozuksa ne işe yarar? Düzenli sağlık kontrolü şart.
# Hızlı kontrol (metadata)
restic --repo "$REPO" --password-file "$PASSWORD_FILE" check
# Derinlemeli kontrol (veri bloklarının %10'unu okur)
restic --repo "$REPO" --password-file "$PASSWORD_FILE" check --read-data-subset=10%
# Tüm veriyi kontrol et (büyük repo'larda çok uzun sürer)
restic --repo "$REPO" --password-file "$PASSWORD_FILE" check --read-data
Repository büyüdükçe prune sonrası oluşan gereksiz dosyaları temizlemek için:
restic --repo "$REPO" --password-file "$PASSWORD_FILE" rebuild-index
Birden Fazla Hedefe Yedekleme
Kritik sistemler için tek hedef yetmez. 3-2-1 kuralı: 3 kopya, 2 farklı medya, 1 offsite.
#!/bin/bash
# Aynı veriyi hem yerel NAS'a hem uzak S3'e yedekle
BACKUP_DIRS="/var/www /etc /opt/db-dumps"
EXCLUDES="--exclude=*.tmp --exclude=*.log"
PASSWORD_FILE="/etc/restic/password.txt"
# Hedef 1: Yerel NAS
restic --repo sftp:nas-server:/backups/webserver
--password-file "$PASSWORD_FILE"
backup $BACKUP_DIRS $EXCLUDES --tag local
# Hedef 2: Uzak S3
export AWS_ACCESS_KEY_ID="key"
export AWS_SECRET_ACCESS_KEY="secret"
restic --repo s3:s3.amazonaws.com/my-bucket/webserver
--password-file "$PASSWORD_FILE"
backup $BACKUP_DIRS $EXCLUDES --tag offsite
echo "Her iki hedefe yedekleme tamamlandi."
Rclone Entegrasyonu ile Genişletilmiş Backend Desteği
Restic’in doğrudan desteklemediği servisleri kullanmak istediğinizde Rclone devreye girer. Google Drive, OneDrive, Dropbox veya onlarca başka servis için Rclone’u backend olarak kullanabilirsiniz.
# Rclone kurulu ve konfigüre edilmiş olmalı
# rclone config ile gdrive remote'u oluşturun
restic --repo rclone:gdrive:restic-backups/webserver
--password-file /etc/restic/password.txt
init
restic --repo rclone:gdrive:restic-backups/webserver
--password-file /etc/restic/password.txt
backup /var/www /etc
Rclone backend’i kullanırken -o rclone.connections=5 parametresiyle paralel bağlantı sayısını artırabilirsiniz:
restic --repo rclone:gdrive:restic-backups/webserver
--password-file /etc/restic/password.txt
-o rclone.connections=5
backup /var/www
Performans İpuçları
Büyük veri setlerinde yedekleme süresini kısaltmak için birkaç pratik öneri:
- –limit-upload ve –limit-download: Bant genişliği sınırlaması için. Gündüz saatlerinde backup çalışıyorsa ağı boğmamak kritik önemde.
restic backup --limit-upload 50000 /var/www # 50 MB/s limit
- GOMAXPROCS: Restic Go ile yazıldığı için çoklu CPU kullanır. Yüksek çekirdek sayılı sistemlerde bu environment variable ile çekirdek sayısını ayarlayabilirsiniz.
- Exclude pattern’larını iyi belirleyin: Cache dizinleri, geçici dosyalar, log dosyaları yedeklemeye alınmamalı. Her gereksiz dosya deduplication’a rağmen metadata overhead yaratır.
- –files-from ile büyük listeleri yönetin: Yedeklenecek dizin listesi uzunsa bir dosyaya yazın:
echo "/var/www" > /etc/restic/backup-paths.txt
echo "/etc" >> /etc/restic/backup-paths.txt
echo "/opt/db-dumps" >> /etc/restic/backup-paths.txt
restic backup --files-from /etc/restic/backup-paths.txt
--password-file /etc/restic/password.txt
--repo "$REPO"
Sonuç
Restic, modern sysadmin araç kutusunda olması gereken bir yazılım. Kurulumu basit, konfigürasyonu anlaşılır ve en önemlisi gerçekten çalışıyor. Deduplication sayesinde disk kullanımı minimumda kalırken şifreleme özelliği uzak depolama güvenliğini garanti altına alıyor.
Bu yazıda anlattıklarımı özetlemek gerekirse: Repository kurulumu ve parola yönetimini doğru yapın, production’a geçmeden önce --dry-run ile rotasyon politikanızı test edin, geri yüklemeyi düzenli aralıklarla test edin (yedekleme almak kadar önemli), ve check komutunu haftalık cron’a ekleyin.
En sık yapılan hata şu: Yedekleme çalışıyor diye varsaymak, aylarca test etmemek, sonra gerçekten bir şeye ihtiyaç duyduğunda repository’nin bozuk olduğunu ya da parolayı kayıp ettiğini fark etmek. Bunu yaşamamak için bu yazıdaki script’i kurun, bir hafta çalıştırın, ardından test sunucusunda geri yükleme yapın. Ancak o zaman gerçekten yedeklemeniz var demektir.
