Yerel ve Uzak Yedekleme Kurulumu: Restic Rehberi
Yedekleme konusuna gelince, çoğu sysadmin iki uç noktadan birinde takılıp kalıyor: ya hiç yedek almıyor ya da yedek alıyor ama o yedeklerin çalışıp çalışmadığını test etmiyor. Restic, bu iki problemi de çözmek için tasarlanmış modern bir yedekleme aracı. Hızlı, şifreli, deduplikasyon destekli ve neredeyse her depolama backend’iyle çalışıyor. Bu yazıda sıfırdan bir Restic kurulumu yapacak, hem yerel hem uzak yedekleme senaryolarını ele alacak ve işi otomatize edecek production-ready bir yapı kuracağız.
Restic Nedir ve Neden Kullanmalısınız
Klasik tar+gzip yedeklerinin aksine Restic, içerik adreslemeli depolama (content-addressable storage) kullanıyor. Yani her dosya bloklara ayrılıyor, SHA-256 ile hashleniyor ve sadece değişen bloklar yedekleniyor. Bu sayede hem disk alanından tasarruf ediyorsunuz hem de backup süresi dramatik biçimde kısalıyor.
Restic’in öne çıkan özellikleri:
- Şifreleme: AES-256-CTR ile her şey client-side şifreleniyor, depolama tarafı hiçbir zaman düz veri görmüyor
- Deduplikasyon: Aynı veri birden fazla snapshot’ta varsa tek kez saklanıyor
- Bütünlük doğrulama:
restic checkkomutuyla istediğiniz zaman repo bütünlüğünü test edebiliyorsunuz - Cross-platform: Linux, macOS, Windows hepsinde çalışıyor
- Birden fazla backend: Local, SFTP, S3, Azure Blob, Google Cloud, Backblaze B2 ve Rclone üzerinden onlarca servis
Kurulum
Restic çoğu Linux dağıtımının resmi repo’larında mevcut, ancak bu repo’lardaki sürümler genellikle geride kalıyor. Ben her zaman GitHub releases’ten binary indirmeyi tercih ediyorum.
# En son sürümü GitHub'dan indir
wget https://github.com/restic/restic/releases/download/v0.16.4/restic_0.16.4_linux_amd64.bz2
# Sıkıştırmayı aç
bunzip2 restic_0.16.4_linux_amd64.bz2
# Çalıştırılabilir yap ve path'e taşı
chmod +x restic_0.16.4_linux_amd64
sudo mv restic_0.16.4_linux_amd64 /usr/local/bin/restic
# Versiyonu doğrula
restic version
Debian/Ubuntu kullanıcıları için apt ile de kurabilirsiniz:
sudo apt update && sudo apt install restic -y
# Kurulumu doğrula
restic self-update # Binary'yi en son versiyona günceller
Repository Kavramı
Restic’te her şey repository (kısaca repo) etrafında dönüyor. Repo, tüm snapshot’larınızın şifreli biçimde saklandığı dizin veya uzak konumdur. Bir repo’yu kullanmaya başlamadan önce init komutuyla başlatmanız gerekiyor.
Yerel Repository Oluşturma
# Yerel bir repo başlat
restic init --repo /mnt/backup/my-repo
# Komut çalıştığında şifre belirlemenizi isteyecek
# Enter password for new repository:
# Enter password again:
# created restic repository abc123def at /mnt/backup/my-repo
Şifreyi girdikten sonra Restic size bir repository ID verecek. Bu ID’yi bir yere not edin, ilerleyen dönemlerde sorun yaşadığınızda işe yarıyor.
Önemli not: Şifreyi kaybederseniz yedeklerinize erişemezsiniz. Bu şifreyi mutlaka güvenli bir şekilde (KeePass, Bitwarden, ya da en azından başka bir lokasyonda şifreli text dosyası) saklayın.
Çevre Değişkenleriyle Kolaylık
Her komuta --repo ve --password-file parametresi geçmek can sıkıcı hale geliyor. Bunun yerine çevre değişkenlerini kullanabiliriz.
# /etc/restic/env adında bir dosya oluşturalım
sudo mkdir -p /etc/restic
sudo nano /etc/restic/env
# Dosya içeriği:
export RESTIC_REPOSITORY="/mnt/backup/my-repo"
export RESTIC_PASSWORD_FILE="/etc/restic/password"
# Şifreyi ayrı dosyaya yaz
echo "cok-gizli-sifre-buraya" | sudo tee /etc/restic/password
sudo chmod 600 /etc/restic/password
sudo chmod 600 /etc/restic/env
# Kullanmak için:
source /etc/restic/env
restic snapshots # Artık --repo parametresi gerekmez
İlk Yedeklemeyi Almak
Basit bir backup komutuyla başlayalım:
source /etc/restic/env
# Web sunucusu config ve veri dizinlerini yedekle
restic backup
/etc/nginx
/var/www/html
/home
--tag "production"
--tag "webserver"
--exclude "/home/*/.cache"
--exclude "/home/*/.local/share/Trash"
--exclude "*.tmp"
--exclude "*.log"
Çıktıda şöyle bir şey görmeniz gerekiyor:
repository abc123def opened (version 2, compression level auto)
no parent snapshot found, will read all files
Files: 1234 new, 0 changed, 0 unmodified
Dirs: 89 new, 0 changed, 0 unmodified
Added to the repository: 245.123 MiB (198.456 MiB stored)
snapshot 7f8e9a2b saved
Buradaki “stored” değeri deduplikasyon sonrası gerçek disk kullanımını gösteriyor. İkinci backup’ta değişen az dosya varsa bu fark çok daha belirgin olacak.
Snapshot Listesini Görüntüleme
restic snapshots
# Daha detaylı çıktı için
restic snapshots --verbose
# Belirli bir tag'e göre filtrele
restic snapshots --tag "production"
Uzak Yedekleme: SFTP Backend
Gerçek dünya senaryosunda sadece yerel yedek yeterli değil. 3-2-1 kuralı gereği en az 3 kopya, 2 farklı medya, 1 off-site olmalı. SFTP backend ile uzak bir sunucuya yedekleme yapabiliriz.
Önce SSH key-based authentication kuralım:
# Yedekleme için ayrı bir SSH key oluştur
ssh-keygen -t ed25519 -f /root/.ssh/restic_backup -N "" -C "restic-backup-$(hostname)"
# Public key'i uzak sunucuya kopyala
ssh-copy-id -i /root/.ssh/restic_backup.pub [email protected]
# Bağlantıyı test et
ssh -i /root/.ssh/restic_backup [email protected] "echo Baglanti basarili"
Şimdi uzak sunucuda SFTP repo başlatalım:
# SFTP reposunu init et
restic -r sftp:[email protected]:/backups/server1-repo init
# Ya da env değişkeniyle
export RESTIC_REPOSITORY="sftp:[email protected]:/backups/server1-repo"
export RESTIC_PASSWORD_FILE="/etc/restic/password"
restic init
SSH config dosyasını düzenleyerek SFTP bağlantısını daha temiz hale getirebiliriz:
# /root/.ssh/config dosyasına ekle
Host backup-server
HostName 192.168.1.100
User backup-user
IdentityFile /root/.ssh/restic_backup
Port 22
ServerAliveInterval 60
ServerAliveCountMax 3
# Artık bu şekilde kullanabilirsiniz
restic -r sftp:backup-server:/backups/server1-repo snapshots
Uzak Yedekleme: Backblaze B2 ile Bulut Yedeklemesi
SFTP iyi bir seçenek ama aynı ağdaki sunucu gerçek anlamda off-site değil. Backblaze B2 uygun fiyatlı (GB başına $0.006/ay) ve Restic ile native entegrasyonu olan bir bulut depolama servisi.
# B2 credentials'larını env'e ekle
export RESTIC_REPOSITORY="b2:my-bucket-name:server1-backup"
export B2_ACCOUNT_ID="your-b2-account-id"
export B2_ACCOUNT_KEY="your-b2-application-key"
export RESTIC_PASSWORD_FILE="/etc/restic/password"
# Repo'yu başlat
restic init
# İlk backup
restic backup /etc /var/www /home
--tag "$(hostname)"
--tag "cloud-backup"
Otomatik Yedekleme: Systemd Timer ile Production Kurulumu
Cron da çalışır ama systemd timer daha iyi logging, dependency yönetimi ve hata yönetimi sunuyor. Ben production’da her zaman systemd timer tercih ediyorum.
Önce bir backup script yazalım:
sudo nano /usr/local/bin/restic-backup.sh
#!/bin/bash
set -euo pipefail
# Logging
LOG_FILE="/var/log/restic/backup.log"
mkdir -p /var/log/restic
exec > >(tee -a "$LOG_FILE") 2>&1
echo "=== Backup basliyor: $(date '+%Y-%m-%d %H:%M:%S') ==="
# Environment
source /etc/restic/env
# Yerel repo backup
echo "[1/2] Yerel repo backup..."
restic backup
/etc
/var/www
/home
--tag "$(hostname)"
--tag "local"
--tag "$(date +%Y-%m)"
--exclude "/home/*/.cache"
--exclude "/home/*/.mozilla"
--exclude "/home/*/.config/google-chrome"
--exclude "*.pyc"
--exclude "__pycache__"
--one-file-system
--verbose
# Uzak repo backup (B2)
echo "[2/2] Bulut backup..."
export RESTIC_REPOSITORY="b2:my-bucket:$(hostname)-backup"
export B2_ACCOUNT_ID="$(cat /etc/restic/b2_account_id)"
export B2_ACCOUNT_KEY="$(cat /etc/restic/b2_account_key)"
restic backup
/etc
/var/www
/home
--tag "$(hostname)"
--tag "cloud"
--exclude "/home/*/.cache"
--one-file-system
--verbose
echo "=== Backup tamamlandi: $(date '+%Y-%m-%d %H:%M:%S') ==="
sudo chmod +x /usr/local/bin/restic-backup.sh
Systemd service dosyası:
sudo nano /etc/systemd/system/restic-backup.service
[Unit]
Description=Restic Backup Service
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
User=root
ExecStart=/usr/local/bin/restic-backup.sh
StandardOutput=journal
StandardError=journal
SyslogIdentifier=restic-backup
# Timeout: 4 saat
TimeoutStartSec=14400
[Install]
WantedBy=multi-user.target
Systemd timer dosyası:
sudo nano /etc/systemd/system/restic-backup.timer
[Unit]
Description=Restic Backup Timer
Requires=restic-backup.service
[Timer]
# Her gece 02:30'da çalış
OnCalendar=*-*-* 02:30:00
RandomizedDelaySec=900
Persistent=true
[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable restic-backup.timer
sudo systemctl start restic-backup.timer
# Timer durumunu kontrol et
sudo systemctl status restic-backup.timer
sudo systemctl list-timers restic-backup.timer
Retention Policy: Eski Yedekleri Temizleme
Sonsuz yedek tutmak ne pratikte ne de maddi açıdan sürdürülebilir. Restic’in forget komutu buna mükemmel bir çözüm sunuyor.
source /etc/restic/env
# Retention policy uygula
restic forget
--keep-last 5
--keep-daily 7
--keep-weekly 4
--keep-monthly 12
--keep-yearly 3
--tag "production"
--prune
# --dry-run ile önce neyin silineceğini gör
restic forget
--keep-last 5
--keep-daily 7
--keep-weekly 4
--keep-monthly 12
--prune
--dry-run
Bu policy şunu söylüyor:
- –keep-last 5: Son 5 snapshot’ı her koşulda tut
- –keep-daily 7: Son 7 günün günlük snapshot’larını tut
- –keep-weekly 4: Son 4 haftanın haftalık snapshot’larını tut
- –keep-monthly 12: Son 12 ayın aylık snapshot’larını tut
- –keep-yearly 3: Son 3 yılın yıllık snapshot’larını tut
- –prune: Referanssız kalan blokları fiziksel olarak sil
Veri Doğrulama: En Önemli Adım
Yedekleyen herkes kahramandır, test eden ise gerçek sysadmin. Backup almak işin yarısı, diğer yarısı düzgün çalıştığını doğrulamak.
source /etc/restic/env
# Repository bütünlüğünü kontrol et
restic check
# Daha kapsamlı kontrol (tüm pack dosyalarını oku)
restic check --read-data
# Belirli bir snapshot'tan dosya listesi
restic ls 7f8e9a2b
# Belirli bir dosyayı restore et (test amaçlı)
restic restore 7f8e9a2b
--target /tmp/restic-test
--include /etc/nginx/nginx.conf
# Restore sonrası kontrol
ls -la /tmp/restic-test/etc/nginx/
diff /etc/nginx/nginx.conf /tmp/restic-test/etc/nginx/nginx.conf
# Test dizinini temizle
rm -rf /tmp/restic-test
Aylık doğrulama script’i:
#!/bin/bash
source /etc/restic/env
echo "=== Aylik Backup Dogrulama: $(date) ==="
# Repo check
if restic check; then
echo "BASARILI: Repository butunlugu dogrulandi"
else
echo "HATA: Repository check basarisiz!"
# Buraya e-posta veya Slack bildirimi eklenebilir
exit 1
fi
# En son snapshot'tan rastgele bir dosyayı restore et ve test et
LATEST=$(restic snapshots --json | python3 -c "import sys,json; snaps=json.load(sys.stdin); print(snaps[-1]['id'])")
TEMP_DIR=$(mktemp -d)
restic restore "$LATEST"
--target "$TEMP_DIR"
--include /etc/hostname
if [ -f "$TEMP_DIR/etc/hostname" ]; then
echo "BASARILI: Restore testi gecti - $(cat $TEMP_DIR/etc/hostname)"
else
echo "HATA: Restore testi basarisiz!"
exit 1
fi
rm -rf "$TEMP_DIR"
echo "=== Dogrulama tamamlandi ==="
Veritabanı Yedeklemesi: MySQL/PostgreSQL
Dosya sistemi yedeği alırken veritabanı dosyalarını olduğu gibi kopyalamak tutarsız yedeklere yol açar. Bunun yerine önce dump alıp sonra Restic ile yedekleyin.
#!/bin/bash
source /etc/restic/env
DUMP_DIR="/var/backups/db-dumps"
mkdir -p "$DUMP_DIR"
DATE=$(date +%Y%m%d_%H%M%S)
# MySQL dump
if command -v mysqldump &> /dev/null; then
echo "MySQL dump aliniyor..."
mysqldump
--defaults-file=/etc/mysql/backup.cnf
--all-databases
--single-transaction
--routines
--triggers
| gzip > "$DUMP_DIR/mysql_all_$DATE.sql.gz"
fi
# PostgreSQL dump
if command -v pg_dumpall &> /dev/null; then
echo "PostgreSQL dump aliniyor..."
sudo -u postgres pg_dumpall
| gzip > "$DUMP_DIR/postgres_all_$DATE.sql.gz"
fi
# Eski dump'ları temizle (7 günden eski)
find "$DUMP_DIR" -name "*.sql.gz" -mtime +7 -delete
# Restic ile dump dizinini yedekle
restic backup "$DUMP_DIR"
--tag "database"
--tag "$(hostname)"
echo "Veritabani yedeklemesi tamamlandi"
Sorun Giderme
Zaman zaman karşılaşılan yaygın sorunlar ve çözümleri:
- “repository is already locked” hatası: Başka bir Restic işlemi çökmüş ve kilidi bırakmış olabilir.
restic unlockile kilidi kaldırın, ancak gerçekten başka bir işlem çalışmadığından emin olun.
- SFTP bağlantısı düşüyor: SSH config’e
ServerAliveInterval 60veServerAliveCountMax 3ekleyin. Büyük yedeklemeler için--limit-uploadile bant genişliğini sınırlandırın.
- Backup çok yavaş:
--compression maxyerine--compression autokullanın. Zaten şifreli veri (HTTPS trafiği, JPEG, ZIP) tekrar sıkıştırılamaz.
- Repository check hata veriyor: Önce
restic check --read-data-subset 10%ile kısmi kontrol yapın. Sorun devam ederserestic repairkomutlarını inceleyin.
- Disk doldu:
restic pruneile gereksiz blokları temizleyin. Öncesinderestic statsile repo boyutunu analiz edin.
# Repository istatistiklerini görüntüle
restic stats
# Mode seçenekleriyle daha detaylı
restic stats --mode raw-data
restic stats --mode blobs-per-file
Sonuç
Restic, modern bir yedekleme altyapısı için gereken tüm özellikleri tek bir binary içinde sunuyor. Şifreleme, deduplikasyon, çoklu backend desteği ve bütünlük doğrulama ile hem küçük VPS’lerden hem de büyük kurumsal sunuculardan ciddi bir yedekleme çözümü olarak kullanılabilir.
Bu yazıda kurduğumuz yapıyı özetleyecek olursak: yerel repo ile hızlı erişim sağladık, SFTP veya B2 ile off-site kopya oluşturduk, systemd timer ile otomasyonu kurduk, retention policy ile disk yönetimini hallettik ve en önemlisi doğrulama script’iyle yedeklerin çalıştığını test ettik.
Son olarak şunu söyleyelim: test etmediğiniz yedek, yedek değildir. Ayda bir otomatik restore testini muhakkak çalıştırın. Felaket anında o test sizi kurtaracak, backup log’larındaki yeşil checkmark’lar değil.
