WordPress 7.1 ra mắt ngày 19/8, chỉ còn 17 ngày nữa. Bạn đã sẵn sàng chưa? Trước khi bấm nút “Update” trên bất kỳ major release nào, việc đầu tiên phải làm là backup đầy đủ. Mình đã thấy quá nhiều case client update WordPress mà không backup, plugin incompatible gây fatal error, cả site trắng tinh trong giờ phút vàng.
Bài này mình sẽ hướng dẫn từ A đến Z: backup database bằng mysqldump, backup files bằng rsync, thiết lập auto backup hằng ngày, và quan trọng nhất — cách restore khi sự cố xảy ra. Không plugin, không GUI, chỉ dùng SSH. Nhanh, gọn, reliable.
Tại Sao Không Dùng Plugin Backup Mà Phải Dùng SSH?
Plugin backup như UpdraftPlus hay BackWPup tiện cho người mới, nhưng trên VPS mình luôn ưu tiên cách thủ công qua SSH vì ba lý do. Thứ nhất, plugin backup chạy trong PHP runtime, bị giới hạn bởi max_execution_time — site lớn backup timeout giữa chừng. Thứ hai, plugin lưu backup cùng server, nếu server crash thì backup cũng theo. Thứ ba, SSH backup chạy ở level hệ điều hành, không phụ thuộc WordPress, nên vẫn hoạt động ngay cả khi WordPress bị hack hoặc fatal error.
Bước 1: Backup Database Bằng mysqldump
Database là phần quan trọng nhất — chứa toàn bộ posts, pages, comments, settings, users. mysqldump là công cụ built-in của MySQL/MariaDB, export database ra file SQL text.
Trước tiên, cần biết tên database, user, password. Kiểm tra trong wp-config.php:
grep -E "DB_NAME|DB_USER|DB_PASSWORD|DB_HOST" /var/www/thienlv.com/public_html/wp-config.phpKết quả sẽ hiện ra thông tin kết nối. Giờ backup:
# Tạo thư mục backup
sudo mkdir -p /backup/thienlv.com/$(date +%Y-%m-%d)
# Backup database với timestamp
mysqldump -u DB_USER -p'DB_PASSWORD' DB_NAME | gzip > \
/backup/thienlv.com/$(date +%Y-%m-%d)/db_$(date +%Y-%m-%d_%H%M%S).sql.gzThay DB_USER, DB_PASSWORD, DB_NAME bằng thông tin thực tế. Lệnh gzip nén file SQL lại, tiết kiệm 70-80% dung lượng.
Mình thường tạo shorthand để chạy nhanh hơn. Tạo file /usr/local/bin/wp-backup-db:
#!/bin/bash
# wp-backup-db - Backup WordPress database
SITE_DIR="/var/www/thienlv.com/public_html"
BACKUP_DIR="/backup/thienlv.com/$(date +%Y-%m-%d)"
mkdir -p "$BACKUP_DIR"
# Đọc DB info từ wp-config.php
DB_NAME=$(grep -oP "define\(\s*'DB_NAME',\s*'\K[^']+" "$SITE_DIR/wp-config.php")
DB_USER=$(grep -oP "define\(\s*'DB_USER',\s*'\K[^']+" "$SITE_DIR/wp-config.php")
DB_PASS=$(grep -oP "define\(\s*'DB_PASSWORD',\s*'\K[^']+" "$SITE_DIR/wp-config.php")
DB_HOST=$(grep -oP "define\(\s*'DB_HOST',\s*'\K[^']+" "$SITE_DIR/wp-config.php")
# Dump và nén
mysqldump -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" \
--single-transaction \
--quick \
--lock-tables=false \
| gzip > "$BACKUP_DIR/db_$(date +%Y-%m-%d_%H%M%S).sql.gz"
# Lưu thông tin
SIZE=$(du -sh "$BACKUP_DIR"/db_*.sql.gz | tail -1 | awk '{print $1}')
echo "DB backup: $BACKUP_DIR/db_$(date +%Y-%m-%d_%H%M%S).sql.gz ($SIZE)"
# Giữ chỉ 30 ngày gần nhất
find /backup/thienlv.com/ -name "db_*.sql.gz" -mtime +30 -deleteQuyền thực thi và test:
sudo chmod +x /usr/local/bin/wp-backup-db
sudo wp-backup-dbNếu thấy output kiểu DB backup: /backup/thienlv.com/2026-08-02/db_2026-08-02_090400.sql.gz (12M) là thành công.
Bước 2: Backup Files Bằng rsync
Database xong, giờ đến files: wp-config.php, wp-content/ (uploads, plugins, themes), và các file custom. rsync là lựa chọn tốt nhất vì chỉ copy phần thay đổi (incremental), không copy lại toàn bộ mỗi lần.
# Backup files bằng rsync (incremental)
sudo rsync -avz --delete \
--exclude='cache/' \
--exclude='w3tc-config/' \
--exclude='uploads/cache/' \
--exclude='*.log' \
/var/www/thienlv.com/public_html/ \
/backup/thienlv.com/files/Giải thích từng flag:
-a (archive): Preserve permissions, ownership, timestamps, symbolic links. Backup y hệt bản gốc.
-v (verbose): Hiển thị file đang copy, dễ theo dõi.
-z (compress): Nén data trong quá trình transfer, giảm I/O.
–delete: Xóa file ở destination không còn ở source. Giúp backup mirror chính xác. Nếu không muốn xóa, bỏ flag này.
–exclude: Bỏ qua thư mục cache, log — không cần backup, vừa tốn dung lượng.
Tạo script /usr/local/bin/wp-backup-files cho tiện:
#!/bin/bash
# wp-backup-files - Backup WordPress files using rsync
SITE_DIR="/var/www/thienlv.com/public_html"
BACKUP_DIR="/backup/thienlv.com/files"
rsync -avz --delete \
--exclude='cache/' \
--exclude='w3tc-config/' \
--exclude='wp-content/cache/' \
--exclude='wp-content/uploads/cache/' \
--exclude='wp-content/wflogs/' \
--exclude='*.log' \
--exclude='.git/' \
"$SITE_DIR/" "$BACKUP_DIR/"
echo "Files backup completed: $(date)"
du -sh "$BACKUP_DIR"sudo chmod +x /usr/local/bin/wp-backup-files
sudo wp-backup-filesBước 3: Backup wp-config.php Riệt Vì Nó Quan Trọng
wp-config.php chứa DB credentials, AUTH_KEYS, table prefix. Mất file này là chết. Mình luôn backup riêng để dễ restore:
sudo cp /var/www/thienlv.com/public_html/wp-config.php \
/backup/thienlv.com/configs/wp-config.php.bak.$(date +%Y%m%d)
# Backup cả .htaccess nếu dùng Apache
sudo cp /var/www/thienlv.com/public_html/.htaccess \
/backup/thienlv.com/configs/.htaccess.bak.$(date +%Y%m%d) 2>/dev/null
# Backup Nginx config nếu dùng Nginx
sudo cp /etc/nginx/sites-available/thienlv.com \
/backup/thienlv.com/configs/nginx.conf.bak.$(date +%Y%m%d) 2>/dev/nullBước 4: Tự Động Backup Bằng Cron Job
Backup thủ công thì sẽ có lúc quên. Cron job chạy tự động mỗi ngày lúc 3h sáng — lúc traffic thấp nhất.
Tạo script all-in-one /usr/local/bin/wp-backup-all:
#!/bin/bash
# wp-backup-all - Full WordPress backup (DB + Files + Configs)
# Run daily via cron at 3:00 AM
set -euo pipefail
SITE="thienlv.com"
SITE_DIR="/var/www/thienlv.com/public_html"
BACKUP_BASE="/backup/$SITE"
DATE=$(date +%Y-%m-%d)
BACKUP_DIR="$BACKUP_BASE/$DATE"
# --- 1. Database ---
mkdir -p "$BACKUP_DIR"
DB_NAME=$(grep -oP "define\(\s*'DB_NAME',\s*'\K[^']+" "$SITE_DIR/wp-config.php")
DB_USER=$(grep -oP "define\(\s*'DB_USER',\s*'\K[^']+" "$SITE_DIR/wp-config.php")
DB_PASS=$(grep -oP "define\(\s*'DB_PASSWORD',\s*'\K[^']+" "$SITE_DIR/wp-config.php")
DB_HOST=$(grep -oP "define\(\s*'DB_HOST',\s*'\K[^']+" "$SITE_DIR/wp-config.php")
mysqldump -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" \
--single-transaction \
--quick \
--lock-tables=false \
| gzip > "$BACKUP_DIR/db.sql.gz"
# --- 2. Configs ---
mkdir -p "$BACKUP_BASE/configs"
cp "$SITE_DIR/wp-config.php" "$BACKUP_DIR/wp-config.php.bak"
# --- 3. Files (incremental rsync) ---
rsync -az --delete \
--exclude='cache/' \
--exclude='w3tc-config/' \
--exclude='wp-content/cache/' \
--exclude='wp-content/uploads/cache/' \
--exclude='wp-content/wflogs/' \
--exclude='*.log' \
--exclude='.git/' \
"$SITE_DIR/" "$BACKUP_BASE/files/"
# --- 4. Cleanup: giữ 30 ngày ---
find "$BACKUP_BASE" -maxdepth 1 -type d -name "20*" -mtime +30 -exec rm -rf {} \;
# --- 5. Log ---
echo "[$(date)] Backup complete: $BACKUP_DIR" >> /var/log/wp-backup.logsudo chmod +x /usr/local/bin/wp-backup-all
# Thêm vào crontab
sudo crontab -e
# Thêm dòng sau:
0 3 * * * /usr/local/bin/wp-backup-all >> /var/log/wp-backup.log 2>&1Từ giờ, mỗi ngày 3h sáng, server tự backup database + files + configs, giữ đúng 30 ngày. Kiểm tra log bất cứ lúc nào:
sudo tail -20 /var/log/wp-backup.logBước 5: Đẩy Backup Lên Remote Storage (S3 Hoặc SFTP)
Backup chỉ nằm trên cùng server là rủi ro. Nếu ổ cứng hỏng hoặc VPS bị suspend, mất hết. Mình luôn push backup lên remote storage — S3, Backblaze B2, hoặc VPS khác qua SFTP.
Cách đơn giản nhất: dùng rclone push lên Backblaze B2 (rẻ nhất, $0.005/GB/tháng):
# Cài rclone
sudo curl https://rclone.org/install.sh | sudo bash
# Cấu hình remote (chạy 1 lần)
rclone config
# Chọn: n (new remote)
# Name: b2-backup
# Storage: backblaze (option 4 hoặc tìm "Backblaze")
# account + key theo B2 dashboard
# Push backup lên B2
rclone sync /backup/thienlv.com/ b2-backup:thienlv-backup/ \
--transfers 4 \
--checkers 8 \
--log-file /var/log/rclone-backup.logThêm vào cron, chạy sau backup local 30 phút:
# Crontab thêm dòng:
30 3 * * * rclone sync /backup/thienlv.com/ b2-backup:thienlv-backup/ --transfers 4 --checkers 8 >> /var/log/rclone-backup.log 2>&1Nếu dùng AWS S3 thay vì B2, thay b2-backup: bằng s3:your-bucket-name/. Cấu hình rclone config tương tự.
Cách Restore Khi Sự Cố Xảy Ra
Backup mà không test restore thì như không backup. Mình sẽ hướng dẫn restore từng phần.
Restore Database
# Giải nén file backup
gunzip < /backup/thienlv.com/2026-08-02/db.sql.gz | \
mysql -u DB_USER -p'DB_PASSWORD' DB_NAME
# Hoặc restore file chưa nén
mysql -u DB_USER -p'DB_PASSWORD' DB_NAME < /backup/thienlv.com/2026-08-02/db.sqlLưu ý quan trọng: Restore database sẽ ghi đè toàn bộ data hiện tại. Chắc chắn đang restore đúng database. Mình thường test trên staging site trước khi làm trên production.
Restore Files
# Reverse rsync: từ backup về site
sudo rsync -avz --delete \
/backup/thienlv.com/files/ \
/var/www/thienlv.com/public_html/
# Đảm bảo quyền đúng
sudo chown -R www-data:www-data /var/www/thienlv.com/public_html/
sudo find /var/www/thienlv.com/public_html/ -type d -exec chmod 755 {} \;
sudo find /var/www/thienlv.com/public_html/ -type f -exec chmod 644 {} \;Restore wp-config.php
sudo cp /backup/thienlv.com/configs/wp-config.php.bak.20260802 \
/var/www/thienlv.com/public_html/wp-config.php
sudo chown www-data:www-data /var/www/thienlv.com/public_html/wp-config.php
sudo chmod 640 /var/www/thienlv.com/public_html/wp-config.phpKiểm Tra Backup Có Hoạt Động Không
Đừng đợi đến lúc cần mới phát hiện backup hỏng. Mình recommend test hàng tháng:
# 1. Kiểm tra backup gần nhất
ls -lh /backup/thienlv.com/$(date +%Y-%m-%d)/
# 2. Kiểm tra file SQL có nội dung hợp lệ
zcat /backup/thienlv.com/$(date +%Y-%m-%d)/db.sql.gz | head -5
# Phải thấy: -- MySQL dump 10.x Distrib ...
# -- Host: localhost Database: ...
# 3. Đếm số table trong backup
zcat /backup/thienlv.com/$(date +%Y-%m-%d)/db.sql.gz | grep "CREATE TABLE" | wc -l
# Phải thấy số > 0, match với số table thực tế
# 4. Kiểm tra backup size bất thường
du -sh /backup/thienlv.com/$(date +%Y-%m-%d)*/
# Nếu size giảm đột ngột so với hôm trước, có vấn đề
# 5. Test restore lên staging
mysql -u staging_user -p'staging_pass' staging_db < \
<(zcat /backup/thienlv.com/$(date +%Y-%m-%d)/db.sql.gz)Checklist Trước Khi Nâng Cấp WordPress 7.1
WordPress 7.1 ra mắt 19/8. Trước khi update, mình luôn chạy qua checklist sau:
# 1. Backup đầy đủ
sudo wp-backup-all
# 2. Kiểm tra backup thành công
ls -lh /backup/thienlv.com/$(date +%Y-%m-%d)/
zcat /backup/thienlv.com/$(date +%Y-%m-%d)/db.sql.gz | grep "CREATE TABLE" | wc -l
# 3. Kiểm tra PHP compatibility (7.1 yêu cầu PHP 8.1+)
php -v
# 4. Kiểm tra plugin compatibility
sudo -u www-data wp plugin list --path=/var/www/thienlv.com/public_html --format=table
# 5. Test trên staging trước (nếu có)
# Update staging trước, test 24h, rồi mới update production
# 6. Đặt maintenance mode
sudo -u www-data wp maintenance-mode activate --path=/var/www/thienlv.com/public_html
# 7. Update
sudo -u www-data wp core update --path=/var/www/thienlv.com/public_html
# 8. Update database
sudo -u www-data wp core update-db --path=/var/www/thienlv.com/public_html
# 9. Test site
curl -I https://thienlv.com
# 10. Tắt maintenance mode
sudo -u www-data wp maintenance-mode deactivate --path=/var/www/thienlv.com/public_htmlNếu sau update site bị lỗi, restore ngay trong 2 lệnh:
# Restore database
gunzip < /backup/thienlv.com/$(date +%Y-%m-%d)/db.sql.gz | \
mysql -u DB_USER -p'DB_PASSWORD' DB_NAME
# Restore files
sudo rsync -az /backup/thienlv.com/files/ /var/www/thienlv.com/public_html/Site quay lại trạng thái trước update trong dưới 5 phút. Đó là sức mạnh của backup thủ công qua SSH.
Kết Luận
Backup là bước đầu tiên và quan trọng nhất trước bất kỳ thay đổi lớn nào trên WordPress. Với VPS, cách thủ công qua mysqldump + rsync + cron nhanh hơn, reliable hơn, và không bị giới hạn như plugin. WordPress 7.1 sắp ra mắt, đừng để sự cố update phá hỏng site của bạn. Backup ngay hôm nay, test restore, rồi mới bấm update.
Mình đã áp dụng phương pháp này cho hơn 20 site WordPress khách hàng trong 2 năm qua, chưa từng mất data. Phương pháp đơn giản, nhưng hiệu quả. Nếu bạn chưa có backup strategy, bắt đầu ngay với bài này.
Nếu muốn tìm hiểu thêm về cách tạo staging site test trước khi update hoặc tối ưu database WordPress, mình đã có hướng dẫn chi tiết. Đọc thêm nhé.
