Hướng dẫn backup tự động VPS lên S3 với Restic

Bạn đã từng mất dữ liệu VPS vì ổ cứng chết, lỗi update hay xóa nhầm file? Restic là công cụ backup mã nguồn mở, nhanh, mã hóa mạnh, hỗ trợ nhiều backend lưu trữ, phổ biến nhất là object storage S3. Bài này hướng dẫn bạn thiết lập backup tự động toàn bộ thư mục quan trọng (cấu hình, database, code) từ VPS Ubuntu 24.04 lên S3, kèm cơ chế tự động xóa snapshot cũ và kiểm tra tính toàn vẹn.
Yêu cầu trước khi bắt đầu
- Một VPS chạy Ubuntu 24.04 LTS (có thể dùng VPS Linux của thueVPS với NVMe, root full quyền).
- User
sudo(không dùng root trực tiếp). - Tài khoản object storage S3: AWS S3, DigitalOcean Spaces, MinIO, Backblaze B2... hoặc bất kỳ dịch vụ nào hỗ trợ S3 API. Bài này dùng AWS S3 bucket.
- Access Key + Secret Key của S3.
- Đã mở port 443 (S3 API) và port 22 (SSH) trên firewall của VPS.
Vì sao nên dùng Restic cho backup VPS?
Restic không phải là công cụ backup đơn giản copy toàn bộ file mỗi lần. Nó sử dụng cơ chế deduplication và snapshot gia tăng. Nghĩa là lần đầu backup toàn bộ dung lượng, các lần sau chỉ ghi phần dữ liệu thay đổi. Điều này tiết kiệm rất nhiều băng thông và dung lượng lưu trữ S3. Toàn bộ dữ liệu được mã hóa AES-GCM trước khi rời khỏi VPS, chỉ bạn mới có khóa giải mã. Không nhà cung cấp S3 nào (kể cả AWS) có thể đọc được dữ liệu bạn backup.
Khác với rsync hay tar, Restic quản lý nhiều snapshot theo thời gian, cho phép bạn giữ lịch sử backup hàng ngày trong 30 ngày, hàng tuần 3 tháng... và tự động dọn dẹp snapshot cũ bằng chính sách forget.
Bước 1 - Cài đặt Restic và khởi tạo repository S3
1.1. Cài đặt Restic
Restic có sẵn trong repository Ubuntu mặc định (phiên bản 0.16.4 trở lên cho Ubuntu 24.04).
sudo apt update
sudo apt install restic -y
Kiểm tra phiên bản đã cài:
restic version
# Output: restic 0.16.4 compiled with go1.22.2 on linux/amd64
1.2. Khởi tạo repository S3
Bạn cần tạo một bucket S3 (ví dụ: backup-vps-example) và lấy Access Key + Secret Key. Cách tạo bucket không nằm trong phạm vi bài này, bạn có thể tham khảo tài liệu của nhà cung cấp S3 (AWS Console, DigitalOcean Control Panel...).
Đặt biến môi trường để tránh lộ key trong bash history:
export AWS_ACCESS_KEY_ID="AKIAIOSFODNN7EXAMPLE"
export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
export RESTIC_REPOSITORY="s3:s3.ap-southeast-1.amazonaws.com/backup-vps-example"
export RESTIC_PASSWORD="MatKhauBackupThatManh_2024!"
Giải thích: RESTIC_REPOSITORY là URL bucket S3, trong đó s3.ap-southeast-1 là endpoint region của AWS (nếu dùng DigitalOcean Spaces: s3:sgp1.digitaloceanspaces.com/bucket-name). RESTIC_PASSWORD là mật khẩu mã hóa cho toàn bộ repository, bạn phải nhớ nó.
Khởi tạo repository:
restic init
Nếu thành công, output: created restic repository ... at s3:...
Lưu ý: Lệnh này chỉ chạy đúng 1 lần. Nếu chạy lại trên cùng bucket, nó sẽ báo lỗi repository already exists.
1.3. Backup thủ nghiệm lần đầu
Tạo backup thử cho thư mục /etc (cấu hình toàn bộ hệ thống):
restic --verbose backup /etc
Output sẽ hiện số file, dung lượng, thời gian. Kiểm tra danh sách snapshot:
restic snapshots
# Output:
# ID Time Host Tags Paths
# f3b2b1a2 ... ubuntu-vps /etc
Bạn cũng có thể backup thư mục /var/www (code web), /home, /root, thậm chí toàn bộ / trừ các thư mục ảo. Xem thêm về cách exclude trong script sau.
Bước 2 - Xây dựng script backup toàn diện
Script này sẽ backup các thư mục quan trọng, sql database và tự động dọn snapshot cũ. Tạo file /usr/local/bin/backup-vps.sh:
sudo nano /usr/local/bin/backup-vps.sh
Nội dung script:
#!/bin/bash
# === CONFIGURATION ===
export AWS_ACCESS_KEY_ID="AKIAIOSFODNN7EXAMPLE"
export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
export RESTIC_REPOSITORY="s3:s3.ap-southeast-1.amazonaws.com/backup-vps-example"
export RESTIC_PASSWORD="MatKhauBackupThatManh_2024!"
LOG_FILE="/var/log/restic-backup.log"
BACKUP_PATHS="/etc /var/www /home /root /opt"
# === DATABASE DUMP (MySQL example) ===
if command -v mysqldump &> /dev/null; then
mkdir -p /tmp/backup-db
mysqldump --all-databases --single-transaction --quick > /tmp/backup-db/all-databases.sql 2>/dev/null
BACKUP_PATHS="$BACKUP_PATHS /tmp/backup-db"
fi
# === EXCLUDE ===
# Exclude cache, logs, tmp, proc, sys, dev, run
EXCLUDE="--exclude-caches --exclude='*.log' --exclude='/tmp/*' --exclude='/var/log/*' --exclude='/proc/*' --exclude='/sys/*' --exclude='/dev/*' --exclude='/run/*'"
# === BACKUP ===
echo "=== $(date) ===" >> "$LOG_FILE"
restic backup $EXCLUDE $BACKUP_PATHS >> "$LOG_FILE" 2>&1
# === FORGET ===
# Keep: last 7 daily, 4 weekly, 6 monthly, and 2 yearly
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --keep-yearly 2 --prune >> "$LOG_FILE" 2>&1
# === CHECK INTEGRITY (weekly on Sunday) ===
if [ "$(date +%u)" = "7" ]; then
restic check --read-data-subset=1/10 >> "$LOG_FILE" 2>&1
fi
# === CLEANUP ===
rm -rf /tmp/backup-db
Giải thích script:
BACKUP_PATHS: danh sách thư mục backup, mặc định gồm/etc,/var/www,/home,/root,/opt. Thêm hoặc bớt tùy nhu cầu.- Phần database dump: dùng
mysqldumpnếu có, xuất toàn bộ database ra file SQL, backup file đó. Tương tự, bạn có thể thêm PostgreSQL dump vớipg_dumpall. --exclude-cachesvà--exclude='*.log'bỏ qua cache và log không cần backup. Bạn nên thêm exclude riêng cho thư mục như/var/lib/dockernếu không cần backup container layer.- Lệnh
restic forget: xóa các snapshot cũ theo chính sách: giữ 7 bản hàng ngày, 4 hàng tuần, 6 hàng tháng, 2 hàng năm.--prunexóa hẳn dữ liệu khỏi S3 sau khi forget. - Lệnh
restic check: kiểm tra tính toàn vẹn repository, chạy mỗi Chủ nhật.--read-data-subset=1/10kiểm tra 10% dữ liệu ngẫu nhiên, vừa đủ để phát hiện lỗi sớm mà không tốn quá nhiều băng thông.
Phân quyền thực thi cho script:
sudo chmod +x /usr/local/bin/backup-vps.sh
Kiểm tra script chạy thử (không có database dump nếu chưa cài MySQL):
sudo /usr/local/bin/backup-vps.sh
cat /var/log/restic-backup.log
Nếu không có lỗi, bạn sẽ thấy log ghi nhận backup thành công.
Bước 3 - Tự động hóa backup với systemd timer
Dùng cron thì được, nhưng systemd timer cho phép kiểm soát tốt hơn (log, dependency, resource limit). Tạo 2 file: service và timer.
3.1. Tạo file service
File /etc/systemd/system/restic-backup.service:
sudo nano /etc/systemd/system/restic-backup.service
Nội dung:
[Unit]
Description=Restic backup to S3
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup-vps.sh
StandardOutput=journal
StandardError=journal
User=root
Group=root
Giải thích: After=network-online.target đảm bảo mạng đã sẵn sàng trước khi backup.
3.2. Tạo file timer
File /etc/systemd/system/restic-backup.timer:
sudo nano /etc/systemd/system/restic-backup.timer
[Unit]
Description=Run Restic backup daily at 3 AM
[Timer]
OnCalendar=daily
Persistent=true
RandomizedDelaySec=1800
[Install]
WantedBy=timers.target
Giải thích:
OnCalendar=daily: chạy mỗi ngày 1 lần, mặc định là 00:00 theo hệ thống (UTC). Có thể đặt cụ thể:OnCalendar=*-*-* 03:00:00(chạy lúc 3h sáng hàng ngày).Persistent=true: nếu VPS tắt vào giờ đó, khi khởi động lại sẽ chạy backup ngay.RandomizedDelaySec=1800: trì hoãn ngẫu nhiên tối đa 30 phút để tránh tất cả VPS cùng đổ vào S3 một lúc.
3.3. Kích hoạt timer
sudo systemctl daemon-reload
sudo systemctl enable restic-backup.timer
sudo systemctl start restic-backup.timer
Kiểm tra trạng thái timer:
sudo systemctl status restic-backup.timer
# Output: Active: active (waiting) ...
# Đã chạy lần nào chưa:
sudo systemctl list-timers restic-backup.timer
Để chạy service thủ công ngay lập tức (không cần đợi timer):
sudo systemctl start restic-backup.service
Bước 4 - Khôi phục dữ liệu
Restic có lệnh phục hồi cực kỳ linh hoạt. Bạn không cần cài sẵn gì trên máy đích, chỉ cần Restic và key.
Liệt kê snapshot để tìm bản cần restore:
restic snapshots
Restore toàn bộ snapshot gần nhất vào thư mục /restore-test:
restic restore latest --target /restore-test
Restore toàn bộ backup của ngày cụ thể (lấy ID từ lệnh trên):
restic restore f3b2b1a2 --target /restore-test
Restore chỉ 1 file hoặc 1 thư mục, ví dụ file /etc/nginx/nginx.conf:
restic restore latest --path /etc/nginx/nginx.conf --target /restore
Sau khi restore, các file sẽ nằm dưới /restore/etc/nginx/nginx.conf (cấu trúc thư mục giữ nguyên đường dẫn gốc). Bạn chỉ cần copy lại vào vị trí thật.
Xử lý lỗi thường gặp
Lỗi "s3: Access Denied"
Nguyên nhân: Access Key hoặc Secret Key sai, hoặc bucket không tồn tại. Kiểm tra:
export | grep AWS_ACCESS
aws s3 ls s3://bucket-name --profile test (nếu có AWS CLI)
Nếu dùng S3 ngoài AWS (MinIO, DigitalOcean), endpoint URL thường khác: s3:https://sgp1.digitaloceanspaces.com/bucket.
Lỗi "repository already initialized"
Bạn đã chạy restic init trên cùng bucket rồi → không cần chạy nữa. Nếu muốn reset, xóa bucket và tạo mới.
Lỗi "signal: killed" khi backup
VPS hết RAM. Restic mặc định dùng 1 thread, nhưng nếu VPS có 1GB RAM và backup nhiều file lớn, nó có thể bị OOM. Thêm flag --b2 2 (2 threads) hoặc giảm --read-threads. Hoặc nâng cấp lên thuê VPS 2GB RAM trở lên.
Kiểm tra log nếu script không chạy
Xem log của systemd service:
sudo journalctl -u restic-backup.service -n 50 --no-pager
Câu hỏi thường gặp
Restic có miễn phí không?
Có, Restic là phần mềm mã nguồn mở hoàn toàn miễn phí (giấy phép BSD-2). Bạn chỉ trả phí cho dung lượng lưu trữ S3 và băng thùng. AWS S3 có mức giá khoảng $0.023/GB/tháng cho dung lượng ổ đĩa.
Làm sao để backup cơ sở dữ liệu PostgreSQL thay vì MySQL?
Thay dòng mysqldump trong script bằng: su - postgres -c "pg_dumpall" > /tmp/backup-db/all-databases.sql. Nên gộp chung với MySQL logic nếu server chạy cả 2.
Tôi có thể dùng 1 repository S3 cho nhiều VPS không?
Có, nhưng mỗi VPS nên tạo 1 path riêng trong cùng bucket để tránh nhầm lẫn. Ví dụ: s3:.../backup-vps-web và s3:.../backup-vps-db. Hoặc dùng tag: restic backup --tag web.
Tôi muốn backup đến nhiều nơi cùng lúc (S3 + local)?
Restic hỗ trợ copy giữa các repository với lệnh restic copy. Có thể chạy script backup 2 lần với 2 RESTIC_REPOSITORY khác nhau. Hoặc dùng rclone để sync repository S3 sang đám mây khác.
Restic có backup được Docker volumes không?
Có, bạn có thể mount volume Docker vào host (hoặc root) và backup thư mục tương ứng. Ví dụ: nếu volume tên mydata mount ở /var/lib/docker/volumes/mydata/_data. Backup thư mục đó như thông thường. Hoặc dùng restic backup /var/lib/docker/volumes để backup toàn bộ volume.
Làm thế nào để đảm bảo backup không bị gián đoạn khi VPS nhỏ?
Giảm độ ưu tiên CPU cho Restic bằng lệnh nice -n 19 restic backup ... trong script. Đặt MemoryMax=512M trong file service để giới hạn RAM. Nếu VPS quá nhỏ, hãy cân nhắc nâng cấp lên thuê VPS Linux có 2GB RAM hoặc dùng VPS SSD NVMe cho I/O mạnh.
Bài viết liên quan
- Tối ưu Linux và NVMe cho workload I/O cao trên VPS
- Cấu hình Logrotate quản lý log trên VPS Ubuntu
- Gửi cảnh báo hệ thống VPS qua Telegram bot bằng script bash
- Benchmark hiệu năng VPS với FIO, sysbench, iperf3


