rsync backup ไฟล์บน VPS อัตโนมัติ

ใช้ rsync Backup ไฟล์บน VPS อัตโนมัติ: คู่มือฉบับสมบูรณ์

มิถุนายน 2026 · อ่าน 8 นาที

rsync เป็น tool backup ที่ติดมากับ Linux ทุกเครื่อง ทำงานได้ทั้ง local-to-local, local-to-remote และ remote-to-remote ผ่าน SSH จุดเด่นคือ incremental sync — ส่งเฉพาะไฟล์ที่เปลี่ยนแปลงจริง ไม่ copy ทั้งหมดทุกครั้ง ทำให้ backup เร็วและกิน bandwidth น้อยมาก

คำสั่ง rsync พื้นฐาน

# ติดตั้ง (มักมีอยู่แล้ว)
apt install rsync -y

# Syntax ทั่วไป
rsync [options] source/ destination/

# ตัวเลือกที่ใช้บ่อย
-a   archive mode (recursive + preserve permissions/timestamps)
-v   verbose (แสดงไฟล์ที่กำลัง sync)
-z   compress ระหว่าง transfer
-P   progress bar + resume partial
--delete  ลบไฟล์ปลายทางที่ไม่มีในต้นทางอีกแล้ว
-n / --dry-run  ทดสอบโดยไม่เปลี่ยนแปลงจริง
Trailing slash สำคัญมาก: rsync -a /data/ (มี /) = copy เนื้อหาในโฟลเดอร์ · rsync -a /data (ไม่มี /) = copy โฟลเดอร์ทั้งใบ ความผิดพลาดบ่อยมาก ควร dry-run ก่อนเสมอ

Backup ไฟล์ Local บน VPS เดิม

# Backup /var/www ไปยัง /backup/www
rsync -av --delete /var/www/ /backup/www/

# ทดสอบก่อนด้วย dry-run
rsync -avn --delete /var/www/ /backup/www/

# Backup หลายโฟลเดอร์พร้อมกัน
rsync -av /var/www/ /etc/nginx/ /etc/php/ /backup/

Backup ไปยัง Remote Server ผ่าน SSH

rsync ใช้ SSH ในการส่งข้อมูล ทำให้ทุก transfer ถูกเข้ารหัสอัตโนมัติ:

# Backup จาก VPS → remote server
rsync -avz -e ssh /var/www/ [email protected]:/backup/vps1/www/

# ระบุ SSH port และ key
rsync -avz -e "ssh -p 2222 -i ~/.ssh/backup_key" \
  /var/www/ [email protected]:/backup/vps1/

# Backup ย้อนกลับ: remote → VPS (pull)
rsync -avz [email protected]:/data/ /local/restore/

ตั้งค่า SSH Key สำหรับ Backup อัตโนมัติ

ต้องใช้ SSH Key แทน password เพื่อให้ cron รันได้โดยไม่ต้องพิมพ์ password:

# สร้าง SSH key เฉพาะสำหรับ backup (ไม่ใส่ passphrase)
ssh-keygen -t ed25519 -C "backup@vps1" -f ~/.ssh/backup_key -N ""

# Copy public key ไปยัง backup server
ssh-copy-id -i ~/.ssh/backup_key.pub -p 22 [email protected]

# ทดสอบว่า login ได้โดยไม่ใส่ password
ssh -i ~/.ssh/backup_key [email protected] echo "OK"
จำกัดสิทธิ์ backup key: ใน ~/.ssh/authorized_keys บน backup server ควรใส่ command="rsync --server ...",restrict ก่อน public key เพื่อให้ key นี้ทำได้เฉพาะ rsync เท่านั้น ป้องกันกรณี key รั่ว

สร้าง Backup Script

nano /usr/local/bin/backup.sh
#!/bin/bash
set -euo pipefail

DATE=$(date +%Y-%m-%d)
LOG="/var/log/backup.log"
REMOTE="[email protected]"
KEY="$HOME/.ssh/backup_key"

log() { echo "$(date '+%F %T') $*" | tee -a "$LOG"; }

log "=== Backup started ==="

# Backup web files
rsync -az --delete \
  -e "ssh -i $KEY -o StrictHostKeyChecking=no" \
  /var/www/ "${REMOTE}:/backup/www/" && log "www OK" || log "www FAILED"

# Backup Nginx config
rsync -az --delete \
  -e "ssh -i $KEY -o StrictHostKeyChecking=no" \
  /etc/nginx/ "${REMOTE}:/backup/nginx/" && log "nginx OK" || log "nginx FAILED"

# Backup MySQL (ถ้ามี)
if command -v mysqldump &>/dev/null; then
  mysqldump --all-databases --single-transaction \
    > /tmp/all_dbs_${DATE}.sql
  gzip /tmp/all_dbs_${DATE}.sql
  rsync -az \
    -e "ssh -i $KEY -o StrictHostKeyChecking=no" \
    /tmp/all_dbs_${DATE}.sql.gz "${REMOTE}:/backup/mysql/"
  rm /tmp/all_dbs_${DATE}.sql.gz
  log "mysql OK"
fi

log "=== Backup done ==="
chmod +x /usr/local/bin/backup.sh
# ทดสอบ
/usr/local/bin/backup.sh

ตั้ง cron ให้รันอัตโนมัติ

crontab -e
# Backup ทุกวันตี 2
0 2 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

# Backup ทุกชั่วโมง (web files อย่างเดียว)
0 * * * * rsync -az --delete -e "ssh -i ~/.ssh/backup_key" \
  /var/www/ [email protected]:/backup/www/ >> /var/log/backup.log 2>&1

Incremental Backup ด้วย --link-dest (Snapshot-style)

เทคนิคนี้ใช้ hard link เพื่อทำให้ดูเหมือนมี full backup ทุกวัน แต่กิน disk เฉพาะไฟล์ที่เปลี่ยนแปลงจริง:

#!/bin/bash
DEST="/backup"
DATE=$(date +%Y-%m-%d)
PREV=$(ls -d ${DEST}/[0-9]* 2>/dev/null | sort | tail -1)

rsync -az --delete \
  ${PREV:+--link-dest="$PREV"} \
  /var/www/ "${DEST}/${DATE}/"

# เก็บแค่ 30 วันล่าสุด
find "$DEST" -maxdepth 1 -type d -name '[0-9]*' | \
  sort | head -n -30 | xargs rm -rf

ตรวจสอบ Backup Log

# ดู log ล่าสุด
tail -50 /var/log/backup.log

# ตรวจว่า backup สำเร็จวันนี้
grep "$(date +%F)" /var/log/backup.log | grep "done"

# ขนาดที่ใช้บน remote
ssh [email protected] du -sh /backup/

rsync เป็น tool backup ที่ทรงพลังและไว้ใจได้สำหรับ VPS — ไม่ต้องติดตั้งอะไรเพิ่ม ทำงานผ่าน SSH ที่มีอยู่แล้ว และ incremental sync ช่วยให้ backup รายวันใช้เวลาเพียงไม่กี่วินาทีหลังจาก full sync ครั้งแรก สิ่งสำคัญคือตั้ง alert เมื่อ backup ล้มเหลว และทดสอบ restore เป็นประจำ

ตรวจสอบว่า Backup ทำงานถูกต้อง

# ทดสอบ rsync ด้วย dry-run ก่อนรันจริง
rsync -avzn --delete /var/www/ [email protected]:/backup/www/
# -n = dry-run (ไม่เปลี่ยนแปลงจริง แต่แสดงว่าจะทำอะไร)

# ตรวจสอบว่า backup cron ทำงาน
grep "backup" /var/log/syslog | tail -10

# ดู backup log ล่าสุด
tail -30 /var/log/backup.log

# ตรวจสอบขนาด backup บน remote
ssh [email protected] "du -sh /backup/ && ls -lt /backup/ | head"
ทดสอบ restore เป็นประจำ: ทำ rsync โดยไม่เคย test restore เหมือนไม่มี backup — ลอง restore ไฟล์สักไฟล์จาก backup อย่างน้อยเดือนละครั้งเพื่อยืนยันว่า backup ใช้งานได้จริง

แก้ปัญหาที่พบบ่อย

Error: "Permission denied (publickey)" สำหรับ backup key

Backup SSH key ต้องถูก authorize บน destination server และต้องระบุ path ของ key ให้ถูกต้อง:

# ทดสอบ key โดยตรง
ssh -i ~/.ssh/backup_key -o BatchMode=yes [email protected] echo "OK"
# ถ้า fail — ตรวจสอบว่า public key อยู่ใน authorized_keys บน destination

# ตรวจสอบ permission ของ key
chmod 600 ~/.ssh/backup_key
chmod 644 ~/.ssh/backup_key.pub

# ดู SSH debug
ssh -v -i ~/.ssh/backup_key [email protected]

Error: rsync ลบไฟล์บน destination ที่ไม่ได้อยากลบ (--delete ทำงานผิด)

ปัญหาจาก trailing slash หรือ path ผิด ให้ทำ dry-run ก่อนเสมอ:

# dry-run เสมอก่อน --delete จริง
rsync -avn --delete /var/www/ /backup/www/

# ถ้าเผลอลบไปแล้ว และมี --link-dest backup ให้ restore ได้
ls /backup/
# หา snapshot วันก่อนที่ยังมีไฟล์

Error: "connection timed out" หรือ "Connection refused" ไป backup server

ตรวจสอบ firewall บน destination server ว่าเปิด SSH port ไว้ และ IP ต้นทางไม่ถูก block:

# ทดสอบ SSH ไป destination ก่อน
ssh -p 22 [email protected]

# ถ้า timeout ตรวจ firewall บน destination
# ถ้า connection refused ตรวจว่า SSH daemon รันอยู่

Error: backup สำเร็จแต่ไม่มีไฟล์ใหม่บน destination

อาจเกิดจาก path ผิด หรือ rsync ดู timestamp แล้วคิดว่าไม่มีการเปลี่ยนแปลง:

# ใช้ --checksum แทน timestamp comparison
rsync -avz --checksum /var/www/ [email protected]:/backup/www/

# ตรวจ verbose output ว่าไฟล์ไหนถูกส่ง
rsync -avzv /var/www/ [email protected]:/backup/www/ 2>&1 | head -30

Error: cron backup ไม่รัน ทั้งที่ทดสอบรันมือได้

cron มี environment ที่แตกต่างจาก shell — ไม่มี PATH หรือ environment variable เหมือนกัน:

# ใช้ full path ทุกคำสั่งใน backup script
/usr/bin/rsync -avz ...
/usr/bin/ssh -i /root/.ssh/backup_key ...

# หรือเพิ่ม PATH ใน crontab
0 2 * * * PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin /usr/local/bin/backup.sh

คำถามที่พบบ่อย

rsync ต่างจาก cp อย่างไร?

cp copy ทุกไฟล์ทุกครั้ง ส่วน rsync ตรวจสอบ size และ timestamp ก่อน จะส่งเฉพาะไฟล์ที่เปลี่ยนแปลงจริง และยังส่งได้ผ่าน SSH ทำให้ปลอดภัยและ bandwidth-efficient มาก หลังจาก full sync ครั้งแรก backup รายวันใช้เวลาเพียงไม่กี่วินาที

flag --delete อันตรายไหม?

--delete จะลบไฟล์บน destination ที่ไม่มีใน source อีกแล้ว ถ้าเรียกถูก path ก็ดีมาก ช่วยให้ backup สะท้อน source จริงๆ แต่ถ้า path ผิดอาจลบข้อมูลผิดได้ ควรทำ dry-run ด้วย -n ก่อนทุกครั้งที่รันมือ และเก็บ snapshot หลายรุ่น (--link-dest) เป็น safety net

ต้องการ restore ทั้งเซิร์ฟเวอร์ ทำอย่างไร?

rsync ใช้ restore ได้เช่นกันแค่สลับ source กับ destination: rsync -avz [email protected]:/backup/www/ /var/www/ สำหรับ restore ทั้ง server ให้ restore ทีละส่วน (files, database, config) และทดสอบแต่ละส่วนก่อนเปิดให้บริการจริง