Mục lục
Giới thiệu
Di chuyển từ VPS này sang VPS khác với Virtualmin hơn 10 tên miền WordPress nghe có vẻ đơn giản trên lý thuyết—sao lưu trên máy chủ cũ, phục hồi trên máy chủ mới, xong. Thực tế thì đó là một bãi mìn gồm những giới hạn hệ thống ẩn, ràng buộc về file descriptor và vấn đề dung lượng đĩa có thể khiến bạn mắc kẹt hàng giờ.
Gần đây tôi đã hoàn tất một cuộc di chuyển Virtualmin đầy thử thách từ một Debian VPS Debian 12 ở Pháp sang một VPS Debian 13 mới ở Hà Lan, chuyển hơn 4,4GB dữ liệu sao lưu qua hơn 10 tên miền. Trong quá trình đó, tôi gặp mọi lỗi lớn mà quản trị viên Virtualmin thường đối mặt—và đã giải quyết tất cả. Bài viết này ghi lại chính xác các vấn đề và cách khắc phục để bạn không phải học theo cách khó khăn.
Dù bạn đang nâng cấp nhà cung cấp VPS, mở rộng theo chiều ngang hay khôi phục sau sự cố máy chủ, hướng dẫn này sẽ dẫn bạn qua những lỗi thực tế và cách khắc phục.

Phần 1: Lập kế hoạch và chuẩn bị trước khi di chuyển
Chọn thông số kỹ thuật cho VPS đích
Trước khi động vào bất cứ thứ gì trên máy chủ hiện tại, hãy đảm bảo VPS mới có đủ tài nguyên. Sai lầm phổ biến là nghĩ rằng chỉ dung lượng đĩa là quan trọng—không phải vậy.
Thông số tối thiểu cho Virtualmin với hơn 10 tên miền:
- Dung lượng đĩa: 100GB (không phải 50GB—site WordPress kèm bản sao lưu tăng nhanh lắm)
- CPU: Từ 6 lõi trở lên (khuyến nghị từ 8 lõi cho hơn 10 tên miền)
- RAM: Tối thiểu 8GB (từ 15GB trở lên cho môi trường production)
- Swap: 4GB (thêm sau khi cài hệ điều hành nếu chưa cấu hình sẵn)
Máy chủ mới nên bằng hoặc mạnh hơn máy chủ cũ về CPU và RAM, với dung lượng đĩa nhiều hơn. Virtualmin tốn nhiều CPU và I/O trong quá trình phục hồi—bộ xử lý yếu sẽ khiến việc phục hồi diễn ra rất chậm.
Danh sách kiểm tra trước khi di chuyển
Trên máy chủ cũ (48 giờ trước khi di chuyển):
- Giảm TTL DNS xuống 300 giây (5 phút) để giảm thiểu vấn đề bộ nhớ đệm:
virtualmin modify-dns --all-domains --ttl 300
- Tạo bản sao lưu mới với định dạng khuyến nghị của Virtualmin:
mkdir /backup
virtualmin backup-domain \
--dest /backup/ \
--all-domains \
--all-features \
--newformat
- Xác minh tính toàn vẹn của bản sao lưu trước khi truyền:
tar -tzf /backup/backup_*.tar.gz > /dev/null && echo "Backup OK" || echo "Backup corrupted"
- Ghi lại dung lượng cơ sở dữ liệu để lập kế hoạch:
mysql -e "SELECT table_schema AS 'Database', ROUND(SUM(data_length+index_length)/1024/1024,2) AS 'Size_MB' FROM information_schema.TABLES GROUP BY table_schema;"
- Kiểm tra các cấu hình tùy chỉnh có thể không được chuyển sang:
- Phiên bản PHP tùy chỉnh
- Cấu hình NGINX đã chỉnh sửa
- Tác vụ cron trong /etc/cron.d/
- Chứng chỉ SSL tùy chỉnh
Phần 2: Quá trình di chuyển
Bước 1: Truyền tệp sao lưu
Dùng SCP kèm checksum để xác minh tính toàn vẹn của tệp:
# On old server, generate checksum
sha256sum /backup/backup_*.tar.gz > /backup/backup.sha256
# Transfer backup and checksum
scp /backup/backup_*.tar.gz [email protected]:/Files/
scp /backup/backup.sha256 [email protected]:/Files/
# On new server, verify
cd /Files/
sha256sum -c backup.sha256
Nếu checksum không khớp, dừng ngay. Tệp đã hỏng trong quá trình truyền. Hãy truyền lại hoặc dùng rsync kèm checksum:
rsync -avz --checksum /backup/backup_*.tar.gz [email protected]:/Files/
Bước 2: Cài đặt Virtualmin trên máy chủ mới
Dùng trình cài đặt chính thức của Virtualmin:
curl https://software.virtualmin.com/gpl/scripts/virtualmin-install.sh | sh
Quan trọng: Cài đặt cùng phiên bản hệ điều hành (hoặc gần nhất)—điều này quan trọng hơn mọi người nghĩ. Tôi đã di chuyển từ Debian 12 lên Debian 13 (không khuyến nghị, nhưng vẫn làm được). Nếu có thể, hãy giữ nguyên phiên bản major.
Bước 3: Cấu hình hệ thống trước khi phục hồi
Đây là chỗ hầu hết các cuộc di chuyển thất bại. Trước khi động vào việc phục hồi, hãy sửa ba giới hạn quan trọng này:
Sửa 1: Tăng số file descriptor mở
Đây là nguyên nhân số 1 gây lỗi “No space left on device” khi phục hồi, ngay cả khi dung lượng đĩa còn rất nhiều.
# Check current limit
ulimit -n
# Likely shows: 1024 (too low for Virtualmin)
# Increase for current session
ulimit -n 65536
# Verify
ulimit -n
# Should show: 65536
# Make permanent
cat >> /etc/security/limits.conf << EOF
* soft nofile 65536
* hard nofile 65536
root soft nofile 65536
root hard nofile 65536
EOF
Vì sao là 65536? Mỗi tệp, socket, pipe và kết nối cơ sở dữ liệu đang mở đều chiếm một file descriptor. Với hơn 10 site WordPress, máy chủ mail, tiến trình NGINX và kết nối MySQL, bạn dễ vượt qua 1024. OVH và các nhà cung cấp khác đặt mặc định thấp như vậy để bảo mật—nó được thiết kế để tăng riêng cho từng ứng dụng.
Sửa 2: Tăng kích thước /tmp (tmpfs)
Trong quá trình phục hồi, Virtualmin tạo các bản dump MySQL trong /tmp/. Mặc định, /tmp là tmpfs (đĩa RAM) giới hạn khoảng 50% tổng RAM. Với 11GB RAM, /tmp tối đa chỉ khoảng 5,8GB. Nhưng Virtualmin có thể dễ dàng tạo 5-6GB tệp tạm trong khi phục hồi.
# Check current /tmp size
df -h /tmp
# Dynamically resize without unmounting
mount -o remount,size=8G /tmp
# Verify
df -h /tmp
# Make permanent
echo "tmpfs /tmp tmpfs size=8G,mode=1777 0 0" >> /etc/fstab
Sửa 3: Thêm không gian swap
Nếu quá trình phục hồi ngốn hết RAM, hệ thống sẽ không phản hồi. 4GB swap tạo một vùng đệm an toàn:
# Create 4GB swap file
fallocate -l 4G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
# Make permanent
echo '/swapfile none swap sw 0 0' >> /etc/fstab
# Verify
swapon --show
Phần 3: Quá trình phục hồi và các lỗi thường gặp
Lỗi 1: “Checking contents of the backup ..” bị treo hơn 20 phút
Nó trông như thế này:
Checking contents of the backup ..
[bị treo 15-30 phút không tiến triển]
Nguyên nhân gốc: Đây không phải là treo—nó thực sự chậm. Lệnh tar -tzf của Virtualmin đọc toàn bộ kho lưu trữ nén 4,4GB, kiểm tra từng header tệp và xác minh tính toàn vẹn của tar. Trên CPU cũ (như Haswell), việc này có thể mất hơn 20 phút cho bản sao lưu 4GB.
Giải pháp:
- Đừng hoảng. Kiểm tra xem tar có thực sự đang chạy không:
ps aux | grep tar
iostat -x 1 # Check disk activity
- Dùng phục hồi qua CLI thay vì giao diện web (bỏ qua thời gian chờ xác minh):
screen -S restore
virtualmin restore-domain \
--source /Files/backup_*.tar.gz \
--all-domains \
--all-features \
--reuid
Việc --reuid tự động điều chỉnh ID người dùng/nhóm—rất quan trọng khi phục hồi giữa các hệ thống khác nhau.
Lỗi 2: “/bin/tar: Cannot write: No space left on device”
Nó trông như thế này:
/bin/tar: ./seo.grahammiranda.com_mail_users: Cannot write: No space left on device
/bin/tar: ./esim.grahammiranda.com_virtualmin_ssl_key: Cannot write: No space left on device
[hàng chục lỗi tương tự nữa]
/bin/tar: Exiting with failure status due to previous errors
Phần gây bối rối: Bạn còn trống 75GB, nhưng nó báo “No space left on device.”
Nguyên nhân gốc (theo thứ tự khả năng):
- Chạm giới hạn file descriptor (phổ biến nhất)
- Triệu chứng: Lỗi xuất hiện sau 5-10 phút phục hồi, không phải ngay từ đầu
- Cách sửa:
ulimit -n 65536(đã nói ở trên)
- /tmp bị đầy (phổ biến thứ hai)
- Triệu chứng: Lỗi nhắc đến MySQL hoặc tệp tạm
- Kiểm tra:
df -h /tmptrong khi phục hồi—xem nó đầy lên 100% - Cách sửa:
mount -o remount,size=8G /tmp(đã nói ở trên)
- Dung lượng đĩa thực sự hết (ít phổ biến nhưng vẫn có thể)
- Kiểm tra:
df -h /hiển thị còn trống <5GB - Giải pháp:
- Kiểm tra:
# Clean up failed restore
rm -rf /home/*
rm -rf /var/lib/virtualmin/*
rm -rf /tmp/*
rm -rf /extract_test/
# If backup is still in /Files, consider moving it
mv /Files/backup_*.tar.gz /mnt/ # Move to another partition if available
- Cạn kiệt inode (hiếm)
- Kiểm tra:
df -i /hiển thị iUsed >90% - Nguyên nhân: Hệ thống tệp được tạo với quá ít inode
- Giải pháp: Định dạng lại hệ thống tệp với nhiều inode hơn (phá hủy dữ liệu)
- Kiểm tra:
Cách chẩn đoán trong khi phục hồi:
Mở một terminal thứ hai và theo dõi theo thời gian thực:
watch -n 2 'df -h / && echo "---" && df -h /tmp && echo "---" && du -sh /tmp/* 2>/dev/null | sort -rh | head -5'
Việc này cho thấy chính xác khi nào và ở đâu bạn chạm giới hạn.
Lỗi 3: NGINX không khởi động sau khi phục hồi
Thông báo lỗi:
nginx[34392]: [emerg] 34392#34392: open() "/etc/nginx/snippets/block-manager.conf" failed (2: No such file or directory)
nginx: configuration file /etc/nginx/nginx.conf test failed
Nguyên nhân gốc: Quá trình phục hồi thất bại một phần, hoặc một số tệp không được truyền đúng. Cấu hình NGINX tham chiếu đến những tệp không tồn tại.
Giải pháp:
- Tạo tệp còn thiếu:
mkdir -p /etc/nginx/snippets
touch /etc/nginx/snippets/block-manager.conf
- Kiểm tra cấu hình NGINX:
nginx -t
- Khởi động NGINX:
systemctl start nginx
systemctl status nginx
Nếu tệp cần nội dung thực, hãy kiểm tra máy chủ cũ:
scp old-server.com:/etc/nginx/snippets/block-manager.conf /etc/nginx/snippets/

Phần 4: Giải pháp nâng cao và tối ưu hóa
Phục hồi từng tên miền một (cách an toàn nhất)
Nếu phục hồi toàn bộ vẫn thất bại dù đã sửa, hãy phục hồi có chọn lọc:
# Clean previous failed attempts
rm -rf /home/*
rm -rf /var/lib/virtualmin/*
# Restore just the main domain first
virtualmin restore-domain \
--source /Files/backup_*.tar.gz \
--domain grahammiranda.com \
--all-features \
--reuid
Cách này giúp khoanh vùng tên miền nào có vấn đề. Nếu một tên miền phục hồi thành công, cách làm đó sẽ hiệu quả với những tên miền khác.
Những lưu ý khi di chuyển từ Debian 12 lên Debian 13
Tôi đã di chuyển từ Debian 12 lên Debian 13. Nhìn chung vẫn tương thích, nhưng cần chú ý:
- Khác biệt phiên bản PHP: Debian 12 có thể có PHP 8.1, Debian 13 dùng 8.3
- Kiểm tra:
php -vtrên cả hai máy chủ - Vấn đề: Hiếm khi gặp vấn đề tương thích với các extension PHP cũ
- Cách sửa: Buộc dùng phiên bản PHP cũ:
virtualmin modify-web --domain example.com --php-version 8.1
- Kiểm tra:
- Cú pháp cấu hình NGINX/Apache: Thường tương thích, nhưng hãy kiểm tra sau khi phục hồi
- Kiểm tra:
nginx -tvàapache2ctl configtest
- Kiểm tra:
- Tương thích MySQL/MariaDB: Nhìn chung tương thích về sau
- Kiểm tra:
mysql --versiontrên cả hai máy chủ - Khác biệt định dạng dump: Hiếm, nhưng Debian mới hơn có thể có SQL mode nghiêm ngặt hơn
- Kiểm tra:
- Tương thích chứng chỉ SSL: Không có vấn đề giữa các phiên bản Debian, nhưng hãy xác minh:
certbot certificates # Check Let's Encrypt certs
Phần 5: Kiểm tra sau khi di chuyển
Các kiểm tra quan trọng trước khi đưa vào hoạt động
Sau khi phục hồi xong, hãy xác minh mọi thứ hoạt động:
# 1. List all restored domains
virtualmin list-domains
# 2. Test web connectivity
curl -I https://yourdomain.com
# 3. Check mail functionality
mysql -u root -p'password' -e "SELECT user FROM mysql.user;"
# 4. Verify DNS
dig yourdomain.com @localhost
# 5. Check Virtualmin module
virtualmin test-domain --domain yourdomain.com
# 6. Monitor logs for errors
journalctl -f
tail -f /var/log/nginx/error.log
Cập nhật bản ghi DNS
Khi mọi tên miền đã phục hồi thành công:
- Cập nhật nameserver tại nhà đăng ký để trỏ đến máy chủ mới
- Theo dõi thời gian đếm ngược TTL (nên là 5 phút với TTL đã giảm)
- Kiểm tra từ nhiều vị trí:
nslookup yourdomain.com
dig yourdomain.com +short
- Đưa TTL DNS trở về bình thường sau 24-48 giờ:
virtualmin modify-dns --all-domains --ttl 3600
Phần 6: Tham khảo giới hạn hệ thống
Để tham khảo sau này, đây là tất cả giới hạn hệ thống đã kiểm tra trong lần di chuyển này:
# User/process limits
ulimit -a # All limits
ulimit -n # Open files
ulimit -u # Max processes
ulimit -v # Virtual memory
# System-wide limits
cat /proc/sys/fs/file-max # System-wide open files
cat /proc/sys/kernel/pid_max # Max process IDs
cat /proc/sys/vm/max_map_count # Memory map limit
# Current resource usage
df -h # Disk space
df -i # Inode usage
free -h # RAM and swap
ps aux | wc -l # Running processes
lsof | wc -l # Open file descriptors
# Filesystem specifics
mount | grep /dev/sda1 # Mount options
quota -s # Disk quotas
tune2fs -l /dev/sda1 # Filesystem properties
Điểm chính cần nhớ
- OVH (và hầu hết nhà cung cấp) đặt mặc định thận trọng. Bạn phải tăng giới hạn file descriptor trước khi phục hồi bản sao lưu Virtualmin.
- Giới hạn hệ thống mới là kẻ thù thực sự, không phải dung lượng đĩa. Ngay cả khi còn trống 75GB, bạn vẫn sẽ gặp “No space left on device” nếu
/tmpbị đầy hoặc file descriptor đã cạn. - Tăng
/tmpkích thước trước khi phục hồi. Virtualmin tạo 5-6GB tệp tạm khi phục hồi bản sao lưu. Phân bổ tmpfs mặc định là không đủ. - Dùng phục hồi qua CLI, không dùng giao diện web. Giao diện web gặp vấn đề hết thời gian chờ với bản sao lưu lớn. Phục hồi qua dòng lệnh đáng tin cậy hơn và hiển thị tiến trình thực tế.
- Di chuyển từ Debian 12 lên Debian 13 vẫn chạy được, nhưng giữ cùng phiên bản sẽ an toàn hơn. Khác biệt phiên bản nhỏ hiếm khi gây vấn đề, nhưng nếu có thể hãy ở trong cùng phiên bản major.
- Xác minh tính toàn vẹn của bản sao lưu trước khi truyền. Dùng checksum SHA256 để đảm bảo tệp sao lưu không bị hỏng trong khi truyền.
- Lập kế hoạch trước khi di chuyển giúp bạn tiết kiệm hàng giờ. Giảm TTL DNS, kiểm tra dung lượng cơ sở dữ liệu và chuẩn bị máy chủ đích sẽ giúp tránh được hầu hết các vấn đề.
Kết luận
Di chuyển Virtualmin không khó—chỉ là nó khá khó tính. Phần lớn sự cố không đến từ bản thân Virtualmin mà từ những giới hạn hệ thống ẩn do nhà cung cấp hosting đặt ra. Hiểu rõ các ràng buộc này và áp dụng những cách khắc phục được ghi trong bài, bạn có thể chuyển hơn 10 trang WordPress giữa các máy chủ một cách ổn định.
Những lỗi cụ thể mà tôi gặp (giới hạn số tệp mở, /tmp cạn kiệt, thiếu các snippet NGINX) đều có thể tái hiện và khá phổ biến. Nếu bạn gặp lỗi nào trong số đó, hãy quay lại hướng dẫn này—bạn sẽ tìm thấy cách giải quyết chính xác.
Chúc bạn di chuyển suôn sẻ. Mong bản sao lưu của bạn được phục hồi nhanh chóng và các tên miền hoạt động trở lại mà không gặp trục trặc.
Tiểu sử tác giả
Hướng dẫn này ghi lại một lần di chuyển Virtualmin thực tế đã hoàn thành vào tháng 2 năm 2026, chuyển hơn 10 tên miền đang chạy thật từ một VPS Debian 12 (Pháp) sang một VPS Debian 13 (Hà Lan). Các giải pháp đều đã được thử thách và kiểm chứng thực tế.



