记从虚拟主机迁移到云服务器的历程

感谢雨云提供的计算服务。


1. 迁移动机

原网站部署在共享虚拟主机上,主要用于个人博客(WordPress)和 Git 文件同步服务(用 PHP 重写的 Git Server)。虚拟主机在功能和资源上存在明显限制:

  • 并发能力差:当同时有 2-3 个用户访问时,频繁出现 500 错误。查看虚拟主机面板显示 CPU 和内存资源使用率长期接近 100%,导致 PHP 进程被强制终止。
  • 无法安装 Redis 等扩展:虚拟主机不支持 Redis、OPcache 等高性能组件,WordPress 缓存只能依赖文件缓存,数据库查询压力大。
  • 环境不可定制:无法修改 PHP 配置(如 memory_limitmax_execution_time),无法安装自定义 Nginx 模块,无法使用 HTTP/2,QUIC 等新特性。
  • 自由度低:域名绑定数量有限(6 个),文件权限受限,部分插件无法正常运行。

经过对多家云服务器厂商的对比,最终选择雨云洛杉矶1区入门版云服务器(1C1G),延迟在 150-250ms 之间,访问网速可达 10MB/s。(延迟和网速数据基于本地电信网络,通过 ping 和 curl 下载测速文件获得,仅供参考。)

2. 前后环境对比

虚拟主机云服务器
网站空间2048MB30GB
数据库空间256MB30GB
每月流量128GB1024GB
网络带宽8Mbps100Mbps
域名绑定6个理论无限
自由度共享独享
价格16.99元/月12.5元/月(首月)22.5元/月

3. 迁移准备

3.1 资产清单

  • 网站文件:/www/wwwroot/,共 670MB(包含 WordPress 核心、主题、插件及 Git 服务代码)
  • 数据库:一个,共 40.1MB
  • 域名:www.vblg.top, git.vblg.top
  • SSL证书:下载 PEM 格式证书
  • 定时任务:虚拟主机上有 2 条 cron 任务(WordPress 自动更新、Git 仓库定期备份)。

3.2 备份策略

  • 停止所有实时任务:在管理后台停用 cron 服务和可能更新数据库的服务(如评论区、自动更新插件)。
  • 数据库备份:使用 phpMyAdmin 导出数据库,格式选择 SQL,编码 utf8mb4,压缩方式 gzip。
  • 文件备份:通过虚拟主机面板的文件管理器,将 /www/wwwroot 目录打包为 tar.gz,下载至本地。
  • 异地留存:备份文件同时保存在虚拟主机 /backup 目录和本地电脑,确保至少保留 7 天。

3.3 回滚方案

  • DNS TTL 调整:提前将域名 DNS 的 TTL 从默认 600 秒降低至 300 秒,加快切换速度。
  • 保留原环境:迁移完成后,虚拟主机保留至少 7 天,确保可随时回滚。
  • 本地 hosts 测试:在正式切换 DNS 前,通过修改本地 hosts 文件模拟域名指向新服务器,充分测试。

4. 实施过程(按时间线)

4.1 停止实时任务(2026.08.19 09:05)

登录虚拟主机控制面板,停止所有可能产生数据写入的服务:

  • wp-config.php 中添加 define('DISABLE_WP_CRON', true);(这行代码需要放在 /* That's all, stop editing! */ 之前)
  • 使用 WP Maintenance Mode 插件,或在主题 header.php 中临时添加维护提示横幅。
  • 在 WordPress 后台的“设置 -> 讨论”中关闭评论功能,或使用维护模式插件临时禁止评论写入。
  • 停用自动更新插件、Git 同步服务。
  • 确认 WooCommerce 等涉及购买的服务已停止(本案例无此服务,但提醒注意)。

结果:网站保持可访问状态,但顶部显示“维护中”公告,数据库不再产生新的写入。

4.2 购买云服务器,安装系统(2026.08.19 09:12)

  • 在雨云控制台购买入门版实例(洛杉矶 1 区)。
  • 安装操作系统:Debian 13。
  • 配置安全组:仅开放 22(SSH)、80(HTTP)、443(HTTPS)端口,限制 SSH 来源 IP。
  • 备注:对于新手,可考虑使用宝塔面板;1Panel 在小内存机器上不推荐。本案例采用手动编译安装。

4.3 备份文件并下载(2026.08.19 09:30)

  • 文件备份:通过虚拟主机文件管理器,将 /www/wwwroot/ 打包。
  • 数据库备份:登录 phpMyAdmin,选择数据库,导出格式 SQL,字符集 utf8mb4。
  • 校验:在本机使用 md5sum 计算两个备份文件的 MD5 值并记录,用于后续完整性校验。

4.4 在云服务器上安装需要的软件(2026.08.19 09:35 – 2026.08.20 08:03)

为了先复原虚拟主机环境,安装 Nginx、PHP、MySQL(MariaDB)。考虑到性能和定制需求,采用源码编译安装,版本如下:

  • Nginx 1.30.4
  • PHP 8.5.9
  • MariaDB 11.8.6

4.4.1 编译安装耗时

软件编译耗时备注
Nginx约 10 分钟启用 HTTP/2、SSL、gzip 等模块
PHP约 30 分钟注意同时安装所需的扩展如mysqli, pdo_mysql, gd, curl, zip, opcache, redis, intl, mbstring
MariaDB约 4 小时编译过程较长,也可使用二进制包快速安装

4.5 环境配置与数据恢复(2026.08.20 08:17)

4.5.1 创建 Nginx 站点配置

为 www.vblg.top 和 git.vblg.top 分别创建 Nginx 配置文件,示例(包含 QUIC 支持):

# /etc/nginx/conf.d/www.vblg.top.conf

# HTTP 强制跳转 HTTPS
server {
    listen 80;
    listen [::]:80;
    server_name www.vblg.top;

    # 用于 ACME 证书验证(如 certbot)
    location ^~ /.well-known/acme-challenge/ {
        root /var/www/letsencrypt;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

# HTTPS 主服务
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    listen 443 quic;                # 启用 HTTP/3 (QUIC)
    listen [::]:443 quic;

    server_name www.vblg.top;

    root /var/www/vblg.top;
    index index.php index.html index.htm;

    # SSL 证书
    ssl_certificate     /etc/nginx/ssl/vblg.top/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/vblg.top/privkey.pem;

    # SSL 协议与加密套件
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    ssl_session_tickets on;

    # HSTS 与 HTTP/3 宣告
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header Alt-Svc 'h3=":443"; ma=86400' always;

    # 日志
    access_log /var/log/nginx/vblg.top.access.log;
    error_log  /var/log/nginx/vblg.top.error.log;

    # 禁止访问敏感文件
    location ~* \.(user\.ini|htaccess|htpasswd|env|git|svn|project|DS_Store|sql|log|md|yml|yaml|lock)$ {
        deny all;
    }

    # 禁止访问敏感目录
    location ~* /(\.git|\.svn|\.env|node_modules|vendor)/ {
        deny all;
    }

    # WordPress 伪静态
    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    # PHP 处理
    location ~ \.php$ {
        try_files $uri =404;
        include fastcgi_params;
        fastcgi_pass unix:/run/php/php8.5-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }

    # 静态资源缓存
    location ~* \.(gif|jpg|jpeg|png|bmp|swf|ico)$ {
        expires 30d;
        access_log off;
    }

    location ~* \.(js|css)$ {
        expires 12h;
        access_log off;
    }

    # ACME 验证目录
    location ^~ /.well-known/acme-challenge/ {
        root /var/www/letsencrypt;
    }
}

该配置假设 Nginx 已编译 QUIC 支持;若未启用 HTTP/3,请删除 listen 443 quic; 和 listen [::]:443 quic; 两行,并去掉 Alt-Svc 头。

4.5.2 导入数据库

使用 mysql -u root -p wordpress < /path/to/wordpress_backup.sql 导入

4.5.3 上传并解压网站文件

4.5.4 修改配置文件

以 WordPress 为例,修改 wp-config.php:

define('DB_NAME', 'wordpress');
define('DB_USER', 'wordpress');
define('DB_PASSWORD', 'strong_password');
define('DB_HOST', 'localhost');

4.5.5 导入 SSL证书

将 PEM 格式证书和私钥上传至 /etc/nginx/ssl/,并在 Nginx 配置中引用。

4.6 进行必要测试(2026.08.20 08:50)

4.6.1 文件完整性校验

在服务器上对上传的 backup.tar.gz 计算 MD5,与本地记录的压缩包 MD5 对比一致。

抽查如 wp-config.php 等文件确保正常。

4.6.2 临时绑定 IP 测试

修改本地 hosts 文件,将 www.vblg.top 和 git.vblg.top 指向新服务器 IP。

测试步骤:

  1. 访问 http://www.vblg.top/,确认跳转至 HTTPS 且页面正常。
  2. 访问 WordPress 后台 /wp-admin/,能正常登录。
  3. 测试 Git 服务:git clone https://git.vblg.top/repo.git,正常。
  4. 检查 Nginx 访问日志和错误日志,无致命错误。
  5. 使用 curl -I https://www.vblg.top/ 确认返回 200,HTTP/2 生效。

4.7 上线(2026.08.20 09:05)

  • 登录域名 DNS 管理后台,备份原有 DNS 记录(A 记录指向虚拟主机 IP)。
  • 修改 A 记录:将 www 和 git 的 A 记录指向新服务器 IP。
  • 由于 TTL 已提前降至 300 秒,理论上 5 分钟左右可开始生效;但受本地运营商 DNS 缓存影响,完全生效可能需要更长时间。
  • 观察 Nginx 访问日志,确认新服务器收到请求。
  • 持续监控 10 分钟,确认无异常,迁移完成。

回滚预案:若出现严重问题(如数据库连接失败、网站无法访问),立即将 DNS A 记录改回原虚拟主机 IP,解析生效后网站即可恢复。

5. 踩坑

5.1:PHP 无法连接数据库

现象:网站访问时出现 500 错误,PHP 错误日志显示 SQLSTATE[HY000] [2002] Connection refused

排查过程

  • 执行 lsof -i:3306,发现 MariaDB 未监听 3306 端口。
  • 执行 systemctl status mariadb,服务未运行。
  • 查看 MariaDB 错误日志 /data/mysql/error.log,提示 Can't start server: Bind on TCP/IP port: Address already in use

原因:残留进程占用了 3306 端口,导致 MariaDB 启动失败,服务未运行。

安全隐患:此前配置中 bind-address = 0.0.0.0 且防火墙未限制 3306,存在暴露风险。

解决:清理残留进程后启动 MariaDB,并改为 bind-address = 127.0.0.1,同时保持防火墙不放行 3306。

预防措施:在编译安装后,检查服务监听状态和防火墙规则,确保数据库仅对本地开放。

5.2:WordPress 后台无法上传文件

现象:登录 WordPress 后台,上传媒体文件时提示“无法创建目录 wp-content/uploads/2026/08”。

原因:解压文件后,wp-content/uploads 目录属主为 root,权限为 755,而 PHP-FPM 运行用户为 www,无写入权限。

解决方案

chown -R www:www /var/www/vblg.top/

# 目录 755,文件 644
find /var/www/vblg.top/ -type d -exec chmod 755 {} \;
find /var/www/vblg.top/ -type f -exec chmod 644 {} \;

# wp-config.php 建议 640
chmod 640 /var/www/vblg.top/wp-config.php

预防措施:解压后统一执行 chown -R www:www 和目录权限调整。

6. 附录


后记:本次迁移虽然耗时较长(主要是编译安装),但整个过程较为顺利,得益于充分的备份和测试。迁移后的云服务器为网站提供了强大的性能和灵活性,也为后续扩展(如 Redis、HTTP/2、自动备份)打下了坚实基础。如果你也计划从虚拟主机迁移到云服务器,希望本文能为你提供参考。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注