博客刚搭好,我又想到一个问题:现在这台服务器到期以后,如果不续费,换一台服务器,博客和域名怎么办?
总不能每换一次服务器,就重新买一个域名,再让别人更新收藏夹。
所以趁着现在的部署过程还记得,我把以后搬家的步骤也整理了一遍。这篇先作为迁移预案,等真正换服务器时,再补实际操作和遇到的问题。
目前我的博客是 Hugo + PaperMod + Nginx:在 Mac 上写文章、生成网页,上传到服务器,用 https://040012.xyz/ 访问。下面按这套静态博客、域名直接连接服务器的部署方式来考虑。
先把“换服务器”和“换域名”分开
我这里说的“把域名转移到新服务器”,实际操作是修改域名的 DNS 解析,让 040012.xyz 指向新的服务器 IP。
域名本身可以继续用,注册商和 DNS 服务商也可以保持原样。
需要迁移或重建的东西,主要有这些:
| 内容 | 换服务器时怎么处理 |
|---|---|
域名 040012.xyz | 保留,修改解析记录 |
| Hugo 源文件 | 继续保存在 Mac,另外做独立备份 |
| 生成的网页 | 重新生成,上传到新服务器 |
| Nginx | 在新服务器安装并配置 |
| HTTPS 证书 | 在新服务器重新申请,或安全迁移已有证书 |
| 续期任务 | 在新服务器重新检查和验证 |
因为域名没有变,Hugo 的 baseURL 仍然是:
baseURL = 'https://040012.xyz/'
这里不用改成新服务器的 IP。以后上传命令里的服务器地址需要更新,但文章对外使用的网址可以保持不变。
尽量在旧服务器到期前开始
虽然题目写的是“服务器到期后”,真要操作,我会尽量提前几天开始,让新旧服务器有一段重叠时间。
如果旧服务器还在,新机器出问题时,至少还有地方可以回退。等新站稳定了,再处理旧机器,会从容很多。
如果已经到期,我会先看云控制台里的实例和磁盘还在不在、有没有快照或恢复入口。具体能否恢复,要看当时的资源状态和平台规则,不能默认过期的数据一定还在。
对现在这个博客来说,只要 Mac 上完整的 my-blog 文件夹还在,就可以重新生成网页,在新机器上重建网站。
但这也让我意识到,源文件不能只放在一台电脑上。真正开始积累文章以后,需要备份的不只是 Markdown,还包括图片、hugo.toml、头像、主题和自己写的模板、样式。
服务器上的网页是生成结果,域名只是访问入口,它们都不能代替完整的源文件备份。
先准备新机器,暂时保留原来的解析
新服务器准备好后,我会先安装 Nginx,开放安全组入方向的 TCP 80 和 443 端口。
如果仍然使用 Ubuntu,可以沿用这次搭建时的安装方式。下面的服务器命令按管理员权限的 root shell 写法展示;这是权限说明,不代表真实 SSH 登录账号。普通管理账号需按需加 sudo:
apt update && apt install -y nginx certbot python3-certbot-nginx
然后配置博客站点。为了延续当前的目录结构,我会继续把网页放到 /var/www/html/,域名明确写成 040012.xyz:
server {
listen 80;
listen [::]:80;
server_name 040012.xyz;
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
这段是新站点配置示例,需要保存到 Nginx 的站点配置目录并启用。新机器如果已经有其他网站,要先看现有配置,避免直接覆盖。
配置启用后,先检查语法,通过后再重新加载:
nginx -t && systemctl reload nginx
此时还没有在新机器上配置 HTTPS,先确认 HTTP 能正确提供博客文件。
接着在 Mac 上重新生成网页并上传。下面使用文档专用 TEST-NET-1 地址 192.0.2.10 和用户名占位符 your-ssh-user,均不是真实服务器信息。实际操作前必须替换 NEW_SERVER_IP 和 SERVER_USER,并确认账号有 /var/www/html/ 的写入权限;没有权限时先上传到可写暂存目录,再由管理员安装到网站目录。
NEW_SERVER_IP='192.0.2.10'
SERVER_USER='your-ssh-user'
cd ~/my-blog
hugo --minify && scp -r public/. "$SERVER_USER@$NEW_SERVER_IP":/var/www/html/
我会先让新机器和旧机器提供同一版博客。迁移期间暂时少改文章,避免不同访客看到两套内容。
不改 DNS,也能先测试新服务器
新服务器部署完成以后,不能只看到 Nginx 返回 200 就认为博客已经正常。默认欢迎页同样会返回 200,还要检查实际页面内容。
这时域名仍然指向旧机器,可以在 Mac 上用 curl --resolve,只让这一次请求连接新机器:
curl --noproxy '*' \
--resolve "040012.xyz:80:$NEW_SERVER_IP" \
-I http://040012.xyz/
--resolve 给这次请求指定了域名和 IP 的对应关系,同时保留请求里的域名信息。它不会修改公共 DNS,也不需要先改电脑的 hosts 文件。
再请求一篇已存在的文章,检查返回的标题和正文:
curl --noproxy '*' \
--resolve "040012.xyz:80:$NEW_SERVER_IP" \
http://040012.xyz/posts/hugo-blog-deployment/
这一步主要确认新机器上的域名匹配、网页目录和文章路径没有配错。首页、文章、图片和搜索用到的 index.json 都应该检查。
Hugo 生成的链接仍然使用正式域名,所以这只能作为定向检查,不能把点开一个普通域名链接、又访问到旧服务器的结果,当成新服务器已经验证通过。
再切换域名解析,给缓存留出时间
我会提前查看域名解析记录的 TTL,也就是解析结果可以被缓存多久。
迁移前,可以把相关记录的 TTL 调低一些。例如平台支持时,设为 600 秒。需要注意的是,已经缓存了旧记录的 DNS 服务器,可能仍会按原来的 TTL 使用旧结果。
因此,我会先降低 TTL,等原来的缓存有效期过去以后,再正式切换 IP。不会在改 IP 的同一分钟才降低 TTL,然后期待所有人马上访问新机器。
切换时,要把根域名对应的 A 记录改成新服务器的 IPv4 地址。如果还使用 www,也要核对它的 A 记录或 CNAME 指向。
还有一个容易漏掉的地方是 AAAA 记录。如果域名原来配置过 IPv6,就需要一起处理:新机器支持 IPv6,就更新地址;暂时不用,就移除对应的旧记录,避免部分访客仍然连到旧机器。
改完以后,可以在 Mac 上查看当前网络查到的结果:
dig +short A 040012.xyz
dig +short AAAA 040012.xyz
查到新 IP,只能说明这次查询使用的解析链路已经更新,不代表全球缓存都已经刷新。不同网络在一段时间内访问到不同服务器,是需要提前考虑的情况。
这也是我想让新旧机器短暂并行的原因。保留时间至少要覆盖旧 TTL,再留一些观察余量。如果预算允许,我会给自己预留一两天的重叠时间,而不是切完解析就立刻释放旧机器。
HTTPS 要单独收尾
改了 DNS,证书文件不会自动出现在新服务器上。
当前这套博客可以在新机器上重新申请证书。使用 Certbot 的 Nginx 插件时,常见的 HTTP-01 验证需要让 Let’s Encrypt 通过域名访问服务器的 80 端口。
所以我会在外部解析已经能指向新机器、80 端口正常开放以后,再执行:
certbot --nginx -d 040012.xyz --redirect
它会验证域名、申请证书,并配置 HTTP 跳转到 HTTPS。
这里有个顺序问题需要记住:如果先切 DNS,再在新机器申请证书,中间可能出现一小段 HTTPS 无法访问的时间。 我现在的网站已经会跳转到 HTTPS,访客和浏览器也可能直接使用 HTTPS,不能因为新机器的 HTTP 页面正常,就认为这一段没有影响。
对个人博客来说,可以选择访问较少的时间完成切换。但如果到时希望尽量减少这段窗口,我会考虑提前通过 DNS-01 验证,在新服务器签好证书、配置并验证 HTTPS,再切换解析。
DNS-01 是通过域名的 TXT 记录验证控制权,不要求网站已经解析到新服务器。不过,如果靠手工添加 TXT 记录完成验证,后续续期也不会因此自动解决。要长期自动续期,还需要配置受支持的 DNS API 插件或验证钩子。
这两种顺序各有操作成本。到真正迁移时,我会根据是否能接受短暂中断来选,不把“换个 A 记录”直接理解成无缝迁移。
证书配置完成后,还要做续期演练,并检查定时任务:
certbot renew --dry-run
systemctl status certbot.timer --no-pager
旧服务器上的定时任务正常,不能证明新服务器上的续期也正常。这一步需要在新机器重新检查。
最后验证,确认后再退掉旧机器
解析切换以后,我会先定向检查新服务器的 HTTPS:
curl --noproxy '*' \
--resolve "040012.xyz:443:$NEW_SERVER_IP" \
-I https://040012.xyz/
这里不加 -k。我需要确认的是,连接到新 IP 时,证书校验也能正常通过。
然后再用普通访问方式检查域名:
curl --noproxy '*' -I https://040012.xyz/
curl --noproxy '*' -I http://040012.xyz/
预期是 HTTPS 正常返回,HTTP 跳转到 HTTPS。浏览器里再检查首页、关于页、文章、头像、项目链接和搜索;用手机切到移动网络再访问一次,也能多验证一条实际访问链路。
观察期间,我会看一下新旧机器的访问日志。如果出问题,旧机器还在时,可以把解析改回去,但回退同样会受到 DNS 缓存影响,不是按一下保存就所有人立刻回到旧站。
确认新站稳定以后,再调整 TTL、保留必要备份,最后处理旧服务器。旧机器到期时间、新机器费用和域名续费是几件独立的事,需要分别记住。
还有一项很实际的收尾:把以后发布博客用的上传命令改成新 IP。否则网站已经搬走了,我还在往旧机器上传,写完文章线上自然不会更新。
hugo --minify && scp -r public/. "$SERVER_USER@$NEW_SERVER_IP":/var/www/html/
目前这个预案只覆盖静态博客。如果以后还在服务器上部署了 Java 项目、PostgreSQL、Redis,那些服务和数据需要另外安排迁移,不能靠上传 public 一起搬过去。
整理下来,Hugo 在这件事上的好处也更明显了:完整的源文件在,网页就能重新生成;域名和文章路径保持一致,换服务器时读者通常不需要记一个新地址。
等真正搬家时,还是按这个顺序来:先把新站准备好,再处理解析和证书,最后验证并收尾。到期之前留一点时间,会比到期以后再想办法轻松得多。
参考资料: