0
0

Halo迁移指南_云服务器到NAS

2026-08-30
2026-08-30
文章摘要
|

Halo 博客从云服务器迁移到 NAS 完整指南

本文档记录将部署在 Ubuntu 云服务器 Docker 中的 Halo 博客系统,完整迁移到 Debian NAS 的 Docker 环境中的全过程,包含遇到的实际问题和解决方法。


一、迁移前的环境情况

云服务器(源):

  • 系统:Ubuntu
  • 部署目录:/opt/halo
  • 容器构成:
    • halo(镜像 halohub/halo:2)—— Halo 博客程序本体
    • halodb(镜像 postgres:15.4)—— PostgreSQL 数据库
  • 数据库信息:数据库名 halo,用户名 halo,密码见 compose 文件中的 POSTGRES_PASSWORD
  • 数据卷:
    • ./halo2:/root/.halo2 —— 文章、配置、上传图片等程序数据
    • ./db:/var/lib/postgresql/data —— 数据库文件
  • SSH 登录方式:仅允许密钥登录,不支持密码登录(root 账号)

NAS(目标):

  • 系统:Debian
  • 已有服务:ZFile(占用 8080 端口)、Dockge、Jellyfin 等
  • 局域网 IP:192.168.1.6
  • 节点小宝虚拟网络 IP:100.66.1.2
  • 操作账号:shuke(普通用户,非 root)

⚠️ 由于 NAS 上 8080 端口已被 ZFile 占用,Halo 的端口需要改为其他端口(本次改为 8081)。


二、在云服务器上:备份数据

1. 找到部署目录,停止容器

cd /opt/halo
docker compose stop        # 停止 halo 和 halodb 两个容器
                            # 用 stop 而不是 down,避免误删数据卷

2. 重新启动数据库容器,导出数据库备份

因为 pg_dump 需要数据库处于运行状态才能连接,所以先单独把数据库启动:

docker compose up -d halodb    # 只启动数据库容器
docker ps                      # 确认 halodb 状态变为 Up ... (healthy)

导出数据库为 SQL 备份文件:

docker exec halodb pg_dump -U halo halo > /opt/halo/halo_db_backup.sql
# -U halo   : 数据库用户名
# halo      : 数据库名称(用户名和库名在这里恰好同名)
# > 后面的路径是导出文件保存位置

ls -lh /opt/halo/halo_db_backup.sql   # 检查文件是否生成、大小是否正常(不应为 0 字节)

导出完成后,重新停止数据库容器:

docker compose stop halodb

3. 打包 Halo 程序数据目录

tar -czvf halo2-data.tar.gz ./halo2
# -c 创建压缩包  -z 用gzip压缩  -v 显示过程  -f 指定文件名
# 这里只打包 halo2 目录(文章、配置、图片),不需要打包 ./db,
# 因为数据库内容已经用 pg_dump 单独导出了

ls -lh halo2-data.tar.gz   # 检查压缩包大小

此时 /opt/halo 目录下应有三个待迁移的文件:

  • docker-compose.yml
  • halo_db_backup.sql
  • halo2-data.tar.gz

三、传输文件:云服务器 → 本地电脑 → NAS

说明:云服务器有公网 IP,本地电脑可以直接访问;但云服务器访问不到 NAS 的局域网 IP(192.168.1.6),两者不在同一网络。因此不能直接从云服务器 scp 到 NAS,需要中转一次:先下载到本地电脑,再从本地电脑上传到 NAS。

1. 云服务器 SSH 只允许密钥登录

尝试用密码直接 scp 会报错:

Permission denied (publickey).

这是因为云服务器的 sshd_config 配置了仅允许密钥认证(PermitRootLogin prohibit-password),需要使用密钥文件登录,而不是密码。

2. 在本地 Windows 电脑上,用密钥从云服务器下载文件

Windows 自带 OpenSSH 客户端,直接在 PowerShell 中操作:

scp -i "C:\Users\shuke\.ssh\server-key.pem" root@云服务器公网IP:/opt/halo/docker-compose.yml .
scp -i "C:\Users\shuke\.ssh\server-key.pem" root@云服务器公网IP:/opt/halo/halo_db_backup.sql .
scp -i "C:\Users\shuke\.ssh\server-key.pem" root@云服务器公网IP:/opt/halo/halo2-data.tar.gz .
# -i 指定私钥文件路径
# 最后的 "." 表示下载到当前所在目录

如果提示 UNPROTECTED PRIVATE KEY FILE 警告,说明密钥文件权限过于开放,可执行以下命令收紧权限:

icacls "C:\Users\shuke\.ssh\server-key.pem" /inheritance:r
icacls "C:\Users\shuke\.ssh\server-key.pem" /grant:r "$($env:USERNAME):(R)"

下载完成后执行 dir 确认三个文件都已下载到本地,且大小与云服务器上一致。

3. 从本地电脑上传到 NAS

先在 NAS 上确认目标目录 /opt/halo 的所有者是 shuke(如果目录是用 root 创建的,需要先改所有权,否则上传会报 Permission denied):

# 在 NAS 上,用有权限的账号(如 root)执行:
chown -R shuke:shuke /opt/halo

然后回到本地 Windows 的 PowerShell,用 shuke 账号上传(NAS 支持密码登录,无需密钥):

scp docker-compose.yml halo_db_backup.sql halo2-data.tar.gz shuke@192.168.1.6:/opt/halo/

上传完成后,在 NAS 上执行 ls -lh /opt/halo/ 核对文件是否完整、大小是否一致。


四、在 NAS 上:恢复数据并修改配置

1. 解压 Halo 程序数据

cd /opt/halo
tar -xzvf halo2-data.tar.gz
ls   # 确认多出一个 halo2 文件夹

2. 修改 docker-compose.yml 中的两处关键配置

nano docker-compose.yml

① 修改端口映射(避免和 NAS 上已有的 ZFile 8080 端口冲突):

ports:
  - "8081:8090"     # 左边宿主机端口改成 8081;右边 8090 是容器内部端口,不要改

② 修改外部访问地址(原来写死的是云服务器的公网 IP,必须改成 NAS 实际可访问的地址):

- --halo.external-url=http://100.66.1.2:8081/
# 换成 NAS 的实际访问地址(这里用的是节点小宝虚拟网络 IP),并同步改成新端口 8081

修改完成:Ctrl + O 保存 → 回车确认文件名 → Ctrl + X 退出。

3. 启动数据库容器,导入数据库备份

先只启动数据库:

docker compose up -d halodb
docker ps    # 确认 halodb 状态为 Up ... (healthy)

导入之前从云服务器导出的数据库内容(注意要在 /opt/halo 目录下执行,不要在 halo2 子目录里,否则找不到备份文件):

cd /opt/halo
cat halo_db_backup.sql | docker exec -i halodb psql -U halo -d halo

4. 启动 Halo 本体容器

docker compose up -d halo
docker ps    # 确认 halo 状态变为 Up ... (healthy)

五、验证迁移结果

浏览器访问:

http://100.66.1.2:8081

检查以下内容是否正常:

  • [ ] 博客首页能正常打开
  • [ ] 之前发布的文章、图片都还在
  • [ ] 后台管理登录正常(用原有账号密码)

确认无误后,迁移完成。建议保留云服务器上的原始数据一段时间,作为回退方案,确认 NAS 上稳定运行一段时间后再考虑清理。


六、过程中遇到的问题与解决方法汇总

问题现象 原因 解决方法
scp 直连从云服务器到 NAS 卡住不动 云服务器(公网)访问不到 NAS 的局域网 IP,两者不在同一网络 改为「云服务器 → 本地电脑 → NAS」两段式中转
Permission denied (publickey) 云服务器 SSH 关闭了密码登录,只认密钥 使用 -i 参数指定 .pem 密钥文件登录
上传到 NAS 时 Permission denied 目标目录 /opt/halo 属主是 root,普通用户 shuke 无写入权限 chown -R shuke:shuke /opt/halo 把目录所有权交给 shuke
数据库导入时提示"没有那个文件或目录" 命令执行时所在目录不对(在 halo2 子目录里执行了引用上级目录文件的命令) cd .. 回到 /opt/halo 目录后再执行导入命令
担心 8080 端口冲突 NAS 上 ZFile 已占用 8080 把 Halo 的宿主机端口改为 8081,容器内部端口 8090 不变

七、常用维护命令(迁移完成后备用)

docker compose logs -f halo      # 实时查看 Halo 运行日志,排查问题用
docker compose restart halo      # 重启 Halo 容器
docker compose down              # 停止并移除容器(数据不会丢,在挂载目录中)
docker compose up -d             # 重新启动全部服务